diff --git a/src/setup.js b/src/setup.js index 56ba6c5..76e4ad2 100644 --- a/src/setup.js +++ b/src/setup.js @@ -19,6 +19,52 @@ import { commandExists } from "./utils/shell.js"; import { isZshShell } from "./utils/shell-context.js"; export { isZshShell } from "./utils/shell-context.js"; +export const SUITUP_PIXEL_LOGO = [ + "gddwwddwwddg", + "gddwwwwwwddg", + "ggdwwdwwddgg", + "ggdwwrwwddgg", + "ggdwrwrwddgg", + "ggdwwrwwddgg", + "ggdwrwrwddgg", + "gggdwwrwddgg", + "gggdwrpppwgg", + "gggdrrpppwgs", + "gggddrpppwgg", +]; + +function colorize256(code, text) { + return `\x1b[38;5;${code}m${text}\x1b[0m`; +} + +function renderPixel(pixel) { + switch (pixel) { + case "g": + return colorize256(245, "██"); + case "d": + return colorize256(236, "██"); + case "w": + return colorize256(255, "██"); + case "r": + return colorize256(202, "██"); + case "p": + return colorize256(224, "██"); + case "s": + return colorize256(255, "● "); + default: + return " "; + } +} + +export function getWelcomeLogo() { + const renderRow = (row) => [...row].map(renderPixel).join(""); + return SUITUP_PIXEL_LOGO.map(renderRow).join("\n"); +} + +export function getWelcomeMessage() { + return `${getWelcomeLogo()}\n${pc.bgCyan(pc.black(" Suit up! "))}`; +} + export function getRecommendedCliToolValues() { return [...CLI_TOOLS.essentials, ...CLI_TOOLS.shell].map((tool) => tool.value); } @@ -126,7 +172,7 @@ export function getInitialStepValues(opts = {}) { } export async function runSetup({ defaults = false } = {}) { - p.intro(pc.bgCyan(pc.black(" Suit up! "))); + p.intro(getWelcomeMessage()); if (!isZshShell()) { p.log.error("Suitup setup must be run from zsh."); diff --git a/tests/setup.test.js b/tests/setup.test.js index 9583d4c..8e52e6d 100644 --- a/tests/setup.test.js +++ b/tests/setup.test.js @@ -17,10 +17,14 @@ import { getInitialStepValues, getRecommendedAppValues, getRecommendedCliToolValues, + getWelcomeLogo, + getWelcomeMessage, + SUITUP_PIXEL_LOGO, isZshShell, } from "../src/setup.js"; const CONFIGS_DIR = join(import.meta.dirname, "..", "configs"); +const ANSI_COLOR_CODE_PATTERN = /\u001b\[[0-9;]*m/g; describe("Setup simulation in sandbox", () => { let sandbox; @@ -163,6 +167,59 @@ describe("Setup simulation in sandbox", () => { ]); }); + test("pixel-art welcome logo uses the expected template", () => { + expect(SUITUP_PIXEL_LOGO).toMatchInlineSnapshot(` + [ + "gddwwddwwddg", + "gddwwwwwwddg", + "ggdwwdwwddgg", + "ggdwwrwwddgg", + "ggdwrwrwddgg", + "ggdwwrwwddgg", + "ggdwrwrwddgg", + "gggdwwrwddgg", + "gggdwrpppwgg", + "gggdrrpppwgs", + "gggddrpppwgg", + ] + `); + }); + + test("pixel-art welcome logo renders colored blocks and the status dot", () => { + const logo = getWelcomeLogo(); + const expectedPixels = [ + "\u001b[38;5;245m██\u001b[0m", + "\u001b[38;5;236m██\u001b[0m", + "\u001b[38;5;255m██\u001b[0m", + "\u001b[38;5;202m██\u001b[0m", + "\u001b[38;5;224m██\u001b[0m", + "\u001b[38;5;255m● \u001b[0m", + ]; + + expect(logo.replace(ANSI_COLOR_CODE_PATTERN, "")).toMatchInlineSnapshot(` + "████████████████████████ + ████████████████████████ + ████████████████████████ + ████████████████████████ + ████████████████████████ + ████████████████████████ + ████████████████████████ + ████████████████████████ + ████████████████████████ + ██████████████████████● + ████████████████████████" + `); + + for (const pixel of expectedPixels) { + expect(logo).toContain(pixel); + } + }); + + test("welcome message displays the suit up badge below the logo", () => { + const message = getWelcomeMessage(); + expect(message).toContain("Suit up!"); + }); + test("detects completed suitup-managed setup steps", () => { mkdirSync(join(sandbox, ".config", "zsh", "core"), { recursive: true }); mkdirSync(join(sandbox, ".config", "zsh", "shared"), { recursive: true });