@functional-examples/test 0.0.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/commands/index.d.ts +41 -0
  2. package/dist/commands/index.d.ts.map +1 -0
  3. package/dist/commands/index.js +9 -0
  4. package/dist/commands/index.js.map +1 -0
  5. package/dist/commands/list.d.ts +10 -0
  6. package/dist/commands/list.d.ts.map +1 -0
  7. package/dist/commands/list.js +57 -0
  8. package/dist/commands/list.js.map +1 -0
  9. package/dist/commands/test.d.ts +19 -0
  10. package/dist/commands/test.d.ts.map +1 -0
  11. package/dist/commands/test.js +110 -0
  12. package/dist/commands/test.js.map +1 -0
  13. package/dist/index.d.ts +13 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +74 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/integration.spec.d.ts +1 -0
  18. package/dist/reporters/index.d.ts +5 -0
  19. package/dist/reporters/index.d.ts.map +1 -0
  20. package/dist/reporters/index.js +4 -0
  21. package/dist/reporters/index.js.map +1 -0
  22. package/dist/reporters/pretty.d.ts +3 -0
  23. package/dist/reporters/pretty.d.ts.map +1 -0
  24. package/dist/reporters/pretty.js +58 -0
  25. package/dist/reporters/pretty.js.map +1 -0
  26. package/dist/reporters/resolve.d.ts +7 -0
  27. package/dist/reporters/resolve.d.ts.map +1 -0
  28. package/dist/reporters/resolve.js +39 -0
  29. package/dist/reporters/resolve.js.map +1 -0
  30. package/dist/reporters/tap.d.ts +3 -0
  31. package/dist/reporters/tap.d.ts.map +1 -0
  32. package/dist/reporters/tap.js +53 -0
  33. package/dist/reporters/tap.js.map +1 -0
  34. package/dist/reporters/types.d.ts +50 -0
  35. package/dist/reporters/types.d.ts.map +1 -0
  36. package/dist/reporters/types.js +2 -0
  37. package/dist/reporters/types.js.map +1 -0
  38. package/dist/runner.d.ts +15 -0
  39. package/dist/runner.d.ts.map +1 -0
  40. package/dist/runner.js +232 -0
  41. package/dist/runner.js.map +1 -0
  42. package/dist/runner.spec.d.ts +1 -0
  43. package/dist/schema.d.ts +298 -0
  44. package/dist/schema.d.ts.map +1 -0
  45. package/dist/schema.js +115 -0
  46. package/dist/schema.js.map +1 -0
  47. package/dist/schema.spec.d.ts +1 -0
  48. package/dist/types.d.ts +37 -0
  49. package/dist/types.d.ts.map +1 -0
  50. package/dist/types.js +2 -0
  51. package/dist/types.js.map +1 -0
  52. package/package.json +54 -0
