Skip to content

Commit

Permalink
feat: add only modifier to describe, it and test methods (#767)
Browse files Browse the repository at this point in the history
* feat: add `only` modifier to `describe`, `it` and `test` methods

* ci: add tests

* ci: add tests

* chore: improve tests

* chore: improve overloads

* chore: improve errors

* chore: add `--describeOnly`, `--itOnly` and `--testOnly` flags

* chore: add `--ensure` flags

* docs: add docs
  • Loading branch information
wellwelwel committed Sep 16, 2024
1 parent 402af07 commit 7658609
Show file tree
Hide file tree
Showing 17 changed files with 598 additions and 33 deletions.
6 changes: 5 additions & 1 deletion biome.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,11 @@
}
},
{
"include": ["src/modules/helpers/modifiers.ts"],
"include": [
"src/modules/helpers/modifiers.ts",
"src/modules/helpers/describe.ts",
"src/modules/helpers/it/core.ts"
],
"linter": {
"rules": {
"suspicious": {
Expand Down
3 changes: 3 additions & 0 deletions src/bin/enforce.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,18 @@ export const checkFlags = () => {
'--denoAllow',
'--denoCjs',
'--denoDeny',
'--describeOnly',
'--enforce',
'--envFile',
'--exclude',
'--failFast',
'--filter',
'--itOnly',
'--killPid',
'--killPort',
'--killRange',
'--node',
'--only',
'--parallel',
'--platform',
'--quiet',
Expand Down
4 changes: 4 additions & 0 deletions src/bin/help.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,24 @@ const summary: [string, string][] = [
['--denoAllow', 'Allow permissions for Deno.'],
['--denoCjs', 'Support CommonJS in Deno.'],
['--denoDeny', 'Deny permissions for Deno.'],
['--describeOnly', 'Only `describe` tests using `.only` will be run.'],
['--enforce, -x', 'Validate options before running tests.'],
['--envFile', 'Read and set an environment file.'],
['--exclude', 'Exclude by path using Regex to match files.'],
['--failFast', 'Stop tests at the first failure.'],
['--filter', 'Filter by path using Regex to match files.'],
['--help, -h', "Show Poku's CLI basic usage."],
['--itOnly', 'Only `it` and `test` tests using `.only` will be run.'],
['--killPid', 'Terminate the specified processes.'],
['--killPort', 'Terminate the specified ports.'],
['--killRange', 'Terminate the specified port ranges.'],
['--listFiles', 'Display all the files returned in the terminal.'],
['--node', 'Enforce tests to run through Node.js.'],
['--only', 'Only tests using `.only` will be run.'],
['--parallel, -p', 'Run tests files in parallel.'],
['--platform', 'Enforce tests to run through a platform.'],
['--quiet, -q', 'Run tests with no logs.'],
['--testOnly', 'Only `it` and `test` tests using `.only` will be run.'],
['--version, -v', "Show Poku's installed version."],
['--watch, -w', 'Watch for test events.'],
['--watchInterval', 'Set an interval for watch events.'],
Expand Down
2 changes: 2 additions & 0 deletions src/configs/poku.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ export const results = {
};

export const VERSION = '';

export const deepOptions: string[] = [];
38 changes: 28 additions & 10 deletions src/modules/helpers/describe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,10 @@ import { hrtime, env } from 'node:process';
import { format } from '../../services/format.js';
import { Write } from '../../services/write.js';
import { indentation } from '../../configs/indentation.js';
import { todo, skip } from './modifiers.js';
import { todo, skip, onlyDescribe } from './modifiers.js';
import { hasDescribeOnly, hasOnly } from '../../parsers/get-arg.js';

async function describeCore(
title: string,
cb: () => Promise<unknown>
): Promise<void>;
function describeCore(title: string, cb: () => unknown): void;
async function describeCore(cb: () => Promise<unknown>): Promise<void>;
function describeCore(cb: () => unknown): unknown;
function describeCore(title: string, options?: DescribeOptions): void;
async function describeCore(
export async function describeBase(
arg1: string | (() => unknown | Promise<unknown>),
arg2?: (() => unknown | Promise<unknown>) | DescribeOptions
): Promise<void> {
Expand Down Expand Up @@ -69,7 +62,32 @@ async function describeCore(
);
}

async function describeCore(
message: string,
cb: () => Promise<unknown>
): Promise<void>;
function describeCore(message: string, cb: () => unknown): void;
function describeCore(message: string, options: DescribeOptions): void;
function describeCore(message: string, options?: DescribeOptions): void;
async function describeCore(cb: () => Promise<unknown>): Promise<void>;
function describeCore(cb: () => unknown): void;
async function describeCore(
messageOrCb: string | (() => unknown | Promise<unknown>),
cbOrOptions?: (() => unknown | Promise<unknown>) | DescribeOptions
): Promise<void> {
if (typeof messageOrCb === 'string' && typeof cbOrOptions !== 'function')
return describeBase(messageOrCb, cbOrOptions);

if (hasOnly || hasDescribeOnly) return;

if (typeof messageOrCb === 'string' && typeof cbOrOptions === 'function')
return describeBase(messageOrCb, cbOrOptions);

if (typeof messageOrCb === 'function') return describeBase(messageOrCb);
}

export const describe = Object.assign(describeCore, {
todo,
skip,
only: onlyDescribe,
});
30 changes: 21 additions & 9 deletions src/modules/helpers/it/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,10 @@ import { each } from '../../../configs/each.js';
import { indentation } from '../../../configs/indentation.js';
import { format } from '../../../services/format.js';
import { Write } from '../../../services/write.js';
import { todo, skip } from '../modifiers.js';
import { todo, skip, onlyIt } from '../modifiers.js';
import { hasItOnly, hasOnly } from '../../../parsers/get-arg.js';

async function itCore(
message: string,
cb: () => Promise<unknown>
): Promise<void>;
function itCore(message: string, cb: () => unknown): void;
async function itCore(cb: () => Promise<unknown>): Promise<void>;
function itCore(cb: () => unknown): void;
async function itCore(
export async function itBase(
...args: [
string | (() => unknown | Promise<unknown>),
(() => unknown | Promise<unknown>)?,
Expand Down Expand Up @@ -80,7 +74,25 @@ async function itCore(
}
}

async function itCore(
message: string,
cb: () => Promise<unknown>
): Promise<void>;
function itCore(message: string, cb: () => unknown): void;
async function itCore(cb: () => Promise<unknown>): Promise<void>;
function itCore(cb: () => unknown): void;
async function itCore(
messageOrCb: string | (() => unknown) | (() => Promise<unknown>),
cb?: (() => unknown) | (() => Promise<unknown>)
): Promise<void> {
if (hasOnly || hasItOnly) return;

if (typeof messageOrCb === 'string' && cb) return itBase(messageOrCb, cb);
if (typeof messageOrCb === 'function') return itBase(messageOrCb);
}

export const it = Object.assign(itCore, {
todo,
skip,
only: onlyIt,
});
53 changes: 53 additions & 0 deletions src/modules/helpers/modifiers.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { Write } from '../../services/write.js';
import { indentation } from '../../configs/indentation.js';
import { format } from '../../services/format.js';
import { itBase } from './it/core.js';
import { describeBase } from './describe.js';
import { hasDescribeOnly, hasItOnly, hasOnly } from '../../parsers/get-arg.js';
import { exit } from 'node:process';

export function todo(message: string): void;
export async function todo(
Expand Down Expand Up @@ -34,3 +38,52 @@ export async function skip(
`${indentation.hasDescribe ? ' ' : ''}${format(`◯ ${message}`).info().bold()}`
);
}

export async function onlyDescribe(
message: string,
cb: () => Promise<unknown>
): Promise<void>;
export function onlyDescribe(message: string, cb: () => unknown): void;
export async function onlyDescribe(cb: () => Promise<unknown>): Promise<void>;
export function onlyDescribe(cb: () => unknown): void;
export async function onlyDescribe(
messageOrCb: string | (() => unknown) | (() => Promise<unknown>),
cb?: (() => unknown) | (() => Promise<unknown>)
): Promise<void> {
if (!(hasOnly || hasDescribeOnly)) {
Write.log(
format(
"Can't run `describe.only` tests without `--only` or `--describeOnly` flags"
).fail()
);
exit(1);
}

if (typeof messageOrCb === 'string' && cb)
return describeBase(messageOrCb, cb);
if (typeof messageOrCb === 'function') return describeBase(messageOrCb);
}

export async function onlyIt(
message: string,
cb: () => Promise<unknown>
): Promise<void>;
export function onlyIt(message: string, cb: () => unknown): void;
export async function onlyIt(cb: () => Promise<unknown>): Promise<void>;
export function onlyIt(cb: () => unknown): void;
export async function onlyIt(
messageOrCb: string | (() => unknown) | (() => Promise<unknown>),
cb?: (() => unknown) | (() => Promise<unknown>)
): Promise<void> {
if (!(hasOnly || hasItOnly)) {
Write.log(
format(
"Can't run `it.only` and `test.only` tests without `--only`, `--itOnly` or `--testOnly` flags"
).fail()
);
exit(1);
}

if (typeof messageOrCb === 'string' && cb) return itBase(messageOrCb, cb);
if (typeof messageOrCb === 'function') return itBase(messageOrCb);
}
6 changes: 6 additions & 0 deletions src/parsers/get-arg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,9 @@ export const argToArray = (
.map((a) => a.trim())
.filter((a) => a);
};

export const hasOnly = hasArg('only');

export const hasItOnly = hasArg('itonly') || hasArg('testonly');

export const hasDescribeOnly = hasArg('describeonly');
3 changes: 2 additions & 1 deletion src/services/run-test-file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { format } from './format.js';
import { isQuiet, parserOutput } from '../parsers/output.js';
import { beforeEach, afterEach } from './each.js';
import { Write } from './write.js';
import { deepOptions } from '../configs/poku.js';

const cwd = processCWD();

Expand Down Expand Up @@ -50,7 +51,7 @@ export const runTestFile = async (
if (!(await beforeEach(fileRelative, configs))) return false;

return new Promise((resolve) => {
const child = spawn(runtime, runtimeArguments, {
const child = spawn(runtime, [...runtimeArguments, ...deepOptions], {
stdio: ['inherit', 'pipe', 'pipe'],
shell: isWindows,
env: {
Expand Down
7 changes: 6 additions & 1 deletion src/services/run-tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,16 @@ import { Write } from '../services/write.js';
import { format } from './format.js';
import { runTestFile } from './run-test-file.js';
import { isQuiet } from '../parsers/output.js';
import { results } from '../configs/poku.js';
import { deepOptions, results } from '../configs/poku.js';
import { availableParallelism } from '../polyfills/os.js';
import { hasOnly, hasDescribeOnly, hasItOnly } from '../parsers/get-arg.js';

const cwd = process.cwd();

if (hasOnly) deepOptions.push('--only');
if (hasDescribeOnly) deepOptions.push('--describeOnly');
if (hasItOnly) deepOptions.push('--itOnly');

export const runTests = async (
dir: string,
configs?: Configs
Expand Down
29 changes: 29 additions & 0 deletions test/__fixtures__/e2e/only/--describe-only/basic-logs.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { assert } from '../../../../../src/modules/essentials/assert.js';
import { describe } from '../../../../../src/modules/helpers/describe.js';
import { it } from '../../../../../src/modules/helpers/it/core.js';

let counter = 0;

it('Should skip', () => {
counter++;
});

describe.only('Should run', () => {
it('Should run', () => {
counter++;
});
});

describe('Should skip', () => {
counter++;

it('Should never be called', () => {
counter++;
});

it.only('Should never be called', () => {
counter++;
});
});

assert.strictEqual(counter, 2);
41 changes: 41 additions & 0 deletions test/__fixtures__/e2e/only/--it-only/basic-logs.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { assert } from '../../../../../src/modules/essentials/assert.js';
import { describe } from '../../../../../src/modules/helpers/describe.js';
import { it } from '../../../../../src/modules/helpers/it/core.js';

let counter = 0;

it('Should skip', () => {
counter++;
});

it.only('Should run', () => {
counter++;
});

describe('Should skip', () => {
it('Should skip', () => {
counter++;
});

it.only('Should run', () => {
counter++;
});
});

describe('Should run', () => {
it('Should skip', () => {
counter++;
});

it.only('Should run', () => {
counter++;
});
});

describe('Should run', () => {
it.only('Should run', () => {
counter++;
});
});

assert.strictEqual(counter, 4);
45 changes: 45 additions & 0 deletions test/__fixtures__/e2e/only/--only/basic-logs.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { assert } from '../../../../../src/modules/essentials/assert.js';
import { describe } from '../../../../../src/modules/helpers/describe.js';
import { it } from '../../../../../src/modules/helpers/it/core.js';

let counter = 0;

it('Should skip', () => {
counter++;
});

it.only('Should run', () => {
counter++;
});

it('Should skip', () => {
counter++;
});

describe('Should skip', () => {
it('Should never be called', () => {
counter++;
});

it.only('Should never be called', () => {
counter++;
});
});

describe.only('Should run', () => {
it('Should skip', () => {
counter++;
});

it.only('Should run', () => {
counter++;
});
});

describe.only('Should run', () => {
it.only('Should run', () => {
counter++;
});
});

assert.strictEqual(counter, 3);
Loading

0 comments on commit 7658609

Please sign in to comment.