Skip to content

Commit

Permalink
test: lots of tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mdonnalley committed Aug 7, 2024
1 parent 04082df commit ec91ffc
Show file tree
Hide file tree
Showing 22 changed files with 620 additions and 1,525 deletions.
2 changes: 1 addition & 1 deletion .mocharc.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"reporter": "spec",
"require": ["ts-node/register"],
"timeout": 60000,
"watch-extensions": ["ts"],
"watch-extensions": ["ts", "tsx"],
"watch-files": ["src", "test"],
"watch-ignore": ["test/tmp"],
"node-option": ["loader=ts-node/esm"]
Expand Down
26 changes: 26 additions & 0 deletions examples/basic.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import {MultiStageOutput} from '../src/components/multi-stage-output.js'

const SLEEP_TIME = Number.parseInt(process.env.SLEEP ?? '100', 10) ?? 100

async function sleep(ms: number): Promise<void> {
return new Promise((resolve) => {
setTimeout(resolve, ms)
})
}

const ms = new MultiStageOutput({
jsonEnabled: false,
stages: ['one', 'two', 'three'],
title: 'Example',
})

ms.goto('one')
await sleep(SLEEP_TIME)

ms.goto('two')
await sleep(SLEEP_TIME)

ms.goto('three')
await sleep(SLEEP_TIME)

ms.stop()
23 changes: 23 additions & 0 deletions examples/error.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import {MultiStageOutput} from '../src/components/multi-stage-output.js'

const SLEEP_TIME = Number.parseInt(process.env.SLEEP ?? '100', 10) ?? 100

async function sleep(ms: number): Promise<void> {
return new Promise((resolve) => {
setTimeout(resolve, ms)
})
}

const ms = new MultiStageOutput({
jsonEnabled: false,
stages: ['one', 'two', 'three'],
title: 'Example',
})

ms.goto('one')
await sleep(SLEEP_TIME)

ms.goto('two')
await sleep(SLEEP_TIME)

ms.stop(new Error('An error occurred'))
42 changes: 42 additions & 0 deletions examples/post-stage-block.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import {MultiStageOutput} from '../src/components/multi-stage-output.js'

const SLEEP_TIME = Number.parseInt(process.env.SLEEP ?? '100', 10) ?? 100

async function sleep(ms: number): Promise<void> {
return new Promise((resolve) => {
setTimeout(resolve, ms)
})
}

const ms = new MultiStageOutput<{message: string; staticValue: string; dynamicValue: string}>({
jsonEnabled: false,
postStagesBlock: [
{
get: (data) => data?.message,
type: 'message',
},
{
get: (data) => data?.staticValue,
label: 'Static',
type: 'static-key-value',
},
{
get: (data) => data?.dynamicValue,
label: 'Dynamic',
type: 'dynamic-key-value',
},
],
stages: ['one', 'two', 'three'],
title: 'Example',
})

ms.goto('one', {message: 'This is a message', staticValue: 'This is a static key:value pair'})
await sleep(SLEEP_TIME)

ms.goto('two', {dynamicValue: 'This is a dynamic key:value pair'})
await sleep(SLEEP_TIME)

ms.goto('three')
await sleep(SLEEP_TIME)

ms.stop()
42 changes: 42 additions & 0 deletions examples/pre-stage-block.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import {MultiStageOutput} from '../src/components/multi-stage-output.js'

const SLEEP_TIME = Number.parseInt(process.env.SLEEP ?? '100', 10) ?? 100

async function sleep(ms: number): Promise<void> {
return new Promise((resolve) => {
setTimeout(resolve, ms)
})
}

const ms = new MultiStageOutput<{message: string; staticValue: string; dynamicValue: string}>({
jsonEnabled: false,
preStagesBlock: [
{
get: (data) => data?.message,
type: 'message',
},
{
get: (data) => data?.staticValue,
label: 'Static',
type: 'static-key-value',
},
{
get: (data) => data?.dynamicValue,
label: 'Dynamic',
type: 'dynamic-key-value',
},
],
stages: ['one', 'two', 'three'],
title: 'Example',
})

