Skip to content

Commit

Permalink
test: more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mdonnalley committed Aug 7, 2024
1 parent ec91ffc commit 7c7c68b
Show file tree
Hide file tree
Showing 4 changed files with 204 additions and 4 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@oclif/multi-stage-output",
"description": "Terminal output for commands with multiple stages",
"description": "Terminal output for oclif commands with multiple stages",
"version": "0.0.0",
"author": "Salesforce",
"bugs": "https://github.com/oclif/multi-stage-output/issues",
Expand Down
4 changes: 2 additions & 2 deletions src/components/multi-stage-output.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ type StageInfoBlock<T extends Record<string, unknown>> = Array<
(KeyValuePair<T> & {stage: string}) | (SimpleMessage<T> & {stage: string})
>

type FormattedKeyValue = {
export type FormattedKeyValue = {
readonly color?: string
readonly isBold?: boolean
// eslint-disable-next-line react/no-unused-prop-types
Expand Down Expand Up @@ -198,7 +198,7 @@ function Infos({
)
}

function Stages({
export function Stages({
error,
hasElapsedTime = true,
hasStageTime = true,
Expand Down
1 change: 0 additions & 1 deletion test/components/multi-stage-output.test.ts

This file was deleted.

201 changes: 201 additions & 0 deletions test/components/multi-stage-output.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
import {config, expect} from 'chai'
import {render} from 'ink-testing-library'
import React from 'react'
import stripAnsi from 'strip-ansi'

import {FormattedKeyValue, Stages} from '../../src/components/multi-stage-output.js'
import {StageTracker} from '../../src/stage-tracker.js'

config.truncateThreshold = 0

function lastValidFrame(frames: string[]): string {
for (let i = frames.length - 1; i >= 0; i--) {
if (frames[i] !== '\n') return stripAnsi(frames[i])
}

return ''
}

describe('Stages', () => {
it('should render pending stages', async () => {
const stageTracker = new StageTracker(['step1', 'step2'])
const {frames, unmount} = render(<Stages stageTracker={stageTracker} title="Test" />)
unmount()
const lastFrame = lastValidFrame(frames)
expect(lastFrame).to.include('─ Test ─')
expect(lastFrame).to.include('◼ Step1')
expect(lastFrame).to.include('◼ Step2')
expect(lastFrame).to.include('Elapsed Time:')
})

it('should render completed stages', async () => {
const stageTracker = new StageTracker(['step1', 'step2'])
stageTracker.set('step1', 'completed')
const {frames, unmount} = render(<Stages stageTracker={stageTracker} title="Test" />)
unmount()
const lastFrame = lastValidFrame(frames)
expect(lastFrame).to.include('─ Test ─')
expect(lastFrame).to.include('✔ Step1')
expect(lastFrame).to.include('◼ Step2')
expect(lastFrame).to.include('Elapsed Time:')
})

it('should render skipped stages', async () => {
const stageTracker = new StageTracker(['step1', 'step2'])
stageTracker.set('step1', 'skipped')
stageTracker.set('step2', 'completed')
const {frames, unmount} = render(<Stages stageTracker={stageTracker} title="Test" />)
unmount()
const lastFrame = lastValidFrame(frames)
expect(lastFrame).to.include('─ Test ─')
expect(lastFrame).to.include('◯ Step1 - Skipped')
expect(lastFrame).to.include('✔ Step2')
expect(lastFrame).to.include('Elapsed Time:')
})

it('should render failed stages', async () => {
const stageTracker = new StageTracker(['step1', 'step2'])
stageTracker.set('step1', 'failed')
const {frames, unmount} = render(<Stages stageTracker={stageTracker} title="Test" error={new Error('oops')} />)
unmount()
const lastFrame = lastValidFrame(frames)
expect(lastFrame).to.include('─ Test ─')
expect(lastFrame).to.include('✘ Step1')
expect(lastFrame).to.include('◼ Step2')
expect(lastFrame).to.include('Elapsed Time:')
})

it('should disable elapsed time', async () => {
const stageTracker = new StageTracker(['step1', 'step2'])
const {frames, unmount} = render(<Stages stageTracker={stageTracker} title="Test" hasElapsedTime={false} />)
unmount()
const lastFrame = lastValidFrame(frames)
expect(lastFrame).to.include('─ Test ─')
expect(lastFrame).to.include('◼ Step1')
expect(lastFrame).to.include('◼ Step2')
expect(lastFrame).to.not.include('Elapsed Time:')
})

it('should enable stage time', async () => {
const stageTracker = new StageTracker(['step1', 'step2'])
stageTracker.set('step1', 'completed')
const {frames, unmount} = render(<Stages hasStageTime stageTracker={stageTracker} title="Test" />)
unmount()
const lastFrame = lastValidFrame(frames)
expect(lastFrame).to.include('─ Test ─')
expect(lastFrame).to.include('✔ Step1 0ms')
expect(lastFrame).to.include('◼ Step2\n')
expect(lastFrame).to.include('Elapsed Time:')
})

it('should disable stage time', async () => {
const stageTracker = new StageTracker(['step1', 'step2'])
stageTracker.set('step1', 'completed')
const {frames, unmount} = render(<Stages stageTracker={stageTracker} title="Test" hasStageTime={false} />)
unmount()
const lastFrame = lastValidFrame(frames)
expect(lastFrame).to.include('─ Test ─')
expect(lastFrame).to.include('✔ Step1\n')
expect(lastFrame).to.include('◼ Step2\n')
expect(lastFrame).to.include('Elapsed Time:')
})

it('should show pre-stage info block', async () => {
const stageTracker = new StageTracker(['step1', 'step2'])

const preStagesBlock: FormattedKeyValue[] = [
{
type: 'message',
value: 'this is a message',
},
{
label: 'Static',
type: 'static-key-value',
value: 'this is a static key:value pair',
},
{
label: 'Dynamic',
type: 'dynamic-key-value',
value: 'this is a dynamic key:value pair',
},
]

const {frames, unmount} = render(
<Stages stageTracker={stageTracker} title="Test" preStagesBlock={preStagesBlock} />,
)
unmount()
const lastFrame = lastValidFrame(frames)
expect(lastFrame).to.include(` this is a message
Static: this is a static key:value pair
Dynamic: this is a dynamic key:value pair
◼ Step1
`)
})

it('should show post-stage info block', async () => {
const stageTracker = new StageTracker(['step1', 'step2'])

const postStagesBlock: FormattedKeyValue[] = [
{
type: 'message',
value: 'this is a message',
},
{
label: 'Static',
type: 'static-key-value',
value: 'this is a static key:value pair',
},
{
label: 'Dynamic',
type: 'dynamic-key-value',
value: 'this is a dynamic key:value pair',
},
]

const {frames, unmount} = render(
<Stages stageTracker={stageTracker} title="Test" postStagesBlock={postStagesBlock} />,
)
unmount()
const lastFrame = lastValidFrame(frames)
expect(lastFrame).to.include(` ◼ Step2
this is a message
Static: this is a static key:value pair
Dynamic: this is a dynamic key:value pair`)
})

it('should show stage specific info block', async () => {
const stageTracker = new StageTracker(['step1', 'step2'])
stageTracker.set('step1', 'completed')
const stageSpecificBlock: FormattedKeyValue[] = [
{
stage: 'step1',
type: 'message',
value: 'this is a message',
},
{
label: 'Static',
stage: 'step1',
type: 'static-key-value',
value: 'this is a static key:value pair',
},
{
label: 'Dynamic',
stage: 'step1',
type: 'dynamic-key-value',
value: 'this is a dynamic key:value pair',
},
]

const {frames, unmount} = render(
<Stages stageTracker={stageTracker} title="Test" stageSpecificBlock={stageSpecificBlock} />,
)
unmount()
const lastFrame = lastValidFrame(frames)
expect(lastFrame).to.include(` ✔ Step1 0ms
this is a message
Static: this is a static key:value pair
Dynamic: this is a dynamic key:value pair`)
})
})

0 comments on commit 7c7c68b

Please sign in to comment.