poku 4.2.1 → 4.2.2-canary.24d7783d

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.
package/README.md CHANGED
@@ -220,6 +220,10 @@ deno run npm:poku
220
220
  <td><a href="https://poku.io/docs/documentation/poku/config-files">config</a></td>
221
221
  <td>⚙️ Customize your Poku options in a config file.</td>
222
222
  </tr>
223
+ <tr>
224
+ <td><a href="https://poku.io/docs/documentation/helpers/coverage">coverage</a></td>
225
+ <td>☔️ Enable coverage collection using a coverage plugin.</td>
226
+ </tr>
223
227
  </table>
224
228
 
225
229
  > _and much more_ 👇🏻
@@ -95,4 +95,12 @@ export type InspectCLIResult = {
95
95
  PID: number;
96
96
  kill: () => Promise<void>;
97
97
  };
98
+ export type ScopeHook = {
99
+ createHolder: () => {
100
+ scope: unknown;
101
+ };
102
+ runScoped: (holder: {
103
+ scope: unknown;
104
+ }, fn: (params?: Record<string, unknown>) => Promise<unknown> | unknown) => Promise<void>;
105
+ };
98
106
  export {};
@@ -145,3 +145,4 @@ export type ConfigJSONFile = {
145
145
  testSkipPattern?: string;
146
146
  } & Omit<Configs, 'beforeEach' | 'afterEach' | 'noExit' | 'filter' | 'exclude' | 'plugins' | 'testNamePattern' | 'testSkipPattern'> & CliConfigs;
147
147
  export type ConfigFile = Omit<Configs, 'noExit'> & CliConfigs;
148
+ export type TestCallback = (params?: Record<string, unknown>) => unknown | Promise<unknown>;
package/lib/bin/help.js CHANGED
@@ -13,6 +13,8 @@ const bullet = d('●');
13
13
  const summary = [
14
14
  ['--concurrency', 'Limit the number of tests running concurrently.'],
15
15
  ['--config, -c', 'Specify a configuration file.'],
16
+ ['--coverage', 'Enable coverage collection using a coverage plugin.'],
17
+ ['--coverageConfig', 'Path to a coverage configuration file.'],
16
18
  ['--debug, -d', 'Show detailed logs.'],
17
19
  ['--denoAllow', 'Allow permissions for Deno.'],
18
20
  ['--denoDeny', 'Deny permissions for Deno.'],
package/lib/bin/index.js CHANGED
@@ -111,6 +111,44 @@ const write_js_1 = require("../services/write.js");
111
111
  afterEach: 'afterEach' in configsFromFile ? configsFromFile.afterEach : undefined,
112
112
  plugins: 'plugins' in configsFromFile ? configsFromFile.plugins : undefined,
113
113
  };
114
+ if ((0, get_arg_js_1.hasArg)('coverage')) {
115
+ const customPkg = (0, get_arg_js_1.getArg)('coverage');
116
+ if (customPkg && /^[./]/.test(customPkg)) {
117
+ (0, write_js_1.log)('Coverage plugin must be an npm package name. Local paths are not supported for security concerns.');
118
+ (0, node_process_1.exit)(1);
119
+ }
120
+ const coveragePackages = customPkg
121
+ ? [customPkg]
122
+ : [
123
+ '@pokujs/c8',
124
+ '@pokujs/monocart',
125
+ '@pokujs/istanbul',
126
+ '@pokujs/one-double-zero',
127
+ ];
128
+ const existingPlugins = poku_js_1.GLOBAL.configs.plugins ?? [];
129
+ const alreadyHasCoverage = existingPlugins.some((plugin) => plugin.name !== undefined && coveragePackages.includes(plugin.name));
130
+ if (!alreadyHasCoverage) {
131
+ let loaded = false;
132
+ for (const pkg of coveragePackages) {
133
+ try {
134
+ const { coverage } = await import(pkg);
135
+ poku_js_1.GLOBAL.configs.plugins = existingPlugins;
136
+ poku_js_1.GLOBAL.configs.plugins.push(coverage());
137
+ loaded = true;
138
+ break;
139
+ }
140
+ catch { }
141
+ }
142
+ if (!loaded) {
143
+ (0, write_js_1.hr)();
144
+ (0, write_js_1.log)(customPkg
145
+ ? `Coverage plugin not found: ${(0, format_js_1.format)(customPkg).bold()}`
146
+ : `To use ${(0, format_js_1.format)('--coverage').bold()}, install a coverage plugin, for example:\n\n${coveragePackages.map((pkg) => ` ${(0, format_js_1.format)('npm i -D').dim()} ${(0, format_js_1.format)(pkg).underline()}`).join('\n')}`);
147
+ (0, write_js_1.hr)();
148
+ (0, node_process_1.exit)(1);
149
+ }
150
+ }
151
+ }
114
152
  if (typeof testNamePattern === 'string')
