Some checks are pending
CI / verify (push) Waiting to run
- 30-test suite (node --test, no framework) covering the exact functions
that have regressed in previous rounds:
* parseStoreArg / parseStoreNumber / storeEmail (helpers)
* greetingForBrand (brand fallback)
* formatE911Address / formatSuite (google response reducer)
* parseNextLink (RFC-5988 pagination — now exported)
* runStep success / non-critical / critical / no-bot paths
- test/setup.js stubs required env vars so any src/ module can be
imported cleanly; loaded via --import once per test process
- npm run test wired up; directory form works on Node 20 + 22
- .gitea/workflows/ci.yml runs lint + format:check + test on push/PR
to main, on Node 22 to match the runtime image
- Exclude test/ and .gitea/ from the Docker build context
- Exclude docker/ from bot Prettier scope (remote-agent is its own
sub-project with its own tooling)
Co-authored-by: Cursor <cursoragent@cursor.com>
67 lines
2.3 KiB
JavaScript
67 lines
2.3 KiB
JavaScript
import { describe, it, beforeEach } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
|
|
import { runStep } from '../src/flows/stepRunner.js';
|
|
|
|
// Minimal bot double: records every `say` call so we can assert on the
|
|
// success/failure blockquote UX without touching a real Webex framework.
|
|
function makeBot() {
|
|
const said = [];
|
|
return {
|
|
said,
|
|
say(format, text) {
|
|
said.push({ format, text });
|
|
},
|
|
};
|
|
}
|
|
|
|
describe('runStep', () => {
|
|
let bot;
|
|
beforeEach(() => {
|
|
bot = makeBot();
|
|
});
|
|
|
|
it('returns the resolved value and shows a success blockquote', async () => {
|
|
const result = await runStep(bot, 'Did the thing', async () => 42);
|
|
assert.equal(result, 42);
|
|
assert.equal(bot.said.length, 1);
|
|
assert.match(bot.said[0].text, /success.*Did the thing/);
|
|
});
|
|
|
|
it('honors an override success message', async () => {
|
|
await runStep(bot, 'internal-desc', async () => 'ok', { successMessage: 'Nice.' });
|
|
assert.match(bot.said[0].text, /success.*Nice\./);
|
|
});
|
|
|
|
it('swallows non-critical failures, returns undefined, and shows a failure blockquote', async () => {
|
|
const result = await runStep(bot, 'That step', async () => {
|
|
throw new Error('nope');
|
|
});
|
|
assert.equal(result, undefined);
|
|
assert.equal(bot.said.length, 1);
|
|
assert.match(bot.said[0].text, /failure.*Error: That step/);
|
|
// Non-critical failures MUST NOT tag the message as aborting.
|
|
assert.doesNotMatch(bot.said[0].text, /aborting/);
|
|
});
|
|
|
|
it('re-throws on a critical failure and annotates the message', async () => {
|
|
await assert.rejects(
|
|
runStep(
|
|
bot,
|
|
'Enabled location for Webex Calling',
|
|
async () => {
|
|
throw new Error('cascade');
|
|
},
|
|
{ critical: true },
|
|
),
|
|
/cascade/,
|
|
);
|
|
assert.equal(bot.said.length, 1);
|
|
assert.match(bot.said[0].text, /aborting \(critical step\)/);
|
|
});
|
|
|
|
it('works when bot is undefined (script/CLI usage)', async () => {
|
|
const result = await runStep(undefined, 'headless', async () => 'ok');
|
|
assert.equal(result, 'ok');
|
|
});
|
|
});
|