ms.goto('one', {message: 'This is a message', staticValue: 'This is a static key:value pair'})
await sleep(SLEEP_TIME)

ms.goto('two', {dynamicValue: 'This is a dynamic key:value pair'})
await sleep(SLEEP_TIME)

ms.goto('three')
await sleep(SLEEP_TIME)

ms.stop()
23 changes: 23 additions & 0 deletions examples/skip.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import {MultiStageOutput} from '../src/components/multi-stage-output.js'

const SLEEP_TIME = Number.parseInt(process.env.SLEEP ?? '100', 10) ?? 100

async function sleep(ms: number): Promise<void> {
return new Promise((resolve) => {
setTimeout(resolve, ms)
})
}

const ms = new MultiStageOutput({
jsonEnabled: false,
stages: ['one', 'two', 'three'],
title: 'Example',
})

ms.goto('one')
await sleep(SLEEP_TIME)

ms.goto('three')
await sleep(SLEEP_TIME)

ms.stop()
45 changes: 45 additions & 0 deletions examples/stage-specific-block.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import {MultiStageOutput} from '../src/components/multi-stage-output.js'

const SLEEP_TIME = Number.parseInt(process.env.SLEEP ?? '100', 10) ?? 100

async function sleep(ms: number): Promise<void> {
return new Promise((resolve) => {
setTimeout(resolve, ms)
})
}

const ms = new MultiStageOutput<{message: string; staticValue: string; dynamicValue: string}>({
jsonEnabled: false,
stageSpecificBlock: [
{
get: (data) => data?.message,
stage: 'one',
type: 'message',
},
{
get: (data) => data?.staticValue,
label: 'Static',
stage: 'two',
type: 'static-key-value',
},
{
get: (data) => data?.dynamicValue,
label: 'Dynamic',
stage: 'one',
type: 'dynamic-key-value',
},
],
stages: ['one', 'two', 'three'],
title: 'Example',
})

ms.goto('one', {message: 'This is a message', staticValue: 'This is a static key:value pair'})
await sleep(SLEEP_TIME)

ms.goto('two', {dynamicValue: 'This is a dynamic key:value pair'})
await sleep(SLEEP_TIME)

ms.goto('three')
await sleep(SLEEP_TIME)

ms.stop()
9 changes: 4 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@
"eslint-plugin-react": "^7.34.3",
"eslint-plugin-react-hooks": "^4.6.2",
"husky": "^9.1.3",
"ink-testing-library": "^4.0.0",
"lint-staged": "^15",
"madge": "^6.1.0",
"mocha": "^10.7.0",
"nyc": "^15.1.0",
"prettier": "^3.3.3",
"shx": "^0.3.4",
"sinon": "^18",
"strip-ansi": "^7.1.0",
"ts-node": "^10.9.2",
"typescript": "^5"
},
Expand Down Expand Up @@ -67,11 +67,10 @@
"compile": "tsc",
"format": "prettier --write \"+(src|test)/**/*.+(ts|js|json)\"",
"lint": "eslint . --ext .ts",
"posttest": "yarn lint && yarn test:circular-deps",
"posttest": "yarn lint",
"prepack": "yarn run build",
"prepare": "husky",
"test:circular-deps": "yarn build && madge lib/ -c",
"test": "nyc mocha --forbid-only \"test/**/*.test.ts\" --parallel"
"test": "mocha --forbid-only \"test/**/*.test.+(ts|tsx)\" --parallel"
},
"types": "lib/index.d.ts",
"type": "module"
Expand Down
29 changes: 16 additions & 13 deletions src/components/multi-stage-output.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import {Box, Instance, Text, render} from 'ink'
import {env} from 'node:process'
import React from 'react'

import {icons, spinners} from './design-elements.js'
import {icons, spinners} from '../design-elements.js'
import {StageTracker} from '../stage-tracker.js'
import {readableTime} from '../utils.js'
import {Divider} from './divider.js'
import {SpinnerOrError, SpinnerOrErrorOrChildren} from './spinner.js'
import {StageTracker} from './stage-tracker.js'
import {Timer} from './timer.js'
import {msInMostReadableFormat, secondsInMostReadableFormat} from './utils.js'

