Skip to content

Commit

Permalink
test(jest): 馃毃 added cli mock for jest
Browse files Browse the repository at this point in the history
  • Loading branch information
folke committed Jan 14, 2020
1 parent 08a5793 commit 035a320
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 0 deletions.
48 changes: 48 additions & 0 deletions packages/devmoji/__tests__/cli-tester.ts
@@ -0,0 +1,48 @@
import { MockCli } from "../src/cli-tester"

test("sync", () => {
const mockCli = new MockCli()
mockCli.test(() => {
console.log("test")
})
expect(mockCli.stdout?.data).toMatch(/test/)
})

test("stderr", () => {
const mockCli = new MockCli()
mockCli.test(() => {
console.error("test")
})
expect(mockCli.stderr?.data).toMatch(/test/)
})

test("sync2", () => {
const mockCli = new MockCli()
mockCli.test(() => {
console.log("test")
})
expect(mockCli.stdout?.data).toMatch(/test/)
})

test("async1", () => {
const mockCli = new MockCli()
mockCli.testAsync(async () => {
await new Promise(done => {
process.stdout.write("test")
done()
})
})
expect(mockCli.stdout?.data).toMatch(/test/)
})

test("async2", () => {
const mockCli = new MockCli()
mockCli.testAsync(async () => {
console.log("foo")
await new Promise(done => {
console.log("test")
done()
})
})
expect(mockCli.stdout?.data).toMatch(/foo/)
})
74 changes: 74 additions & 0 deletions packages/devmoji/src/cli-tester.ts
@@ -0,0 +1,74 @@
import { Writable, WritableOptions } from "stream"
import { StringDecoder } from "string_decoder"
import { Console } from "console"

class StringWritable extends Writable {
data = ""
decoder: StringDecoder
constructor(options?: WritableOptions) {
super(options)
this.decoder = new StringDecoder("utf-8")
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
_write(chunk: any, encoding: string, callback: () => void) {
this.data += this.decoder.write(chunk)
callback()
}

_destroy(err: Error, callback: () => void) {
this.data += this.decoder.end()
callback()
}
}

export class MockCli {
mocks: [Writable, Writable, Writable["write"]][] = []
stdout?: StringWritable
stderr?: StringWritable
console = global.console
// eslint-disable-next-line @typescript-eslint/unbound-method

mock(stream: Writable) {
const mock = new StringWritable()
// eslint-disable-next-line @typescript-eslint/unbound-method
this.mocks.push([mock, stream, stream.write])
// eslint-disable-next-line @typescript-eslint/unbound-method
stream.write = mock.write.bind(mock)
return mock
}

restore() {
for (const [mock, stream, write] of this.mocks) {
mock.destroy()
// eslint-disable-next-line @typescript-eslint/unbound-method
stream.write = write.bind(stream)
}
global.console = this.console
}

setup() {
this.stdout = this.mock(global.process.stdout)
this.stderr = this.mock(global.process.stderr)
this.console = global.console
global.console = new Console({ stdout: this.stdout, stderr: this.stderr })
}

test(func: () => void) {
try {
this.setup()
func()
} finally {
this.restore()
}
}

async testAsync<T>(func: () => Promise<T>) {
this.setup()
try {
await func()
} finally {
this.restore()
}
}
}

0 comments on commit 035a320

Please sign in to comment.