Skip to content

Commit

Permalink
feat: added promptModule test helper
Browse files Browse the repository at this point in the history
  • Loading branch information
wesleytodd committed Jan 3, 2024
1 parent 27e4ed5 commit 1ed108f
Show file tree
Hide file tree
Showing 5 changed files with 290 additions and 87 deletions.
57 changes: 57 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,60 @@ await myOpts.prompt()
const vals = myOpts.values()
console.log(vals) // all options from both Project and My Project
```

## Prompt Testing

Testing user input can be difficult. This package exports a test helper which can mimic different behaviors of users interacting
with prompts without dealing with the complicated work to actually handle user input. Here is an example:

```javascript
const test = require('node:test');
const assert = require('node:assert')
const opta = require('opta')
const optaUtils = require('opta/utils')

test('some test', async (t) => {
const opts = opta({
options: {
foo: true,
bar: true
},
// Create a promptModule mock
promptModule: optaUtils.test.promptModule({
// Will assert that two prompts were displayed
assertCount: 2,
prompts: {
foo: {
// Set a value as if it was user input
value: 'foo',

// Assert some things about the prompt config
// which is passed on to inquirer
assert: (p) =>{
assert.strictEqual(p.name, 'foo')
assert.strictEqual(p.message, 'foo:')
assert.strictEqual(p.type, 'input')
assert.strictEqual(p.when, true)
},

// Setup a context object which is passed to the prompt
// default if it is a function
defaultContext: {}
},

// Or more simply, just set value directly
bar: 'bar'
}
})
})

// Run the opta prompts
await opts.prompt()()
const values = opts.values({ baz: 'baz' })
assert.deepStrictEqual(values, {
foo: 'foo',
bar: 'bar',
baz: 'baz'
})
})
```
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"choices"
],
"scripts": {
"test": "standard && mocha",
"test": "mocha",
"test:debug": "mocha --inspect --inspect-brk --timeout=0",
"lint": "standard",
"lint:fix": "standard --fix",
Expand Down
190 changes: 104 additions & 86 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ const fs = require('fs').promises
const assert = require('assert')
const pkg = require('../package.json')
const opta = require('..')
const utils = require('../utils')

const FIX = path.join(__dirname, 'fixtures')
const TMP = path.join(FIX, '__tmp')

suite(pkg.name, () => {
beforeEach(async () => {
try {
await fs.rmdir(TMP, { recursive: true })
await fs.rm(TMP, { recursive: true })
} catch (e) {}
await fs.mkdir(TMP, { recursive: true })
})
Expand All @@ -23,23 +24,29 @@ suite(pkg.name, () => {
foo: true,
bar: true
},
promptModule: () => {
return async (prompts) => {
assert.strictEqual(prompts[0].name, 'foo')
assert.strictEqual(prompts[0].message, 'foo:')
assert.strictEqual(prompts[0].type, 'input')
assert.strictEqual(prompts[0].when, false)

assert.strictEqual(prompts[1].name, 'bar')
assert.strictEqual(prompts[1].message, 'bar:')
assert.strictEqual(prompts[1].type, 'input')
assert.strictEqual(prompts[1].when, true)

return {
bar: 'bar'
promptModule: utils.test.promptModule({
assertCount: 1,
prompts: {
foo: {
value: 'foo',
assert: (p) => {
assert.strictEqual(p.name, 'foo')
assert.strictEqual(p.message, 'foo:')
assert.strictEqual(p.type, 'input')
assert.strictEqual(p.when, false)
}
},
bar: {
value: 'bar',
assert: (p) => {
assert.strictEqual(p.name, 'bar')
assert.strictEqual(p.message, 'bar:')
assert.strictEqual(p.type, 'input')
assert.strictEqual(p.when, true)
}
}
}
}
})
})

opts.cli()(['--foo', 'foo'])
Expand All @@ -64,19 +71,24 @@ suite(pkg.name, () => {
defaults: {
baz: 'baz'
},
promptModule: () => {
return async (prompts) => {
assert.strictEqual(prompts[0].name, 'foo')
assert.strictEqual(prompts[0].default, 'foo')

assert.strictEqual(prompts[1].name, 'bar')
assert.strictEqual(prompts[1].default, 'bar')

return {
bar: 'bar!'
promptModule: utils.test.promptModule({
assertCount: 2,
prompts: {
foo: {
assert: (p) => {
assert.strictEqual(p.name, 'foo')
assert.strictEqual(p.default, 'foo')
}
},
bar: {
value: 'bar!',
assert: (p) => {
assert.strictEqual(p.name, 'bar')
assert.strictEqual(p.default, 'bar')
}
}
}
}
})
})

opts.defaults({
Expand All @@ -95,13 +107,12 @@ suite(pkg.name, () => {
foo: true,
bar: true
},
promptModule: () => {
return async () => {
return {
bar: 'bar'
}
promptModule: utils.test.promptModule({
assertCount: 1,
prompts: {
bar: 'bar'
}
}
})
})

opts.overrides({
Expand Down Expand Up @@ -129,18 +140,19 @@ suite(pkg.name, () => {
}
}
},
promptModule: () => {
return async (prompts) => {
assert.strictEqual(prompts[0].name, 'remoteOrigin')
assert.strictEqual(prompts[0].message, 'remote origin:')
assert.strictEqual(prompts[0].type, 'input')
assert.strictEqual(typeof prompts[0].default, 'function')

return {
remoteOrigin: prompts[0].default()
promptModule: utils.test.promptModule({
assertCount: 1,
prompts: {
remoteOrigin: {
assert: (p) => {
assert.strictEqual(p.name, 'remoteOrigin')
assert.strictEqual(p.message, 'remote origin:')
assert.strictEqual(p.type, 'input')
assert.strictEqual(p.default, remote)
}
}
}
}
})
})
createGit.cli()(['--cwd', TMP])
await createGit.prompt()()
Expand All @@ -161,24 +173,28 @@ suite(pkg.name, () => {
},
repository: true
},
promptModule: () => {
return async (prompts) => {
assert.strictEqual(prompts[0].name, 'name')
assert.strictEqual(prompts[0].message, 'name:')
assert.strictEqual(prompts[0].type, 'input')
assert.strictEqual(await prompts[0].default(), '__tmp')

assert.strictEqual(prompts[1].name, 'repository')
assert.strictEqual(prompts[1].message, 'repository:')
assert.strictEqual(prompts[1].type, 'input')
assert.strictEqual(prompts[1].default, remote)

return {
name: 'tmp',
repository: remote
promptModule: utils.test.promptModule({
assertCount: 2,
prompts: {
name: {
value: 'tmp',
assert: (p) => {
assert.strictEqual(p.name, 'name')
assert.strictEqual(p.message, 'name:')
assert.strictEqual(p.type, 'input')
assert.strictEqual(p.default, '__tmp')
}
},
repository: {
assert: (p) => {
assert.strictEqual(p.name, 'repository')
assert.strictEqual(p.message, 'repository:')
assert.strictEqual(p.type, 'input')
assert.strictEqual(p.default, remote)
}
}
}
}
})
})
createPkgJson.cli()(['--cwd', TMP])
await createPkgJson.prompt((prompts) => {
Expand All @@ -202,14 +218,15 @@ suite(pkg.name, () => {
...createGit.options,
remoteOrigin: false
},
promptModule: () => {
return async (prompts) => {
return {
name: '@scope/tmp',
repository: await prompts[1].default({ name: '@scope/tmp' })
promptModule: utils.test.promptModule({
assertCount: 2,
prompts: {
name: '@scope/tmp',
repository: {
defaultContext: { name: '@scope/tmp' }
}
}
}
})
})
createPkg.cli()(['--cwd', TMP])
await createPkg.prompt((prompts) => {
Expand Down Expand Up @@ -237,14 +254,21 @@ suite(pkg.name, () => {
},
baz: true
},
promptModule: () => {
return async (prompts) => {
assert.strictEqual(prompts.length, 2)
assert.strictEqual(prompts[0].name, 'foo')
assert.strictEqual(prompts[1].name, 'bar')
return { }
promptModule: utils.test.promptModule({
assertCount: 2,
prompts: {
foo: {
assert: (p) => {
assert.strictEqual(p.name, 'foo')
}
},
bar: {
assert: (p) => {
assert.strictEqual(p.name, 'bar')
}
}
}
}
})
})

await opts.prompt(['FooBar'])()
Expand All @@ -256,13 +280,12 @@ suite(pkg.name, () => {
foo: true,
bar: true
},
promptModule: () => {
return async (prompts) => {
return {
bar: 'bar'
}
promptModule: utils.test.promptModule({
assertCount: 1,
prompts: {
bar: 'bar'
}
}
})
})
const obj1 = opts.values()
opts.cli()(['--foo=foo'])
Expand Down Expand Up @@ -300,14 +323,9 @@ suite(pkg.name, () => {
default: async () => undefined
}
},
promptModule: () => {
return async (prompts) => {
return {
foo: prompts[0].default(),
bar: await prompts[1].default()
}
}
}
promptModule: utils.test.promptModule({
assertCount: 2
})
})

await opts.prompt()()
Expand Down
41 changes: 41 additions & 0 deletions test/util.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
'use strict'
const { suite, test } = require('mocha')
const assert = require('assert')
const utils = require('../utils')

suite('utils', () => {
suite('promptModule', async () => {
test('take options and run assertions and return output', async () => {
const prompts = [{
name: 'example',
message: 'example:',
type: 'input',
when: true
}, {
name: 'example2',
message: 'example two:',
type: 'input',
when: false
}]

const pm = utils.test.promptModule({
assertCount: 1,
prompts: {
example: 'test input',
example2: {
value: 'example2 test input',
assert: (p) => {
assert.deepStrictEqual(p, prompts[1])
}
}
}
})()

const output = await pm(prompts)

assert.deepStrictEqual(output, {
example: 'test input'
})
})
})
})
Loading

0 comments on commit 1ed108f

Please sign in to comment.