// Taken from https://github.com/sindresorhus/is-in-ci
const isInCi =
Expand Down Expand Up @@ -114,6 +114,10 @@ type MultiStageComponentOptions<T extends Record<string, unknown>> = {
* Pass in this.jsonEnabled() from the command class to determine if JSON output is enabled.
*/
readonly jsonEnabled: boolean
/**
* Whether to override the CI detection and force the component to render as if it's in a CI environment.
*/
readonly isInCiOverride?: boolean
}

type StagesProps = {
Expand Down Expand Up @@ -288,7 +292,7 @@ class CIMultiStageOutput<T extends Record<string, unknown>> {
private readonly stageSpecificBlock?: StageInfoBlock<T>
private startTime: number | undefined
private startTimes: Map<string, number> = new Map()
private readonly timerUnit?: 'ms' | 's'
private readonly timerUnit: 'ms' | 's'
private readonly title: string

public constructor({
Expand Down Expand Up @@ -331,8 +335,7 @@ class CIMultiStageOutput<T extends Record<string, unknown>> {
if (this.startTime) {
const elapsedTime = Date.now() - this.startTime
ux.stdout()
const displayTime =
this.timerUnit === 'ms' ? msInMostReadableFormat(elapsedTime) : secondsInMostReadableFormat(elapsedTime, 0)
const displayTime = readableTime(elapsedTime, this.timerUnit)
ux.stdout(`Elapsed time: ${displayTime}`)
ux.stdout()
}
Expand Down Expand Up @@ -375,10 +378,7 @@ class CIMultiStageOutput<T extends Record<string, unknown>> {
if (this.hasStageTime && status !== 'skipped') {
const startTime = this.startTimes.get(stage)
const elapsedTime = startTime ? Date.now() - startTime : 0
const displayTime =
this.timerUnit === 'ms'
? msInMostReadableFormat(elapsedTime)
: secondsInMostReadableFormat(elapsedTime, 0)
const displayTime = readableTime(elapsedTime, this.timerUnit)
ux.stdout(`${icons[status]} ${capitalCase(stage)} (${displayTime})`)
this.printInfo(this.preStagesBlock, 3)
this.printInfo(
Expand Down Expand Up @@ -430,6 +430,7 @@ export class MultiStageOutput<T extends Record<string, unknown>> implements Disp
private readonly hasStageTime?: boolean
private inkInstance: Instance | undefined

private readonly isInCi: boolean
private readonly postStagesBlock?: InfoBlock<T>
private readonly preStagesBlock?: InfoBlock<T>
private readonly stages: readonly string[] | string[]
Expand All @@ -441,6 +442,7 @@ export class MultiStageOutput<T extends Record<string, unknown>> implements Disp

public constructor({
data,
isInCiOverride,
jsonEnabled,
postStagesBlock,
preStagesBlock,
Expand All @@ -461,10 +463,11 @@ export class MultiStageOutput<T extends Record<string, unknown>> implements Disp
this.timerUnit = timerUnit ?? 'ms'
this.stageTracker = new StageTracker(stages)
this.stageSpecificBlock = stageSpecificBlock
this.isInCi = isInCiOverride ?? isInCi

if (jsonEnabled) return

if (isInCi) {
if (this.isInCi) {
this.ciInstance = new CIMultiStageOutput({
data,
jsonEnabled,
Expand Down Expand Up @@ -520,7 +523,7 @@ export class MultiStageOutput<T extends Record<string, unknown>> implements Disp

this.stageTracker.refresh(this.stageTracker.current ?? this.stages[0], {hasError: Boolean(error), isStopping: true})

if (isInCi) {
if (this.isInCi) {
this.ciInstance?.stop(this.stageTracker)
return
}
Expand Down Expand Up @@ -589,7 +592,7 @@ export class MultiStageOutput<T extends Record<string, unknown>> implements Disp

this.stageTracker.refresh(stage)

if (isInCi) {
if (this.isInCi) {
this.ciInstance?.update(this.stageTracker, this.data)
} else {
this.inkInstance?.rerender(
Expand Down
Loading

0 comments on commit ec91ffc

Please sign in to comment.