115
153
  node_process_1.env.POKU_TEST_NAME_PATTERN = testNamePattern;
116
154
  if (typeof testSkipPattern === 'string')
@@ -21,7 +21,7 @@ exports.results = {
21
21
  skipped: 0,
22
22
  todo: 0,
23
23
  };
24
- exports.VERSION = '4.2.1';
24
+ exports.VERSION = '4.2.2-canary.24d7783d';
25
25
  exports.deepOptions = [];
26
26
  exports.GLOBAL = {
27
27
  cwd: (0, node_process_1.cwd)(),
@@ -1,11 +1,12 @@
1
+ import type { TestCallback } from '../../../@types/poku.js';
1
2
  import { onlyIt, skip, todo } from '../modifiers.js';
2
3
  export declare const getTitle: (input: unknown) => string | undefined;
3
- export declare const getCallback: (input: unknown) => (() => unknown) | (() => Promise<unknown>) | undefined;
4
- export declare const itBase: (titleOrCb: string | (() => unknown | Promise<unknown>), callback?: () => unknown | Promise<unknown>) => Promise<void>;
5
- declare function itCore(title: string, cb: () => Promise<unknown>): Promise<void>;
6
- declare function itCore(title: string, cb: () => unknown): void;
7
- declare function itCore(cb: () => Promise<unknown>): Promise<void>;
8
- declare function itCore(cb: () => unknown): void;
4
+ export declare const getCallback: (input: unknown) => TestCallback | undefined;
5
+ export declare const itBase: (titleOrCb: string | TestCallback, callback?: TestCallback) => Promise<void>;
6
+ declare function itCore(title: string, cb: (params?: Record<string, unknown>) => Promise<unknown>): Promise<void>;
7
+ declare function itCore(title: string, cb: (params?: Record<string, unknown>) => unknown): void;
8
+ declare function itCore(cb: (params?: Record<string, unknown>) => Promise<unknown>): Promise<void>;
9
+ declare function itCore(cb: (params?: Record<string, unknown>) => unknown): void;
9
10
  export declare const it: typeof itCore & {
10
11
  todo: typeof todo;
11
12
  skip: typeof skip;
@@ -11,12 +11,12 @@ const indentation_js_1 = require("../../../configs/indentation.js");
11
11
  const poku_js_1 = require("../../../configs/poku.js");
12
12
  const get_arg_js_1 = require("../../../parsers/get-arg.js");
13
13
  const modifiers_js_1 = require("../modifiers.js");
14
+ const SCOPE_HOOKS_KEY = Symbol.for('@pokujs/poku.test-scope-hooks');
14
15
  const getTitle = (input) => typeof input === 'string' ? input : undefined;
15
16
  exports.getTitle = getTitle;
16
- const getCallback = (input) => typeof input === 'function'
17
- ? input
18
- : undefined;
17
+ const getCallback = (input) => typeof input === 'function' ? input : undefined;
19
18
  exports.getCallback = getCallback;
19
+ const getScopeHook = () => globalThis[SCOPE_HOOKS_KEY];
20
20
  const itBase = async (titleOrCb, callback) => {
21
21
  try {
22
22
  const title = (0, exports.getTitle)(titleOrCb);
@@ -49,9 +49,16 @@ const itBase = async (titleOrCb, callback) => {
49
49
  poku_js_1.errorHoist.failed = false;
50
50
  start = node_process_1.default.hrtime();
51
51
  try {
52
- const resultCb = cb();
53
- if (resultCb instanceof Promise)
54
- await resultCb;
52
+ const hooks = getScopeHook();
53
+ if (hooks) {
54
+ const holder = hooks.createHolder();
55
+ await hooks.runScoped(holder, (params) => cb(params));
56
+ }
57
+ else {
58
+ const resultCb = cb();
59
+ if (resultCb instanceof Promise)
60
+ await resultCb;
61
+ }
55
62
  }
56
63
  catch (error) {
57
64
  node_process_1.default.exitCode = 1;
@@ -1,8 +1,8 @@
1
1
  export declare const test: {
2
- (title: string, cb: () => Promise<unknown>): Promise<void>;
3
- (title: string, cb: () => unknown): void;
4
- (cb: () => Promise<unknown>): Promise<void>;
5
- (cb: () => unknown): void;
2
+ (title: string, cb: (params?: Record<string, unknown>) => Promise<unknown>): Promise<void>;
3
+ (title: string, cb: (params?: Record<string, unknown>) => unknown): void;
4
+ (cb: (params?: Record<string, unknown>) => Promise<unknown>): Promise<void>;
5
+ (cb: (params?: Record<string, unknown>) => unknown): void;
6
6
  } & {
7
7
  todo: typeof import("./modifiers.js").todo;
8
8
  skip: typeof import("./modifiers.js").skip;
@@ -4,7 +4,7 @@ export { createReporter } from '../builders/reporter.js';
4
4
  export { findFileFromStack } from '../parsers/find-file-from-stack.js';
5
5
  export { onSigint } from './essentials/poku.js';
6
6
  export { reporter as reporterRegistry } from '../services/reporter.js';
7
- export type { ReporterPlugin, ReporterEvents, PokuPlugin, PluginContext, InspectCLIResult, } from '../@types/plugin.js';
7
+ export type { ReporterPlugin, ReporterEvents, PokuPlugin, PluginContext, InspectCLIResult, ScopeHook, } from '../@types/plugin.js';
8
8
  /** 🐷 Auxiliary function to define a Poku plugin */
9
9
  export declare const definePlugin: (plugin: PokuPlugin) => PokuPlugin;
10
10
  /** 🐽 Auxiliary function to inspect a Poku CLI execution */
@@ -31,6 +31,8 @@ const checkFlags = () => {
31
31
  const allowedFlags = new Set([
32
32
  '--concurrency',
33
33
  '--config',
34
+ '--coverage',
35
+ '--coverageConfig',
34
36
  '--debug',
35
37
  '--denoAllow',
36
38
  '--denoDeny',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "poku",
3
- "version": "4.2.1",
3
+ "version": "4.2.2-canary.24d7783d",
4
4
  "description": "🐷 Poku makes testing easy for Node.js, Bun, Deno, and you at the same time.",
5
5
  "main": "./lib/modules/index.js",
6
6
  "exports": {
@@ -37,7 +37,7 @@
37
37
  "test": "tsx src/bin/index.ts test/unit test/integration test/e2e",
38
38
  "test:bun": "bun src/bin/index.ts test/unit test/integration test/e2e",
39
39
  "test:deno": "deno run -A src/bin/index.ts --denoAllow=all test/unit test/integration test/e2e",
40
- "test:coverage": "npm test -- -c=.c8.ts",
40
+ "test:coverage": "npm test -- --coverage",
41
41
  "test:docker:node": "bun test/ci.test.ts",
42
42
  "build": "bash scripts/build.sh",
43
43
  "lint": "bash scripts/lint.sh",
@@ -48,7 +48,7 @@
48
48
  "devDependencies": {
49
49
  "@biomejs/biome": "^2.4.10",
50
50
  "@ianvs/prettier-plugin-sort-imports": "^4.7.1",
51
- "@pokujs/c8": "^1.0.2",
51
+ "@pokujs/c8": "^1.2.0",
52
52
  "@pokujs/docker": "^1.0.0",
53
53
  "@types/node": "^25.5.0",
54
54
  "concurrently": "^9.2.1",