diff --git a/package.json b/package.json index 1666382f..7481e2e5 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "format": "biome check --write", "lint": "biome lint --write --unsafe", "type-check": "biome lint && tsc", - "test": "pnpm -r run test", + "test": "pnpm --color -r run test", "ci:version": "changeset version && pnpm install --no-frozen-lockfile", "ci:publish": "changeset publish" }, diff --git a/packages/prompts/src/__snapshots__/index.test.ts.snap b/packages/prompts/src/__snapshots__/index.test.ts.snap index 9b51db39..c45f71ef 100644 --- a/packages/prompts/src/__snapshots__/index.test.ts.snap +++ b/packages/prompts/src/__snapshots__/index.test.ts.snap @@ -1,6 +1,6 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`spinner > message > sets message for next frame 1`] = ` +exports[`isCI = false > spinner > message > sets message for next frame 1`] = ` [ "[?25l", "│ @@ -12,7 +12,7 @@ exports[`spinner > message > sets message for next frame 1`] = ` ] `; -exports[`spinner > start > renders frames at interval 1`] = ` +exports[`isCI = false > spinner > start > renders frames at interval 1`] = ` [ "[?25l", "│ @@ -30,7 +30,7 @@ exports[`spinner > start > renders frames at interval 1`] = ` ] `; -exports[`spinner > start > renders message 1`] = ` +exports[`isCI = false > spinner > start > renders message 1`] = ` [ "[?25l", "│ @@ -39,7 +39,7 @@ exports[`spinner > start > renders message 1`] = ` ] `; -exports[`spinner > start > renders timer when indicator is "timer" 1`] = ` +exports[`isCI = false > spinner > start > renders timer when indicator is "timer" 1`] = ` [ "[?25l", "│ @@ -48,7 +48,7 @@ exports[`spinner > start > renders timer when indicator is "timer" 1`] = ` ] `; -exports[`spinner > stop > renders cancel symbol if code = 1 1`] = ` +exports[`isCI = false > spinner > stop > renders cancel symbol if code = 1 1`] = ` [ "[?25l", "│ @@ -62,7 +62,7 @@ exports[`spinner > stop > renders cancel symbol if code = 1 1`] = ` ] `; -exports[`spinner > stop > renders error symbol if code > 1 1`] = ` +exports[`isCI = false > spinner > stop > renders error symbol if code > 1 1`] = ` [ "[?25l", "│ @@ -76,7 +76,7 @@ exports[`spinner > stop > renders error symbol if code > 1 1`] = ` ] `; -exports[`spinner > stop > renders message 1`] = ` +exports[`isCI = false > spinner > stop > renders message 1`] = ` [ "[?25l", "│ @@ -90,7 +90,7 @@ exports[`spinner > stop > renders message 1`] = ` ] `; -exports[`spinner > stop > renders submit symbol and stops spinner 1`] = ` +exports[`isCI = false > spinner > stop > renders submit symbol and stops spinner 1`] = ` [ "[?25l", "│ @@ -103,3 +103,108 @@ exports[`spinner > stop > renders submit symbol and stops spinner 1`] = ` "[?25h", ] `; + +exports[`isCI = true > spinner > message > sets message for next frame 1`] = ` +[ + "[?25l", + "│ +", + "◒ ...", + " +", + "", + "", + "◐ foo...", +] +`; + +exports[`isCI = true > spinner > start > renders frames at interval 1`] = ` +[ + "[?25l", + "│ +", + "◒ ...", +] +`; + +exports[`isCI = true > spinner > start > renders message 1`] = ` +[ + "[?25l", + "│ +", + "◒ foo...", +] +`; + +exports[`isCI = true > spinner > start > renders timer when indicator is "timer" 1`] = ` +[ + "[?25l", + "│ +", + "◒ ...", +] +`; + +exports[`isCI = true > spinner > stop > renders cancel symbol if code = 1 1`] = ` +[ + "[?25l", + "│ +", + "◒ ...", + " +", + "", + "", + "■ +", + "[?25h", +] +`; + +exports[`isCI = true > spinner > stop > renders error symbol if code > 1 1`] = ` +[ + "[?25l", + "│ +", + "◒ ...", + " +", + "", + "", + "▲ +", + "[?25h", +] +`; + +exports[`isCI = true > spinner > stop > renders message 1`] = ` +[ + "[?25l", + "│ +", + "◒ ...", + " +", + "", + "", + "◇ foo +", + "[?25h", +] +`; + +exports[`isCI = true > spinner > stop > renders submit symbol and stops spinner 1`] = ` +[ + "[?25l", + "│ +", + "◒ ...", + " +", + "", + "", + "◇ +", + "[?25h", +] +`; diff --git a/packages/prompts/src/index.test.ts b/packages/prompts/src/index.test.ts index 93eb43d7..64f5c571 100644 --- a/packages/prompts/src/index.test.ts +++ b/packages/prompts/src/index.test.ts @@ -1,5 +1,5 @@ import { Writable } from 'node:stream'; -import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'; +import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, test, vi } from 'vitest'; import * as prompts from './index.js'; // TODO (43081j): move this into a util? @@ -16,127 +16,140 @@ class MockWritable extends Writable { } } -describe('spinner', () => { - let output: MockWritable; +describe.each(['true', 'false'])('isCI = %s', (isCI) => { + let originalCI: string | undefined; - beforeEach(() => { - vi.useFakeTimers(); - output = new MockWritable(); + beforeAll(() => { + originalCI = process.env.CI; + process.env.CI = isCI; }); - afterEach(() => { - vi.restoreAllMocks(); - vi.useRealTimers(); + afterAll(() => { + process.env.CI = originalCI; }); - test('returns spinner API', () => { - const api = prompts.spinner({ output }); + describe('spinner', () => { + let output: MockWritable; - expect(api.stop).toBeTypeOf('function'); - expect(api.start).toBeTypeOf('function'); - expect(api.message).toBeTypeOf('function'); - }); - - describe('start', () => { - test('renders frames at interval', () => { - const result = prompts.spinner({ output }); + beforeEach(() => { + vi.useFakeTimers(); + output = new MockWritable(); + }); - result.start(); + afterEach(() => { + vi.restoreAllMocks(); + vi.useRealTimers(); + }); - // there are 4 frames - for (let i = 0; i < 4; i++) { - vi.advanceTimersByTime(80); - } + test('returns spinner API', () => { + const api = prompts.spinner({ output }); - expect(output.buffer).toMatchSnapshot(); + expect(api.stop).toBeTypeOf('function'); + expect(api.start).toBeTypeOf('function'); + expect(api.message).toBeTypeOf('function'); }); - test('renders message', () => { - const result = prompts.spinner({ output }); + describe('start', () => { + test('renders frames at interval', () => { + const result = prompts.spinner({ output }); - result.start('foo'); + result.start(); - vi.advanceTimersByTime(80); + // there are 4 frames + for (let i = 0; i < 4; i++) { + vi.advanceTimersByTime(80); + } - expect(output.buffer).toMatchSnapshot(); - }); + expect(output.buffer).toMatchSnapshot(); + }); - test('renders timer when indicator is "timer"', () => { - const result = prompts.spinner({ output, indicator: 'timer' }); + test('renders message', () => { + const result = prompts.spinner({ output }); - result.start(); + result.start('foo'); - vi.advanceTimersByTime(80); + vi.advanceTimersByTime(80); + + expect(output.buffer).toMatchSnapshot(); + }); + + test('renders timer when indicator is "timer"', () => { + const result = prompts.spinner({ output, indicator: 'timer' }); + + result.start(); + + vi.advanceTimersByTime(80); - expect(output.buffer).toMatchSnapshot(); + expect(output.buffer).toMatchSnapshot(); + }); }); - }); - describe('stop', () => { - test('renders submit symbol and stops spinner', () => { - const result = prompts.spinner({ output }); + describe('stop', () => { + test('renders submit symbol and stops spinner', () => { + const result = prompts.spinner({ output }); - result.start(); + result.start(); - vi.advanceTimersByTime(80); + vi.advanceTimersByTime(80); - result.stop(); + result.stop(); - vi.advanceTimersByTime(80); + vi.advanceTimersByTime(80); - expect(output.buffer).toMatchSnapshot(); - }); + expect(output.buffer).toMatchSnapshot(); + }); - test('renders cancel symbol if code = 1', () => { - const result = prompts.spinner({ output }); + test('renders cancel symbol if code = 1', () => { + const result = prompts.spinner({ output }); - result.start(); + result.start(); - vi.advanceTimersByTime(80); + vi.advanceTimersByTime(80); - result.stop('', 1); + result.stop('', 1); - expect(output.buffer).toMatchSnapshot(); - }); + expect(output.buffer).toMatchSnapshot(); + }); - test('renders error symbol if code > 1', () => { - const result = prompts.spinner({ output }); + test('renders error symbol if code > 1', () => { + const result = prompts.spinner({ output }); - result.start(); + result.start(); - vi.advanceTimersByTime(80); + vi.advanceTimersByTime(80); - result.stop('', 2); + result.stop('', 2); - expect(output.buffer).toMatchSnapshot(); - }); + expect(output.buffer).toMatchSnapshot(); + }); - test('renders message', () => { - const result = prompts.spinner({ output }); + test('renders message', () => { + const result = prompts.spinner({ output }); - result.start(); + result.start(); - vi.advanceTimersByTime(80); + vi.advanceTimersByTime(80); - result.stop('foo'); + result.stop('foo'); - expect(output.buffer).toMatchSnapshot(); + expect(output.buffer).toMatchSnapshot(); + }); }); - }); - describe('message', () => { - test('sets message for next frame', () => { - const result = prompts.spinner({ output }); + describe('message', () => { + test('sets message for next frame', () => { + const result = prompts.spinner({ output }); - result.start(); + result.start(); - vi.advanceTimersByTime(80); + vi.advanceTimersByTime(80); - result.message('foo'); + result.message('foo'); - vi.advanceTimersByTime(80); + vi.advanceTimersByTime(80); - expect(output.buffer).toMatchSnapshot(); + expect(output.buffer).toMatchSnapshot(); + }); }); }); });