@@ -0,0 +1,41 @@
1
+ import type { ResolvedConfig } from '@functional-examples/devkit';
2
+ import type { ResolvedTestPluginOptions } from '../types.js';
3
+ export declare function createTestCommands(config: ResolvedConfig, pluginOpts: ResolvedTestPluginOptions): import("cli-forge").CLI<{
4
+ unmatched: string[];
5
+ '--'?: string[];
6
+ } & {
7
+ path?: string;
8
+ } & {} & {
9
+ filter?: string;
10
+ } & {} & {
11
+ bail?: boolean;
12
+ } & {} & {
13
+ verbose?: boolean;
14
+ } & {} & {
15
+ format?: string;
16
+ } & {} & {
17
+ timeout?: number;
18
+ } & {}, Promise<never>, import("cli-forge").CommandToChildEntry<import("cli-forge").CLI<{
19
+ unmatched: string[];
20
+ '--'?: string[];
21
+ } & {
22
+ path?: string;
23
+ } & {} & {
24
+ format?: "table" | "json";
25
+ } & {}, Promise<void>, {}, undefined>, import("cli-forge").CLI<{
26
+ unmatched: string[];
27
+ '--'?: string[];
28
+ } & {
29
+ path?: string;
30
+ } & {} & {
31
+ filter?: string;
32
+ } & {} & {
33
+ bail?: boolean;
34
+ } & {} & {
35
+ verbose?: boolean;
36
+ } & {} & {
37
+ format?: string;
38
+ } & {} & {
39
+ timeout?: number;
40
+ } & {}, Promise<never>, {}, undefined>>, undefined>[];
41
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAI7D,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,cAAc,EACtB,UAAU,EAAE,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sDAOtC"}
@@ -0,0 +1,9 @@
1
+ import { createTestCommand } from './test.js';
2
+ import { createListCommand } from './list.js';
3
+ export function createTestCommands(config, pluginOpts) {
4
+ // Main test command with list as subcommand
5
+ const testCommand = createTestCommand(config, pluginOpts)
6
+ .commands(createListCommand(config));
7
+ return [testCommand];
8
+ }
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAE9C,MAAM,UAAU,kBAAkB,CAChC,MAAsB,EACtB,UAAqC;IAErC,4CAA4C;IAC5C,MAAM,WAAW,GAAG,iBAAiB,CAAC,MAAM,EAAE,UAAU,CAAC;SACtD,QAAQ,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC;IAEvC,OAAO,CAAC,WAAW,CAAC,CAAC;AACvB,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { ResolvedConfig } from '@functional-examples/devkit';
2
+ export declare function createListCommand(config: ResolvedConfig): import("cli-forge").CLI<{
3
+ unmatched: string[];
4
+ '--'?: string[];
5
+ } & {
6
+ path?: string;
7
+ } & {} & {
8
+ format?: "table" | "json";
9
+ } & {}, Promise<void>, {}, undefined>;
10
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAW,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAa3E,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,cAAc;;;;;;;sCAyDvD"}
@@ -0,0 +1,57 @@
1
+ import { cli } from 'cli-forge';
2
+ import { scanExamples } from 'functional-examples';
3
+ import { normalizeTests } from '../runner.js';
4
+ import { testMetadataSchema } from '../schema.js';
5
+ function hasTests(example) {
6
+ const result = testMetadataSchema.safeParse(example.metadata);
7
+ return result.success && result.data.test !== undefined;
8
+ }
9
+ export function createListCommand(config) {
10
+ return cli('list', {
11
+ description: 'List available tests',
12
+ builder: (cmd) => cmd
13
+ .option('path', {
14
+ type: 'string',
15
+ alias: ['p'],
16
+ description: 'Path to examples directory',
17
+ default: '.',
18
+ })
19
+ .option('format', {
20
+ type: 'string',
21
+ choices: ['table', 'json'],
22
+ description: 'Output format',
23
+ default: 'table',
24
+ }),
25
+ handler: async (args) => {
26
+ const { examples } = await scanExamples(config);
27
+ const testableExamples = examples.filter(hasTests);
28
+ const testList = testableExamples.flatMap((example) => {
29
+ const tests = normalizeTests(example.metadata.test);
30
+ return tests.map((t) => ({
31
+ example: example.id,
32
+ test: t.name,
33
+ command: 'steps' in t
34
+ ? `${t.steps.length} step${t.steps.length > 1 ? 's' : ''}`
35
+ : t.options.command,
36
+ }));
37
+ });
38
+ if (args.format === 'json') {
39
+ console.log(JSON.stringify(testList, null, 2));
40
+ return;
41
+ }
42
+ // Table format
43
+ if (testList.length === 0) {
44
+ console.log('No tests found');
45
+ return;
46
+ }
47
+ console.log('Example'.padEnd(30) + 'Test'.padEnd(30) + 'Command');
48
+ console.log('-'.repeat(80));
49
+ for (const t of testList) {
50
+ console.log(t.example.slice(0, 28).padEnd(30) +
51
+ t.test.slice(0, 28).padEnd(30) +
52
+ t.command);
53
+ }
54
+ },
55
+ });
56
+ }
57
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { ResolvedConfig } from '@functional-examples/devkit';
2
+ import type { ResolvedTestPluginOptions } from '../types.js';
3
+ export declare function createTestCommand(config: ResolvedConfig, pluginOpts: ResolvedTestPluginOptions): import("cli-forge").CLI<{
4
+ unmatched: string[];
5
+ '--'?: string[];
6
+ } & {
7
+ path?: string;
8
+ } & {} & {
9
+ filter?: string;
10
+ } & {} & {
11
+ bail?: boolean;
12
+ } & {} & {
13
+ verbose?: boolean;
14
+ } & {} & {
15
+ format?: string;
16
+ } & {} & {
17
+ timeout?: number;
18
+ } & {}, Promise<never>, {}, undefined>;
19
+ //# sourceMappingURL=test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../../src/commands/test.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAW,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAK3E,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAoB7D,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,cAAc,EACtB,UAAU,EAAE,yBAAyB;;;;;;;;;;;;;;;uCA+GtC"}
@@ -0,0 +1,110 @@
1
+ import { cli } from 'cli-forge';
2
+ import { scanExamples } from 'functional-examples';
3
+ import { normalizeTests, runTest } from '../runner.js';
4
+ import { testMetadataSchema } from '../schema.js';
5
+ function isCI() {
6
+ return !!(process.env.CI ||
7
+ process.env.GITHUB_ACTIONS ||
8
+ process.env.GITLAB_CI ||
9
+ process.env.CIRCLECI ||
10
+ process.env.JENKINS_URL ||
11
+ process.env.TRAVIS);
12
+ }
13
+ function hasTests(example) {
14
+ const result = testMetadataSchema.safeParse(example.metadata);
15
+ return result.success && result.data.test !== undefined;
16
+ }
17
+ export function createTestCommand(config, pluginOpts) {
18
+ const { reporters, defaultReporter, ciReporter, timeout } = pluginOpts;
19
+ return cli('$0', {
20
+ description: 'Run tests for functional examples',
21
+ builder: (cmd) => cmd
22
+ .option('path', {
23
+ type: 'string',
24
+ alias: ['p'],
25
+ description: 'Path to examples directory',
26
+ default: '.',
27
+ })
28
+ .option('filter', {
29
+ type: 'string',
30
+ alias: ['f'],
31
+ description: 'Filter examples by id pattern',
32
+ })
33
+ .option('bail', {
34
+ type: 'boolean',
35
+ alias: ['b'],
36
+ description: 'Stop on first failure',
37
+ default: false,
38
+ })
39
+ .option('verbose', {
40
+ type: 'boolean',
41
+ alias: ['v'],
42
+ description: 'Show command output even on success',
43
+ default: false,
44
+ })
45
+ .option('format', {
46
+ type: 'string',
47
+ description: `Output format (default: ${defaultReporter} in TTY, ${ciReporter} in CI)`,
48
+ })
49
+ .option('timeout', {
50
+ type: 'number',
51
+ description: 'Default timeout in ms',
52
+ default: timeout,
53
+ }),
54
+ handler: async (args) => {
55
+ const formatName = args.format ?? (isCI() ? ciReporter : defaultReporter);
56
+ const reporterFactory = reporters[formatName];
57
+ if (!reporterFactory) {
58
+ console.error(`Unknown reporter: ${formatName}`);
59
+ console.error(`Available: ${Object.keys(reporters).join(', ')}`);
60
+ process.exit(1);
61
+ }
62
+ const reporter = reporterFactory();
63
+ // Scan for examples
64
+ const { examples, errors } = await scanExamples(config);
65
+ if (errors.length) {
66
+ for (const error of errors) {
67
+ console.error(`Error in ${error}: ${error.message}`);
68
+ }
69
+ process.exit(1);
70
+ }
71
+ // Filter to examples with tests
72
+ let testableExamples = examples.filter(hasTests);
73
+ // Apply filter pattern
74
+ if (args.filter) {
75
+ const pattern = args.filter.toLowerCase();
76
+ testableExamples = testableExamples.filter((e) => e.id.toLowerCase().includes(pattern) ||
77
+ e.rootPath.toLowerCase().includes(pattern));
78
+ }
79
+ if (testableExamples.length === 0) {
80
+ console.log('No examples with tests found');
81
+ process.exit(0);
82
+ }
83
+ await reporter.start(testableExamples);
84
+ let passed = 0;
85
+ let failed = 0;
86
+ for (const example of testableExamples) {
87
+ const tests = normalizeTests(example.metadata.test);
88
+ for (const testCase of tests) {
89
+ const result = await runTest(example.id, example.rootPath, testCase, {
90
+ timeout: args.timeout,
91
+ });
92
+ await reporter.report(result, args.verbose);
93
+ if (result.passed) {
94
+ passed++;
95
+ }
96
+ else {
97
+ failed++;
98
+ if (args.bail) {
99
+ await reporter.finish({ passed, failed, bail: true });
100
+ process.exit(1);
101
+ }
102
+ }
103
+ }
104
+ }
105
+ await reporter.finish({ passed, failed });
106
+ process.exit(failed > 0 ? 1 : 0);
107
+ },
108
+ });
109
+ }
110
+ //# sourceMappingURL=test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test.js","sourceRoot":"","sources":["../../src/commands/test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { Plugin } from '@functional-examples/devkit';
2
+ import type { TestMetadata } from './schema.js';
3
+ import type { TestPluginOptions } from './types.js';
4
+ /**
5
+ * Create the test plugin
6
+ */
7
+ export declare function createTestPlugin(options?: TestPluginOptions): Plugin<TestMetadata>;
8
+ export type { Reporter, ReporterConfig, ReporterFactory, TestResult, TestSummary, } from './reporters/types.js';
9
+ export type { CommandStep, DirAssertions, FileAssertions, OptionsTestCase, StepsTestCase, TestAssertions, TestCase, TestMetadata, TestOptions, TestStep, } from './schema.js';
10
+ export type { TestPluginOptions } from './types.js';
11
+ export { createPrettyReporter } from './reporters/pretty.js';
12
+ export { createTapReporter } from './reporters/tap.js';
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAoB,MAAM,6BAA6B,CAAC;AAI5E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAqDpD;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,GAAE,iBAAsB,GAC9B,MAAM,CAAC,YAAY,CAAC,CAqBtB;AAGD,YAAY,EACV,QAAQ,EACR,cAAc,EACd,eAAe,EACf,UAAU,EACV,WAAW,GACZ,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EACV,WAAW,EACX,aAAa,EACb,cAAc,EACd,eAAe,EACf,aAAa,EACb,cAAc,EACd,QAAQ,EACR,YAAY,EACZ,WAAW,EACX,QAAQ,GACT,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAGpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,74 @@
1
+ import { z } from 'zod';
2
+ import { createTestCommands } from './commands/index.js';
3
+ import { resolveReporters } from './reporters/resolve.js';
4
+ import { TEST_METADATA_JSON_SCHEMA, testMetadataSchema } from './schema.js';
5
+ function mapZodIssue(zIssue) {
6
+ return {
7
+ path: zIssue.path.join('.'),
8
+ message: zIssue.message,
9
+ };
10
+ }
11
+ /**
12
+ * Validate test metadata using Zod schema
13
+ */
14
+ function validateTestMetadata(metadata) {
15
+ const result = testMetadataSchema.safeParse(metadata);
16
+ if (result.success) {
17
+ return { success: true, errors: [] };
18
+ }
19
+ if (result.error.issues.length === 1) {
20
+ const issue = result.error.issues[0];
21
+ if (issue.code === 'invalid_union' && issue.errors.length > 0) {
22
+ // Type assertion needed because Zod 4's invalid_union has errors typed as
23
+ // $ZodIssue[][] | [] (union with empty tuple), which confuses TypeScript
24
+ const unionErrors = issue.errors;
25
+ const issuesFromUnionMembersWithCorrectType = unionErrors.length > 1
26
+ ? unionErrors.filter((zErr) => !zErr.find((err) => err.code === 'invalid_type'))
27
+ : [];
28
+ if (issuesFromUnionMembersWithCorrectType.length === 1) {
29
+ return {
30
+ success: false,
31
+ errors: issuesFromUnionMembersWithCorrectType[0].map(mapZodIssue),
32
+ };
33
+ }
34
+ }
35
+ }
36
+ return {
37
+ success: false,
38
+ errors: [
39
+ {
40
+ path: '',
41
+ message: z.prettifyError(result.error),
42
+ ...result.error,
43
+ },
44
+ ],
45
+ };
46
+ }
47
+ /**
48
+ * Create the test plugin
49
+ */
50
+ export function createTestPlugin(options = {}) {
51
+ return {
52
+ name: '@functional-examples/test',
53
+ schemas: {
54
+ metadata: JSON.stringify(TEST_METADATA_JSON_SCHEMA),
55
+ },
56
+ validators: {
57
+ metadata: validateTestMetadata,
58
+ },
59
+ commands: async (config) => {
60
+ const reporters = await resolveReporters(options.reporters);
61
+ return createTestCommands(config, {
62
+ reporters,
63
+ defaultReporter: options.defaultReporter ?? 'pretty',
64
+ ciReporter: options.ciReporter ?? 'tap',
65
+ timeout: options.timeout ?? 30000,
66
+ });
67
+ },
68
+ _options: options,
69
+ };
70
+ }
71
+ // Re-export reporter factories for custom compositions
72
+ export { createPrettyReporter } from './reporters/pretty.js';
73
+ export { createTapReporter } from './reporters/tap.js';
74
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,5 @@
1
+ export type { Reporter, ReporterFactory, ReporterConfig, TestResult, TestSummary, } from './types.js';
2
+ export { createPrettyReporter } from './pretty.js';
3
+ export { createTapReporter } from './tap.js';
4
+ export { resolveReporters, BUILTIN_REPORTERS } from './resolve.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/reporters/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,QAAQ,EACR,eAAe,EACf,cAAc,EACd,UAAU,EACV,WAAW,GACZ,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { createPrettyReporter } from './pretty.js';
2
+ export { createTapReporter } from './tap.js';
3
+ export { resolveReporters, BUILTIN_REPORTERS } from './resolve.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/reporters/index.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Reporter } from './types.js';
2
+ export declare function createPrettyReporter(): Reporter;
3
+ //# sourceMappingURL=pretty.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pretty.d.ts","sourceRoot":"","sources":["../../src/reporters/pretty.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAmB3C,wBAAgB,oBAAoB,IAAI,QAAQ,CAgD/C"}
@@ -0,0 +1,58 @@
1
+ const PASS = '\x1b[32m PASS \x1b[0m';
2
+ const FAIL = '\x1b[31m FAIL \x1b[0m';
3
+ const DIM = '\x1b[2m';
4
+ const RESET = '\x1b[0m';
5
+ const RED = '\x1b[31m';
6
+ const GREEN = '\x1b[32m';
7
+ const YELLOW = '\x1b[33m';
8
+ function countTests(examples) {
9
+ return examples.reduce((sum, e) => {
10
+ const test = e.metadata?.test;
11
+ if (!test)
12
+ return sum;
13
+ return sum + (Array.isArray(test) ? test.length : 1);
14
+ }, 0);
15
+ }
16
+ export function createPrettyReporter() {
17
+ return {
18
+ start(examples) {
19
+ const testCount = countTests(examples);
20
+ console.log(`\nRunning ${testCount} test${testCount !== 1 ? 's' : ''} from ${examples.length} example${examples.length !== 1 ? 's' : ''}\n`);
21
+ },
22
+ report(result, verbose) {
23
+ const status = result.passed ? PASS : FAIL;
24
+ const duration = `${DIM}(${result.duration}ms)${RESET}`;
25
+ console.log(`${status} ${result.example} > ${result.test} ${duration}`);
26
+ if (!result.passed && result.error) {
27
+ const indented = result.error
28
+ .split('\n')
29
+ .map((line) => ` ${line}`)
30
+ .join('\n');
31
+ console.log(indented);
32
+ if (result.actual) {
33
+ console.log(` ${DIM}Exit code: ${result.actual.exitCode}${RESET}`);
34
+ }
35
+ }
36
+ if (verbose && result.passed && result.actual) {
37
+ if (result.actual.stdout) {
38
+ const truncated = result.actual.stdout.slice(0, 200);
39
+ console.log(` ${DIM}stdout: ${truncated}${RESET}`);
40
+ }
41
+ }
42
+ },
43
+ finish({ passed, failed, bail }) {
44
+ console.log('');
45
+ if (bail) {
46
+ console.log(`${YELLOW}Bailed after first failure${RESET}\n`);
47
+ }
48
+ const parts = [];
49
+ if (failed > 0)
50
+ parts.push(`${RED}${failed} failed${RESET}`);
51
+ if (passed > 0)
52
+ parts.push(`${GREEN}${passed} passed${RESET}`);
53
+ parts.push(`${passed + failed} total`);
54
+ console.log(`Tests: ${parts.join(', ')}`);
55
+ },
56
+ };
57
+ }
58
+ //# sourceMappingURL=pretty.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pretty.js","sourceRoot":"","sources":["../../src/reporters/pretty.ts"],"names":[],"mappings":"AAGA,MAAM,IAAI,GAAG,uBAAuB,CAAC;AACrC,MAAM,IAAI,GAAG,uBAAuB,CAAC;AACrC,MAAM,GAAG,GAAG,SAAS,CAAC;AACtB,MAAM,KAAK,GAAG,SAAS,CAAC;AACxB,MAAM,GAAG,GAAG,UAAU,CAAC;AACvB,MAAM,KAAK,GAAG,UAAU,CAAC;AACzB,MAAM,MAAM,GAAG,UAAU,CAAC;AAE1B,SAAS,UAAU,CAAC,QAAmB;IACrC,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;QAChC,MAAM,IAAI,GAAI,CAAC,CAAC,QAA+B,EAAE,IAAI,CAAC;QACtD,IAAI,CAAC,IAAI;YAAE,OAAO,GAAG,CAAC;QACtB,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACvD,CAAC,EAAE,CAAC,CAAC,CAAC;AACR,CAAC;AAED,MAAM,UAAU,oBAAoB;IAClC,OAAO;QACL,KAAK,CAAC,QAAQ;YACZ,MAAM,SAAS,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;YACvC,OAAO,CAAC,GAAG,CACT,aAAa,SAAS,QAAQ,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,SAAS,QAAQ,CAAC,MAAM,WAAW,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,CAChI,CAAC;QACJ,CAAC;QAED,MAAM,CAAC,MAAM,EAAE,OAAO;YACpB,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;YAC3C,MAAM,QAAQ,GAAG,GAAG,GAAG,IAAI,MAAM,CAAC,QAAQ,MAAM,KAAK,EAAE,CAAC;YAExD,OAAO,CAAC,GAAG,CAAC,GAAG,MAAM,IAAI,MAAM,CAAC,OAAO,MAAM,MAAM,CAAC,IAAI,IAAI,QAAQ,EAAE,CAAC,CAAC;YAExE,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;gBACnC,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK;qBAC1B,KAAK,CAAC,IAAI,CAAC;qBACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,IAAI,EAAE,CAAC;qBAC/B,IAAI,CAAC,IAAI,CAAC,CAAC;gBACd,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;gBACtB,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;oBAClB,OAAO,CAAC,GAAG,CAAC,UAAU,GAAG,cAAc,MAAM,CAAC,MAAM,CAAC,QAAQ,GAAG,KAAK,EAAE,CAAC,CAAC;gBAC3E,CAAC;YACH,CAAC;YAED,IAAI,OAAO,IAAI,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;gBAC9C,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;oBACzB,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;oBACrD,OAAO,CAAC,GAAG,CAAC,UAAU,GAAG,WAAW,SAAS,GAAG,KAAK,EAAE,CAAC,CAAC;gBAC3D,CAAC;YACH,CAAC;QACH,CAAC;QAED,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE;YAC7B,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAChB,IAAI,IAAI,EAAE,CAAC;gBACT,OAAO,CAAC,GAAG,CAAC,GAAG,MAAM,6BAA6B,KAAK,IAAI,CAAC,CAAC;YAC/D,CAAC;YAED,MAAM,KAAK,GAAa,EAAE,CAAC;YAC3B,IAAI,MAAM,GAAG,CAAC;gBAAE,KAAK,CAAC,IAAI,CAAC,GAAG,GAAG,GAAG,MAAM,UAAU,KAAK,EAAE,CAAC,CAAC;YAC7D,IAAI,MAAM,GAAG,CAAC;gBAAE,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,GAAG,MAAM,UAAU,KAAK,EAAE,CAAC,CAAC;YAC/D,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,GAAG,MAAM,QAAQ,CAAC,CAAC;YAEvC,OAAO,CAAC,GAAG,CAAC,UAAU,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC5C,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { ReporterFactory, ReporterConfig } from './types.js';
2
+ export declare const BUILTIN_REPORTERS: Record<string, ReporterFactory>;
3
+ /**
4
+ * Resolve reporter configs to factory functions
5
+ */
6
+ export declare function resolveReporters(custom?: Record<string, ReporterConfig>): Promise<Record<string, ReporterFactory>>;
7
+ //# sourceMappingURL=resolve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/reporters/resolve.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAIlE,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAG7D,CAAC;AAyBF;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAM,GAC1C,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,CAY1C"}
@@ -0,0 +1,39 @@
1
+ import { createPrettyReporter } from './pretty.js';
2
+ import { createTapReporter } from './tap.js';
3
+ export const BUILTIN_REPORTERS = {
4
+ pretty: createPrettyReporter,
5
+ tap: createTapReporter,
6
+ };
7
+ /**
8
+ * Load a reporter from a module path
9
+ */
10
+ async function loadReporterModule(modulePath) {
11
+ try {
12
+ const mod = await import(modulePath);
13
+ const factory = mod.default ?? mod.reporter ?? mod.createReporter;
14
+ if (typeof factory !== 'function') {
15
+ throw new Error(`Reporter module "${modulePath}" must export a factory function ` +
16
+ `as default, 'reporter', or 'createReporter'`);
17
+ }
18
+ return factory;
19
+ }
20
+ catch (err) {
21
+ throw new Error(`Failed to load reporter from "${modulePath}": ${err instanceof Error ? err.message : err}`);
22
+ }
23
+ }
24
+ /**
25
+ * Resolve reporter configs to factory functions
26
+ */
27
+ export async function resolveReporters(custom = {}) {
28
+ const resolved = { ...BUILTIN_REPORTERS };
29
+ for (const [name, config] of Object.entries(custom)) {
30
+ if (typeof config === 'function') {
31
+ resolved[name] = config;
32
+ }
33
+ else if (typeof config === 'string') {
34
+ resolved[name] = await loadReporterModule(config);
35
+ }
36
+ }
37
+ return resolved;
38
+ }
39
+ //# sourceMappingURL=resolve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/reporters/resolve.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAE7C,MAAM,CAAC,MAAM,iBAAiB,GAAoC;IAChE,MAAM,EAAE,oBAAoB;IAC5B,GAAG,EAAE,iBAAiB;CACvB,CAAC;AAEF;;GAEG;AACH,KAAK,UAAU,kBAAkB,CAAC,UAAkB;IAClD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;QACrC,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,cAAc,CAAC;QAElE,IAAI,OAAO,OAAO,KAAK,UAAU,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CACb,oBAAoB,UAAU,mCAAmC;gBAC/D,6CAA6C,CAChD,CAAC;QACJ,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,iCAAiC,UAAU,MAAM,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,CAC5F,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,SAAyC,EAAE;IAE3C,MAAM,QAAQ,GAAoC,EAAE,GAAG,iBAAiB,EAAE,CAAC;IAE3E,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACpD,IAAI,OAAO,MAAM,KAAK,UAAU,EAAE,CAAC;YACjC,QAAQ,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC;QAC1B,CAAC;aAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;YACtC,QAAQ,CAAC,IAAI,CAAC,GAAG,MAAM,kBAAkB,CAAC,MAAM,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Reporter } from './types.js';
2
+ export declare function createTapReporter(): Reporter;
3
+ //# sourceMappingURL=tap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tap.d.ts","sourceRoot":"","sources":["../../src/reporters/tap.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAW3C,wBAAgB,iBAAiB,IAAI,QAAQ,CAgD5C"}
@@ -0,0 +1,53 @@
1
+ function countTests(examples) {
2
+ return examples.reduce((sum, e) => {
3
+ const test = e.metadata?.test;
4
+ if (!test)
5
+ return sum;
6
+ return sum + (Array.isArray(test) ? test.length : 1);
7
+ }, 0);
8
+ }
9
+ export function createTapReporter() {
10
+ let testNumber = 0;
11
+ return {
12
+ start(examples) {
13
+ const total = countTests(examples);
14
+ console.log('TAP version 14');
15
+ console.log(`1..${total}`);
16
+ },
17
+ report(result, _verbose) {
18
+ testNumber++;
19
+ const status = result.passed ? 'ok' : 'not ok';
20
+ const name = `${result.example} > ${result.test}`;
21
+ console.log(`${status} ${testNumber} - ${name}`);
22
+ if (!result.passed) {
23
+ console.log(' ---');
24
+ if (result.error) {
25
+ const escaped = result.error.replace(/"/g, '\\"');
26
+ console.log(` message: "${escaped}"`);
27
+ }
28
+ if (result.actual) {
29
+ console.log(` actual_exit_code: ${result.actual.exitCode}`);
30
+ if (result.actual.stdout) {
31
+ console.log(' stdout: |');
32
+ result.actual.stdout.split('\n').forEach((line) => {
33
+ console.log(` ${line}`);
34
+ });
35
+ }
36
+ if (result.actual.stderr) {
37
+ console.log(' stderr: |');
38
+ result.actual.stderr.split('\n').forEach((line) => {
39
+ console.log(` ${line}`);
40
+ });
41
+ }
42
+ }
43
+ console.log(' ...');
44
+ }
45
+ },
46
+ finish({ passed, failed }) {
47
+ console.log(`# tests ${passed + failed}`);
48
+ console.log(`# pass ${passed}`);
49
+ console.log(`# fail ${failed}`);
50
+ },
51
+ };
52
+ }
53
+ //# sourceMappingURL=tap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tap.js","sourceRoot":"","sources":["../../src/reporters/tap.ts"],"names":[],"mappings":"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"}