From 526112c26fa028895487004101dc66f0fd72837e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Weslley=20Ara=C3=BAjo?=
<46850407+wellwelwel@users.noreply.github.com>
Date: Thu, 1 Aug 2024 02:58:03 -0300
Subject: [PATCH] feat: add `.todo` helper for `describe`, `it`, and `test`
(#633)
* ci: add `todo` tdd
* refactor: adjusts unreached lines
* chore: adjust ignored paths
* feat: add `.todo` helper for `describe`, `it`, and `test`
* ci: add failure tests
* ci: improve Windows timeout
* ci: improve coverage
* ci: improve coverage
* docs: improve documentation
* chore: adjust table size
* docs: improve docs guides
* docs: add `.todo` documentation and examples
---
.github/workflows/ci_coverage-windows.yml | 2 +-
CONTRIBUTING.md | 10 +++
README.md | 29 ++++++++-
.../final-results/skip-and-todo/skip.test.ts | 3 +
.../final-results/skip-and-todo/todo.test.ts | 3 +
.../skip-todo-and-failure/failure.test.ts | 3 +
.../skip-todo-and-failure/skip.test.ts | 3 +
.../skip-todo-and-failure/todo.test.ts | 3 +
fixtures/final-results/skip/skip.test.ts | 3 +
fixtures/final-results/todo/todo.test.ts | 3 +
fixtures/schemas/options.json | 2 +-
src/bin/index.ts | 12 +++-
src/configs/poku.ts | 3 +-
src/modules/essentials/poku.ts | 8 +--
src/modules/helpers/describe.ts | 17 ++++--
src/modules/helpers/exit.ts | 33 ++++++++--
src/modules/helpers/it/core.ts | 5 +-
src/modules/helpers/it/todo.ts | 9 +++
src/modules/helpers/list-files.ts | 2 +-
src/modules/helpers/skip.ts | 6 +-
src/parsers/output.ts | 11 +++-
src/services/format.ts | 5 ++
src/services/watch.ts | 18 +++---
test/c8.test.ts | 18 +++---
test/e2e/final-results.test.ts | 53 ++++++++++++++++
test/e2e/ignored-paths.test.ts | 42 +++++++++++++
test/integration/describe/todo.test.ts | 9 +++
test/integration/it/it.test.ts | 2 +-
test/integration/it/todo.test.ts | 10 +++
test/integration/test/test.test.ts | 2 +-
test/integration/test/todo.test.ts | 10 +++
test/unit/wait-for/wait-for-trhows.test.ts | 50 +++++++++++++++
website/README.md | 2 +-
.../documentation/helpers/startScript.mdx | 2 +-
.../documentation/helpers/startService.mdx | 2 +-
website/docs/documentation/helpers/todo.mdx | 61 +++++++++++++++++++
.../docs/documentation/poku/config-files.mdx | 6 +-
.../docs/documentation/poku/include-files.mdx | 12 ++--
website/docs/examples/local-server.mdx | 1 +
website/docs/philosophy.mdx | 12 ++--
website/docs/tutorials/beginner.mdx | 4 +-
website/docs/tutorials/cross-platform.mdx | 6 +-
website/docs/tutorials/good-practices.mdx | 4 +-
website/sidebars.ts | 12 ++--
44 files changed, 433 insertions(+), 80 deletions(-)
create mode 100644 fixtures/final-results/skip-and-todo/skip.test.ts
create mode 100644 fixtures/final-results/skip-and-todo/todo.test.ts
create mode 100644 fixtures/final-results/skip-todo-and-failure/failure.test.ts
create mode 100644 fixtures/final-results/skip-todo-and-failure/skip.test.ts
create mode 100644 fixtures/final-results/skip-todo-and-failure/todo.test.ts
create mode 100644 fixtures/final-results/skip/skip.test.ts
create mode 100644 fixtures/final-results/todo/todo.test.ts
create mode 100644 src/modules/helpers/it/todo.ts
create mode 100644 test/e2e/final-results.test.ts
create mode 100644 test/e2e/ignored-paths.test.ts
create mode 100644 test/integration/describe/todo.test.ts
create mode 100644 test/integration/it/todo.test.ts
create mode 100644 test/integration/test/todo.test.ts
create mode 100644 test/unit/wait-for/wait-for-trhows.test.ts
create mode 100644 website/docs/documentation/helpers/todo.mdx
diff --git a/.github/workflows/ci_coverage-windows.yml b/.github/workflows/ci_coverage-windows.yml
index 0b8a0cc3..76347148 100644
--- a/.github/workflows/ci_coverage-windows.yml
+++ b/.github/workflows/ci_coverage-windows.yml
@@ -10,7 +10,7 @@ on:
jobs:
windows:
runs-on: windows-latest
- timeout-minutes: 5
+ timeout-minutes: 10
strategy:
fail-fast: false
name: Windows
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index b8d8fa3b..77ee0b71 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -48,13 +48,23 @@ It's better to discuss an **API** before actually start implementing it. You can
Check if there is an existing section or feel free to create a new one. You can find the wesite source code at [./website](https://github.com/wellwelwel/poku/tree/main/website).
+- Feel free to open PRs fixing typos or adding support for other languages 🤝
+
Before commiting, consider to run:
```sh
cd website
+
+# Installing dependencies
+npm ci
+
+# Fixing lint rules
npm run lint:fix
+
+# Testing
+npm run test
```
diff --git a/README.md b/README.md
index b56b34a8..eb963fcb 100644
--- a/README.md
+++ b/README.md
@@ -29,7 +29,7 @@ Enjoying **Poku**? Give him a star to show your support 🌟
Run **CommonJS** files directly with [**Deno**][deno-version-url]
Auto detect **ESM**, **CJS**, and **TypeScript** files
Run the **same test suite** for [**Node.js**][node-version-url], [**Bun**][bun-version-url], and [**Deno**][deno-version-url]
- Easily handle **servers**, **processes**, **ports**, and **containers** ✨
+ Easily handle **servers**, **processes**, **ports**, and even **containers** ✨
---
@@ -37,20 +37,43 @@ Enjoying **Poku**? Give him a star to show your support 🌟
### Install
+
+
+
+
```bash
# Node.js
npm i -D poku
+```
+
+
+
+```bash
# TypeScript (Node.js)
npm i -D poku tsx
+```
+
+
+
+```bash
# Bun
bun add -d poku
+```
+
+
+
-# Deno
+```bash
+# Deno (optional)
deno add npm:poku
```
+
+
+
+
---
### Test
@@ -220,8 +243,8 @@ To see the detailed documentation, please visit the [**Documentation**](https://
- [Avoiding conflicts in environments with multiple platforms installed](https://poku.io/docs/tutorials/cross-platform#recommendations).
- [Properly running asynchronous tests on the same file](https://poku.io/docs/examples/promises).
-- [Migrating from version **1.x** to version **2.x**](https://github.com/wellwelwel/poku/issues/533).
- [Using **Poku** without installing on **Deno** and alternatives to **JSR**](https://github.com/wellwelwel/poku/discussions/565).
+- [Migrating from version **1.x** to version **2.x**](https://github.com/wellwelwel/poku/issues/533).
---
diff --git a/fixtures/final-results/skip-and-todo/skip.test.ts b/fixtures/final-results/skip-and-todo/skip.test.ts
new file mode 100644
index 00000000..9b9526ac
--- /dev/null
+++ b/fixtures/final-results/skip-and-todo/skip.test.ts
@@ -0,0 +1,3 @@
+import { skip } from '../../../src/modules/helpers/skip.js';
+
+skip('Some skip');
diff --git a/fixtures/final-results/skip-and-todo/todo.test.ts b/fixtures/final-results/skip-and-todo/todo.test.ts
new file mode 100644
index 00000000..e3db8c9f
--- /dev/null
+++ b/fixtures/final-results/skip-and-todo/todo.test.ts
@@ -0,0 +1,3 @@
+import { test } from '../../../src/modules/helpers/test.js';
+
+test.todo('Some todo');
diff --git a/fixtures/final-results/skip-todo-and-failure/failure.test.ts b/fixtures/final-results/skip-todo-and-failure/failure.test.ts
new file mode 100644
index 00000000..40f3bbc8
--- /dev/null
+++ b/fixtures/final-results/skip-todo-and-failure/failure.test.ts
@@ -0,0 +1,3 @@
+import { exit } from 'node:process';
+
+exit(1);
diff --git a/fixtures/final-results/skip-todo-and-failure/skip.test.ts b/fixtures/final-results/skip-todo-and-failure/skip.test.ts
new file mode 100644
index 00000000..9b9526ac
--- /dev/null
+++ b/fixtures/final-results/skip-todo-and-failure/skip.test.ts
@@ -0,0 +1,3 @@
+import { skip } from '../../../src/modules/helpers/skip.js';
+
+skip('Some skip');
diff --git a/fixtures/final-results/skip-todo-and-failure/todo.test.ts b/fixtures/final-results/skip-todo-and-failure/todo.test.ts
new file mode 100644
index 00000000..e3db8c9f
--- /dev/null
+++ b/fixtures/final-results/skip-todo-and-failure/todo.test.ts
@@ -0,0 +1,3 @@
+import { test } from '../../../src/modules/helpers/test.js';
+
+test.todo('Some todo');
diff --git a/fixtures/final-results/skip/skip.test.ts b/fixtures/final-results/skip/skip.test.ts
new file mode 100644
index 00000000..9b9526ac
--- /dev/null
+++ b/fixtures/final-results/skip/skip.test.ts
@@ -0,0 +1,3 @@
+import { skip } from '../../../src/modules/helpers/skip.js';
+
+skip('Some skip');
diff --git a/fixtures/final-results/todo/todo.test.ts b/fixtures/final-results/todo/todo.test.ts
new file mode 100644
index 00000000..e3db8c9f
--- /dev/null
+++ b/fixtures/final-results/todo/todo.test.ts
@@ -0,0 +1,3 @@
+import { test } from '../../../src/modules/helpers/test.js';
+
+test.todo('Some todo');
diff --git a/fixtures/schemas/options.json b/fixtures/schemas/options.json
index c4a345d4..c67e8ec4 100644
--- a/fixtures/schemas/options.json
+++ b/fixtures/schemas/options.json
@@ -13,7 +13,7 @@
"items": {
"type": "string"
},
- "description": "Specify the path(s) to include in the configuration.\nhttps://poku.io/docs/documentation/poku/include-files",
+ "description": "Specify the path(s) to include in the configuration. Doesn't support glob patterns.\nhttps://poku.io/docs/documentation/poku/include-files",
"default": "."
},
"parallel": {
diff --git a/src/bin/index.ts b/src/bin/index.ts
index f9c64f00..566a90eb 100644
--- a/src/bin/index.ts
+++ b/src/bin/index.ts
@@ -20,7 +20,8 @@ import { getConfigs } from '../parsers/options.js';
const defaultConfigs = await getConfigs(configFile);
const dirs: string[] = (() => {
- const includeArg = getArg('include'); // deprecated
+ /* c8 ignore next 4 */ // Deprecated
+ const includeArg = getArg('include');
if (includeArg !== undefined) {
return includeArg.split(',');
}
@@ -38,6 +39,7 @@ import { getConfigs } from '../parsers/options.js';
const killPort = getArg('kill-port');
const killRange = getArg('kill-range');
const killPID = getArg('kill-pid');
+ /* c8 ignore start */ // Deno
const denoAllow = argToArray('deno-allow') ?? defaultConfigs?.deno?.allow;
const denoDeny = argToArray('deno-deny') ?? defaultConfigs?.deno?.deny;
const denoCJS =
@@ -47,6 +49,7 @@ import { getConfigs } from '../parsers/options.js';
.filter((a) => a) ||
hasArg('deno-cjs') ||
defaultConfigs?.deno?.cjs;
+ /* c8 ignore stop */
const parallel =
hasArg('parallel') || hasArg('p', '-') || defaultConfigs?.parallel;
const quiet = hasArg('quiet') || hasArg('q', '-') || defaultConfigs?.quiet;
@@ -70,6 +73,7 @@ import { getConfigs } from '../parsers/options.js';
const tasks: Promise[] = [];
+ /* c8 ignore start */ // Process-based
if (killPort || defaultConfigs?.kill?.port) {
const ports =
killPort?.split(',').map(Number) || defaultConfigs?.kill?.port || [];
@@ -96,6 +100,7 @@ import { getConfigs } from '../parsers/options.js';
tasks.push(kill.pid(PIDs));
}
+ /* c8 ignore stop */
if (hasEnvFile || defaultConfigs?.envFile) {
const envFilePath = getArg('env-file') ?? defaultConfigs?.envFile;
@@ -104,6 +109,7 @@ import { getConfigs } from '../parsers/options.js';
}
const options: Configs = {
+ /* c8 ignore next 11 */ // Varies Platform
platform: platformIsValid(platform)
? platform
: hasArg('node')
@@ -152,6 +158,7 @@ import { getConfigs } from '../parsers/options.js';
let isRunning = false;
+ /* c8 ignore start */ // Process-based
const listenStdin = (input: Buffer | string) => {
if (isRunning || executing.size > 0) {
return;
@@ -167,6 +174,7 @@ import { getConfigs } from '../parsers/options.js';
startTests();
}
};
+ /* c8 ignore stop */
const resultsClear = () => {
fileResults.success.clear();
@@ -184,6 +192,7 @@ import { getConfigs } from '../parsers/options.js';
poku(dirs, options)
.then(() => {
if (watchMode) {
+ /* c8 ignore next 2 */ // Process-based
process.stdin.removeListener('data', listenStdin);
process.removeListener('SIGINT', onSigint);
resultsClear();
@@ -245,6 +254,7 @@ import { getConfigs } from '../parsers/options.js';
`${format('Watching:').bold()} ${format(dirs.join(', ')).underline()}`
);
+ /* c8 ignore next 2 */ // Process-based
process.stdin.setEncoding('utf-8');
process.stdin.on('data', listenStdin);
}
diff --git a/src/configs/poku.ts b/src/configs/poku.ts
index eb53deb2..8960d5c8 100644
--- a/src/configs/poku.ts
+++ b/src/configs/poku.ts
@@ -1,5 +1,6 @@
export const results = {
success: 0,
fail: 0,
- skipped: 0,
+ skip: 0,
+ todo: 0,
};
diff --git a/src/modules/essentials/poku.ts b/src/modules/essentials/poku.ts
index 710fba72..90d163c4 100644
--- a/src/modules/essentials/poku.ts
+++ b/src/modules/essentials/poku.ts
@@ -8,13 +8,13 @@ import { format, showTestResults } from '../../services/format.js';
import { isQuiet } from '../../parsers/output.js';
import { finalResults } from '../../configs/files.js';
-/* c8 ignore next 3 */ // Process-based
+/* c8 ignore start */ // Process-based
export const onSigint = () => {
process.stdout.write('\u001B[?25h');
};
-/* c8 ignore next */ // Process-based
process.once('SIGINT', onSigint);
+/* c8 ignore stop */
export async function poku(
targetPaths: string | string[],
@@ -33,8 +33,7 @@ export async function poku(
finalResults.started = new Date();
const start = process.hrtime();
- const prepareDirs = Array.prototype.concat(targetPaths);
- const dirs = prepareDirs.length > 0 ? prepareDirs : ['.'];
+ const dirs = Array.prototype.concat(targetPaths);
const showLogs = !isQuiet(configs);
// Sequential
@@ -62,7 +61,6 @@ export async function poku(
showLogs && showTestResults();
exit(code, configs?.quiet);
- return;
}
// Parallel
diff --git a/src/modules/helpers/describe.ts b/src/modules/helpers/describe.ts
index 43f359c3..01764515 100644
--- a/src/modules/helpers/describe.ts
+++ b/src/modules/helpers/describe.ts
@@ -3,16 +3,17 @@ 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 } from './it/todo.js';
-export async function describe(
+async function describeCore(
title: string,
cb: () => Promise
): Promise;
-export function describe(title: string, cb: () => unknown): void;
-export async function describe(cb: () => Promise): Promise;
-export function describe(cb: () => unknown): unknown;
-export function describe(title: string, options?: DescribeOptions): void;
-export async function describe(
+function describeCore(title: string, cb: () => unknown): void;
+async function describeCore(cb: () => Promise): Promise;
+function describeCore(cb: () => unknown): unknown;
+function describeCore(title: string, options?: DescribeOptions): void;
+async function describeCore(
arg1: string | (() => unknown | Promise),
arg2?: (() => unknown | Promise) | DescribeOptions
): Promise {
@@ -76,3 +77,7 @@ export async function describe(
);
}
}
+
+export const describe = Object.assign(describeCore, {
+ todo,
+});
diff --git a/src/modules/helpers/exit.ts b/src/modules/helpers/exit.ts
index 3f58fe30..16acfafc 100644
--- a/src/modules/helpers/exit.ts
+++ b/src/modules/helpers/exit.ts
@@ -6,8 +6,35 @@ import { Write } from '../../services/write.js';
import { fileResults, finalResults } from '../../configs/files.js';
import { parseTime, parseTimeToSecs } from '../../parsers/time.js';
-export const exit = (code: Code, quiet?: boolean) => {
+export const exit = (code: Code, quiet?: boolean): never => {
const isPoku = results.success > 0 || results.fail > 0;
+ const success = ` PASS › ${results.success - results.skip || 0} `;
+ const failure = ` FAIL › ${results.fail} `;
+ const skips = ` SKIP › ${results.skip} `;
+ const plans = ` TODO › ${results.todo} `;
+ const inline = results.skip === 0 || results.todo === 0;
+
+ let message = '';
+
+ if (inline) {
+ message += `${format(success).bg('green')} ${format(failure).bg(results.fail === 0 ? 'grey' : 'brightRed')}`;
+
+ if (results.skip) {
+ message += ` ${format(skips).bg('brightBlue')}`;
+ }
+
+ if (results.todo) {
+ message += ` ${format(plans).bg('brightBlue')}`;
+ }
+ } else {
+ message += `${format(success).success().bold()}\n`;
+ message +=
+ results.fail === 0
+ ? format(`${failure}\n`).bold()
+ : `${format(failure).fail().bold()}\n`;
+ message += `${format(skips).info().bold()}\n`;
+ message += `${format(plans).info().bold()}`;
+ }
!quiet &&
process.on('exit', (code) => {
@@ -23,9 +50,7 @@ export const exit = (code: Code, quiet?: boolean) => {
` ${format(`Test Files › ${format(String(fileResults.success.size + fileResults.fail.size)).bold()}`).dim()}`
);
Write.hr();
- Write.log(
- `${format(` PASS › ${results.success - results.skipped} `).bg('green')} ${format(` FAIL › ${results.fail} `).bg(results.fail === 0 ? 'grey' : 'red')} ${results.skipped > 0 ? format(` SKIPPED › ${results.skipped} `).bg(results.skipped === 0 ? 'grey' : 'blue') : ''}`
- );
+ Write.log(message);
Write.hr();
}
diff --git a/src/modules/helpers/it/core.ts b/src/modules/helpers/it/core.ts
index 7c133b75..584a85e5 100644
--- a/src/modules/helpers/it/core.ts
+++ b/src/modules/helpers/it/core.ts
@@ -3,6 +3,7 @@ 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 } from './todo.js';
async function itCore(
message: string,
@@ -89,4 +90,6 @@ async function itCore(
}
}
-export const it = Object.assign(itCore, {});
+export const it = Object.assign(itCore, {
+ todo,
+});
diff --git a/src/modules/helpers/it/todo.ts b/src/modules/helpers/it/todo.ts
new file mode 100644
index 00000000..0c4d0100
--- /dev/null
+++ b/src/modules/helpers/it/todo.ts
@@ -0,0 +1,9 @@
+import { Write } from '../../../services/write.js';
+import { indentation } from '../../../configs/indentation.js';
+import { format } from '../../../services/format.js';
+
+export const todo = (message: string, _cb?: () => unknown) => {
+ Write.log(
+ `${indentation.hasDescribe ? ' ' : ''}${format(`● ${message}`).cyan().bold()}`
+ );
+};
diff --git a/src/modules/helpers/list-files.ts b/src/modules/helpers/list-files.ts
index 0b9c2334..a0eca8c9 100644
--- a/src/modules/helpers/list-files.ts
+++ b/src/modules/helpers/list-files.ts
@@ -70,7 +70,7 @@ export const getAllFiles = async (
if (
fullPath.indexOf('node_modules') !== -1 ||
- fullPath.indexOf('.git') === 0
+ fullPath.indexOf('.git/') !== -1
) {
return;
}
diff --git a/src/modules/helpers/skip.ts b/src/modules/helpers/skip.ts
index eb0ee404..bff5356e 100644
--- a/src/modules/helpers/skip.ts
+++ b/src/modules/helpers/skip.ts
@@ -2,7 +2,7 @@ import { exit, env } from 'node:process';
import { Write } from '../../services/write.js';
import { format } from '../../services/format.js';
-export const skip = (message?: string) => {
+export const skip = (message = 'Skipping') => {
const isPoku = typeof env?.FILE === 'string' && env?.FILE.length > 0;
const FILE = env.FILE;
@@ -10,8 +10,8 @@ export const skip = (message?: string) => {
Write.log(
format(
isPoku
- ? `ℹ ${message} ${format('›').dim()} ${format(`${FILE}`).italic().gray().dim()}`
- : `ℹ ${message}`
+ ? `◯ ${message} ${format('›').dim()} ${format(`${FILE}`).italic().gray().dim()}`
+ : `◯ ${message}`
)
.info()
.bold()
diff --git a/src/parsers/output.ts b/src/parsers/output.ts
index 8fe9897d..b814f479 100644
--- a/src/parsers/output.ts
+++ b/src/parsers/output.ts
@@ -4,7 +4,8 @@ import { results } from '../configs/poku.js';
const regex = {
newLine: /\n/,
ansi: /u001b\[0m|\n/i,
- skipped: /^"\\u001b\[94m\\u001b\[1mℹ/i,
+ skip: /\\u001b\[94m\\u001b\[1m◯/i,
+ todo: /\\u001b\[96m\\u001b\[1m●/i,
} as const;
export const isQuiet = (configs?: Configs): boolean =>
@@ -20,8 +21,12 @@ export const parserOutput = (options: {
const { output, result, configs } = options;
const normalizedOutput = JSON.stringify(output);
- if (regex.skipped.test(normalizedOutput)) {
- ++results.skipped;
+ if (regex.skip.test(normalizedOutput)) {
+ ++results.skip;
+ }
+
+ if (regex.todo.test(normalizedOutput)) {
+ ++results.todo;
}
const debug = isDebug(configs);
diff --git a/src/services/format.ts b/src/services/format.ts
index c13cc479..35b826e7 100644
--- a/src/services/format.ts
+++ b/src/services/format.ts
@@ -79,6 +79,11 @@ export class Formatter {
return this;
}
+ cyan() {
+ this.parts += '\x1b[96m';
+ return this;
+ }
+
bg(color: keyof typeof backgroundColor) {
this.parts += `\x1b[${backgroundColor[color]}m\x1b[1m`;
return this;
diff --git a/src/services/watch.ts b/src/services/watch.ts
index 2938ee4d..0548efcb 100644
--- a/src/services/watch.ts
+++ b/src/services/watch.ts
@@ -77,18 +77,16 @@ export class Watcher {
}
public async start() {
- try {
- const stats = await stat(this.rootDir);
+ const stats = await stat(this.rootDir);
- if (stats.isDirectory()) {
- this.files = await listFiles(this.rootDir);
+ if (stats.isDirectory()) {
+ this.files = await listFiles(this.rootDir);
- this.watchFiles(this.files);
- await this.watchDirectory(this.rootDir);
- } else {
- this.watchFile(this.rootDir);
- }
- } catch {}
+ this.watchFiles(this.files);
+ await this.watchDirectory(this.rootDir);
+ } else {
+ this.watchFile(this.rootDir);
+ }
}
public stop() {
diff --git a/test/c8.test.ts b/test/c8.test.ts
index 75122097..45372c4d 100644
--- a/test/c8.test.ts
+++ b/test/c8.test.ts
@@ -21,7 +21,7 @@ test(async () => {
await describe('CLI', async () => {
await it('Sequential (Just Touch)', async () => {
const results = await inspectCLI(
- 'npx tsx src/bin/index.ts --platform=node --include=test/integration/import.test.ts'
+ 'npx tsx src/bin/index.ts --platform=node test/integration/import.test.ts'
);
console.log(results.stdout);
@@ -32,7 +32,7 @@ test(async () => {
await it('Parallel (Just Touch)', async () => {
const results = await inspectCLI(
- 'npx tsx src/bin/index.ts --platform=node --parallel --include=test/integration/import.test.ts'
+ 'npx tsx src/bin/index.ts --platform=node --parallel test/integration/import.test.ts'
);
console.log(results.stdout);
@@ -43,7 +43,7 @@ test(async () => {
await it('Parallel (FILTER Env)', async () => {
const results = await inspectCLI(
- 'npx tsx src/bin/index.ts --platform=node --parallel --include=test/integration',
+ 'npx tsx src/bin/index.ts --platform=node --parallel test/integration',
{
env: { ...process.env, FILTER: 'import' },
}
@@ -58,8 +58,8 @@ test(async () => {
await it('Sequential + Options (Just Touch)', async () => {
const results = await inspectCLI(
isWindows
- ? 'npx tsx src/bin/index.ts --concurrency=4 --platform=node --fast-fail --debug --exclude=".bak" --kill-port=4000 --kill-range="4000-4001" --include=test/integration/import.test.ts --filter=".test.|.spec."'
- : 'npx tsx src/bin/index.ts --concurrency=4 --platform=node --fast-fail --debug --exclude=.bak --kill-port=4000 --kill-range=4000-4001 --include=test/integration/import.test.ts --filter=.test.|.spec.'
+ ? 'npx tsx src/bin/index.ts --concurrency=4 --platform=node --fast-fail --debug --exclude=".bak" --kill-port=4000 --kill-range="4000-4001" test/integration/import.test.ts --filter=".test.|.spec."'
+ : 'npx tsx src/bin/index.ts --concurrency=4 --platform=node --fast-fail --debug --exclude=.bak --kill-port=4000 --kill-range=4000-4001 test/integration/import.test.ts --filter=.test.|.spec.'
);
console.log(results.stdout);
@@ -71,8 +71,8 @@ test(async () => {
await it('Parallel + Options (Just Touch)', async () => {
const results = await inspectCLI(
isWindows
- ? 'npx tsx src/bin/index.ts --parallel --concurrency=4 --platform=node --fast-fail --debug --exclude=".bak" --kill-port=4000 --kill-range="4000-4001" --include=test/integration/import.test.ts --filter=".test.|.spec."'
- : 'npx tsx src/bin/index.ts --parallel --concurrency=4 --platform=node --fast-fail --debug --exclude=.bak --kill-port=4000 --kill-range=4000-4001 --include=test/integration/import.test.ts --filter=.test.|.spec.'
+ ? 'npx tsx src/bin/index.ts --parallel --concurrency=4 --platform=node --fast-fail --debug --exclude=".bak" --kill-port=4000 --kill-range="4000-4001" test/integration/import.test.ts --filter=".test.|.spec."'
+ : 'npx tsx src/bin/index.ts --parallel --concurrency=4 --platform=node --fast-fail --debug --exclude=.bak --kill-port=4000 --kill-range=4000-4001 test/integration/import.test.ts --filter=.test.|.spec.'
);
console.log(results.stdout);
@@ -84,8 +84,8 @@ test(async () => {
await it('Parallel + Options (CLI Env Variables Propagation)', async () => {
const results = await inspectCLI(
isWindows
- ? 'npx tsx src/bin/index.ts --include=test/integration/env --env-file="fixtures/.env.test"'
- : 'npx tsx src/bin/index.ts --include=test/integration/env --env-file=fixtures/.env.test',
+ ? 'npx tsx src/bin/index.ts test/integration/env --env-file="fixtures/.env.test"'
+ : 'npx tsx src/bin/index.ts test/integration/env --env-file=fixtures/.env.test',
{
env: {
...env,
diff --git a/test/e2e/final-results.test.ts b/test/e2e/final-results.test.ts
new file mode 100644
index 00000000..b96d2496
--- /dev/null
+++ b/test/e2e/final-results.test.ts
@@ -0,0 +1,53 @@
+import { describe } from '../../src/modules/helpers/describe.js';
+import { it } from '../../src/modules/helpers/it/core.js';
+import { assert } from '../../src/modules/essentials/assert.js';
+import { inspectCLI, isProduction } from '../helpers/capture-cli.test.js';
+import { skip } from '../../src/modules/helpers/skip.js';
+
+if (isProduction) {
+ skip();
+}
+
+describe('Final Results', async () => {
+ await it('Skip', async () => {
+ const results = await inspectCLI('npx tsx ../../../src/bin/index.ts', {
+ cwd: './fixtures/final-results/skip',
+ });
+
+ assert.match(results.stdout, /PASS › 0/, 'Needs to pass 0');
+ assert.match(results.stdout, /FAIL › 0/, 'Needs to fail 0');
+ assert.match(results.stdout, /SKIP › 1/, 'Needs to skip 1');
+ });
+
+ await it('Todo', async () => {
+ const results = await inspectCLI('npx tsx ../../../src/bin/index.ts', {
+ cwd: './fixtures/final-results/todo',
+ });
+
+ assert.match(results.stdout, /PASS › 1/, 'Needs to pass 1');
+ assert.match(results.stdout, /FAIL › 0/, 'Needs to fail 0');
+ assert.match(results.stdout, /TODO › 1/, 'Needs to todo 1');
+ });
+
+ await it('Skip + Todo', async () => {
+ const results = await inspectCLI('npx tsx ../../../src/bin/index.ts', {
+ cwd: './fixtures/final-results/skip-and-todo',
+ });
+
+ assert.match(results.stdout, /PASS › 1/, 'Needs to pass 1');
+ assert.match(results.stdout, /FAIL › 0/, 'Needs to fail 0');
+ assert.match(results.stdout, /SKIP › 1/, 'Needs to todo 1');
+ assert.match(results.stdout, /TODO › 1/, 'Needs to todo 1');
+ });
+
+ await it('Skip + Todo + Failure', async () => {
+ const results = await inspectCLI('npx tsx ../../../src/bin/index.ts', {
+ cwd: './fixtures/final-results/skip-todo-and-failure',
+ });
+
+ assert.match(results.stdout, /PASS › 1/, 'Needs to pass 1');
+ assert.match(results.stdout, /FAIL › 1/, 'Needs to fail 1');
+ assert.match(results.stdout, /SKIP › 1/, 'Needs to todo 1');
+ assert.match(results.stdout, /TODO › 1/, 'Needs to todo 1');
+ });
+});
diff --git a/test/e2e/ignored-paths.test.ts b/test/e2e/ignored-paths.test.ts
new file mode 100644
index 00000000..bae8a6c1
--- /dev/null
+++ b/test/e2e/ignored-paths.test.ts
@@ -0,0 +1,42 @@
+import { join } from 'node:path';
+import { describe } from '../../src/modules/helpers/describe.js';
+import { it } from '../../src/modules/helpers/it/core.js';
+import { assert } from '../../src/modules/essentials/assert.js';
+import { inspectCLI, isProduction } from '../helpers/capture-cli.test.js';
+import { skip } from '../../src/modules/helpers/skip.js';
+import { accessSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
+
+if (isProduction) {
+ skip();
+}
+
+const createTestFile = (dirName: string) => {
+ try {
+ const baseDir = join('./fixtures/list-files', dirName);
+ const filePath = join(baseDir, 'a.test.js');
+
+ mkdirSync(baseDir, { recursive: true });
+
+ try {
+ accessSync(filePath);
+ } catch {
+ writeFileSync(filePath, '');
+ }
+ } catch {}
+};
+
+describe('List Files: node_modules and .git', async () => {
+ createTestFile('.git');
+ createTestFile('node_modules');
+
+ await it('Sequential', async () => {
+ const results = await inspectCLI('npx tsx ../../src/bin/index.ts', {
+ cwd: './fixtures/list-files',
+ });
+
+ assert.doesNotMatch(results.stdout, /PASS ›/, 'Needs to pass 0');
+ assert.doesNotMatch(results.stdout, /FAIL ›/, 'Needs to fail 0');
+ });
+
+ rmSync('./fixtures/list-files', { force: true, recursive: true });
+});
diff --git a/test/integration/describe/todo.test.ts b/test/integration/describe/todo.test.ts
new file mode 100644
index 00000000..44659e8e
--- /dev/null
+++ b/test/integration/describe/todo.test.ts
@@ -0,0 +1,9 @@
+import { describe } from '../../../src/modules/helpers/describe.js';
+
+describe('Testing "describe.todo" overloads', () => {
+ describe.todo('Basic todo');
+ describe.todo(
+ 'Ignore callback',
+ async () => await new Promise((_, reject) => reject(undefined))
+ );
+});
diff --git a/test/integration/it/it.test.ts b/test/integration/it/it.test.ts
index a650804a..1bca9dd3 100644
--- a/test/integration/it/it.test.ts
+++ b/test/integration/it/it.test.ts
@@ -2,7 +2,7 @@ import { test } from '../../../src/modules/helpers/test.js';
import { describe } from '../../../src/modules/helpers/describe.js';
import { it } from '../../../src/modules/helpers/it/core.js';
-test('Testing "it" method', () => {
+test('Testing "it" overloads', () => {
describe(async () => {
it(() => {});
it(() => true);
diff --git a/test/integration/it/todo.test.ts b/test/integration/it/todo.test.ts
new file mode 100644
index 00000000..a9edae7e
--- /dev/null
+++ b/test/integration/it/todo.test.ts
@@ -0,0 +1,10 @@
+import { describe } from '../../../src/modules/helpers/describe.js';
+import { it } from '../../../src/modules/helpers/it/core.js';
+
+describe('Testing "it.todo" overloads', () => {
+ it.todo('Basic todo');
+ it.todo(
+ 'Ignore callback',
+ async () => await new Promise((_, reject) => reject(undefined))
+ );
+});
diff --git a/test/integration/test/test.test.ts b/test/integration/test/test.test.ts
index 7d0b175a..87af8389 100644
--- a/test/integration/test/test.test.ts
+++ b/test/integration/test/test.test.ts
@@ -1,6 +1,6 @@
import { test } from '../../../src/modules/helpers/test.js';
-test('Testing "test" method', async () => {
+test('Testing "test" overloads', async () => {
test(() => {});
test(() => true);
test(() => false);
diff --git a/test/integration/test/todo.test.ts b/test/integration/test/todo.test.ts
new file mode 100644
index 00000000..3daae7ac
--- /dev/null
+++ b/test/integration/test/todo.test.ts
@@ -0,0 +1,10 @@
+import { describe } from '../../../src/modules/helpers/describe.js';
+import { test } from '../../../src/modules/helpers/test.js';
+
+describe('Testing "test.todo" overloads', () => {
+ test.todo('Basic todo');
+ test.todo(
+ 'Ignore callback',
+ async () => await new Promise((_, reject) => reject(undefined))
+ );
+});
diff --git a/test/unit/wait-for/wait-for-trhows.test.ts b/test/unit/wait-for/wait-for-trhows.test.ts
new file mode 100644
index 00000000..c70b4c63
--- /dev/null
+++ b/test/unit/wait-for/wait-for-trhows.test.ts
@@ -0,0 +1,50 @@
+import { test } from '../../../src/modules/helpers/test.js';
+import { assert } from '../../../src/modules/essentials/assert.js';
+import {
+ sleep,
+ waitForExpectedResult,
+ waitForPort,
+} from '../../../src/modules/helpers/wait-for.js';
+
+test('Wait For Expected Result: Throws', async () => {
+ await assert.rejects(
+ // @ts-expect-error
+ async () => await sleep(undefined),
+ 'Invalid milliseconds'
+ );
+ await assert.rejects(
+ // @ts-expect-error
+ async () => await waitForExpectedResult(undefined, true),
+ 'Invalid callback'
+ );
+ await assert.rejects(
+ async () =>
+ await waitForExpectedResult(() => true, true, {
+ // @ts-expect-error
+ interval: true,
+ }),
+ 'Invalid interval'
+ );
+ await assert.rejects(
+ async () =>
+ await waitForExpectedResult(() => true, true, {
+ // @ts-expect-error
+ timeout: true,
+ }),
+ 'Invalid timeout'
+ );
+ await assert.rejects(
+ async () =>
+ await waitForExpectedResult(() => true, true, {
+ // @ts-expect-error
+ delay: true,
+ }),
+ 'Invalid delay'
+ );
+ await assert.rejects(
+ async () =>
+ // @ts-expect-error
+ await waitForPort(undefined),
+ 'Invalid port'
+ );
+});
diff --git a/website/README.md b/website/README.md
index 2b18280d..9ae49351 100644
--- a/website/README.md
+++ b/website/README.md
@@ -1,3 +1,3 @@
# Website
-This [website](https://poku.io) is built using [Docusaurus 3](https://docusaurus.io/), a modern static website generator and [SVPS](https://github.com/wellwelwel/svps) to deploy it.
+This [website](https://poku.io) is built using [**Docusaurus 3**](https://docusaurus.io/), a modern static website generator and [**SVPS**](https://github.com/wellwelwel/svps) to deploy it.
diff --git a/website/docs/documentation/helpers/startScript.mdx b/website/docs/documentation/helpers/startScript.mdx
index 676c6085..9191b9cd 100644
--- a/website/docs/documentation/helpers/startScript.mdx
+++ b/website/docs/documentation/helpers/startScript.mdx
@@ -1,6 +1,6 @@
---
sidebar_position: 7
-tags: [background, server, service, package.json, scripts]
+tags: [background, server, service, package.json, scripts, supertest]
---
import Tabs from '@theme/Tabs';
diff --git a/website/docs/documentation/helpers/startService.mdx b/website/docs/documentation/helpers/startService.mdx
index 2d1dbd24..996b745f 100644
--- a/website/docs/documentation/helpers/startService.mdx
+++ b/website/docs/documentation/helpers/startService.mdx
@@ -1,6 +1,6 @@
---
sidebar_position: 8
-tags: [background, server, service]
+tags: [background, server, service, supertest]
---
import Tabs from '@theme/Tabs';
diff --git a/website/docs/documentation/helpers/todo.mdx b/website/docs/documentation/helpers/todo.mdx
new file mode 100644
index 00000000..aa0e03f5
--- /dev/null
+++ b/website/docs/documentation/helpers/todo.mdx
@@ -0,0 +1,61 @@
+---
+sidebar_position: 10
+tags: [boilerplate]
+---
+
+# 📋 todo
+
+`.todo` is an extended helper for `describe`, `it`, and `test` to assist you plan future tests.
+
+## Basic Usage
+
+### Simple message
+
+```ts
+import { describe, it, test } from 'poku';
+
+describe.todo('todo: Upcoming test');
+
+it.todo('todo: Upcoming test');
+
+test.todo('todo: Upcoming test');
+```
+
+- There is no difference between the features.
+
+Also in internal contexts:
+
+```ts
+import { describe, it } from 'poku';
+
+describe(() => {
+ it.todo('todo: Upcoming test');
+
+ it('Real test', () => {
+ /* ... */
+ });
+});
+```
+
+### Ignoring a callback
+
+This can be useful when you already have an idea or prototype of what you want to test, but you don't want the test to actually run.
+It can also be useful for tests that have unexpectedly stopped working due to some external event, requiring further attention.
+
+```ts
+import { describe, it } from 'poku';
+
+describe.todo('todo: Upcoming test', () => {
+ it(async () => {
+ process.exit(1);
+ });
+});
+```
+
+- The method received by `todo` and everything inside it will be completely ignored.
+
+
+
+:::note
+When using `beforeEach` or `afterEach`, they will not be triggered by tests with `.todo`.
+:::
diff --git a/website/docs/documentation/poku/config-files.mdx b/website/docs/documentation/poku/config-files.mdx
index 37d7c7f6..54cc136d 100644
--- a/website/docs/documentation/poku/config-files.mdx
+++ b/website/docs/documentation/poku/config-files.mdx
@@ -43,7 +43,7 @@ By default, **Poku** comes with the most common usage pre-set, but you can confi
Pros: Supports functions and regex.
- Cons: Needs to be an CommonJS file.
+ Cons: Needs to be a CommonJS file.
>
}
@@ -55,7 +55,7 @@ Create a `poku.config.js` (or `poku.config.cjs` when using `"type": "module"` in
const { defineConfig } = require('poku');
module.exports = defineConfig({
- include: ['.'],
+ include: ['.'], // Doesn't support glob patterns
parallel: false,
debug: false,
filter: /\.(test.|.spec)\./,
@@ -107,7 +107,7 @@ Create a `.pokurc.json` (or `.pokurc.jsonc`) in your project's root directory, f
```js
{
"$schema": "https://poku.io/schemas/configs.json",
- "include": ["."],
+ "include": ["."], // Doesn't support glob patterns
"parallel": false,
"debug": false,
"filter": ".test.|.spec.", // regex as string
diff --git a/website/docs/documentation/poku/include-files.mdx b/website/docs/documentation/poku/include-files.mdx
index 4034190c..c316fa1c 100644
--- a/website/docs/documentation/poku/include-files.mdx
+++ b/website/docs/documentation/poku/include-files.mdx
@@ -45,6 +45,12 @@ npx poku --parallel
- Run all tests in parallel.
+```bash
+npx poku ./test
+```
+
+- Run all tests in `./test` directory.
+
:::tip
You can pass both directories and files.
:::
@@ -55,11 +61,7 @@ It's not possible to run tests in the `.git` and `node_modules` directories.
-### By setting the directories as the last argument
-
-```bash
-npx poku targetPath
-```
+### By setting multiple paths
```bash
npx poku targetPathA targetPathB
diff --git a/website/docs/examples/local-server.mdx b/website/docs/examples/local-server.mdx
index ab2683f7..e613bf7a 100644
--- a/website/docs/examples/local-server.mdx
+++ b/website/docs/examples/local-server.mdx
@@ -1,5 +1,6 @@
---
sidebar_position: 1
+tags: [background, server, service, package.json, scripts, supertest]
---
import Tabs from '@theme/Tabs';
diff --git a/website/docs/philosophy.mdx b/website/docs/philosophy.mdx
index f9d6b13d..17ff4b45 100644
--- a/website/docs/philosophy.mdx
+++ b/website/docs/philosophy.mdx
@@ -3,7 +3,7 @@ import TabItem from '@theme/TabItem';
# Philosophy
-**Poku**'s philosophy focuses on simplicity and efficiency, removing complexities and boilerplate to make testing accessible for the simplest to the most complex projects.
+**Poku**'s philosophy consists of simplicity and efficiency, removing complexities and boilerplate requirements to make testing accessible for the simplest to the most complex projects.
@@ -291,9 +291,11 @@ Although not a priority, there are plans to integrate the following features int
They aren't considered breaking changes:
-- Formatting and style changes to outputs.
-- New functionalities that depend from a specific platform version.
-- If a feature is no longer useful due to a new approach.
+- Formatting and style changes to outputs _(including reporters — soon)_.
+- New functionalities that depend from a specific platform version:
+ - As long as it doesn't affect basic usability.
+ - E.g., when using **Node.js** previous to `v15.x.x`, the `strict` method isn't available.
+- If a feature is no longer useful due to a new approach _(as long as it doesn't affect the end user)_.
- _JSON_ intellisense schema changes _(config files)_.
@@ -306,5 +308,5 @@ They aren't considered breaking changes:
- Although these points are taken into consideration, the main aim is to maintain a balance between good practices.
:::danger
-Note that **Poku** has a different way of being used, inspired entirely by the essence of native JavaScript, which can be both an advantage and a disadvantage for those who are used to the traditional _hooks_ of other test runners.
+Note that **Poku** has a different way of being used, inspired entirely by the essence of native **JavaScript**, which can be both an advantage and a disadvantage for those who are used to the traditional _hooks_ of other test runners.
:::
diff --git a/website/docs/tutorials/beginner.mdx b/website/docs/tutorials/beginner.mdx
index 6e8dbc05..c78a3d36 100644
--- a/website/docs/tutorials/beginner.mdx
+++ b/website/docs/tutorials/beginner.mdx
@@ -1,5 +1,5 @@
---
-title: Beginner
+title: 🐣 Beginner
description: From a basic assertion test to its execution.
tags: [assert, assertion, tutorial, beginner, roadmap]
sidebar_position: 0
@@ -10,7 +10,7 @@ import Junior from '@site/static/img/junior.svg';
-# Beginner Tutorial
+# 🐣 Beginner Tutorial
- From a basic assertion test to its execution.
diff --git a/website/docs/tutorials/cross-platform.mdx b/website/docs/tutorials/cross-platform.mdx
index 7f2bab41..a529dda3 100644
--- a/website/docs/tutorials/cross-platform.mdx
+++ b/website/docs/tutorials/cross-platform.mdx
@@ -1,5 +1,5 @@
---
-title: Testing Across Platforms
+title: 👩🏼🚀 Testing Across Platforms
description: Running the same test suite on different platforms.
tags: [cross-platform, Node.js, Bun, Deno, tutorial, roadmap]
sidebar_position: 3
@@ -12,7 +12,7 @@ import Maintainer from '@site/static/img/maintainer.svg';
-# Testing Across Platforms
+# 👩🏼🚀 Testing Across Platforms
- Running the same test suite on different platforms.
@@ -38,7 +38,7 @@ npx poku
npx poku --node
```
-- It calls **Poku** through **Node.js**, but runs all the tests using **Node.js**.
+- It calls **Poku** through **Node.js** and runs all the tests using **Node.js**.
```sh
npx poku --bun
diff --git a/website/docs/tutorials/good-practices.mdx b/website/docs/tutorials/good-practices.mdx
index 1bf124ca..f3ef673a 100644
--- a/website/docs/tutorials/good-practices.mdx
+++ b/website/docs/tutorials/good-practices.mdx
@@ -1,5 +1,5 @@
---
-title: Good Practices
+title: 🪴 Good Practices
description: Organizing tests for different needs, requirements and approaches.
tags: [assert, assertion, test, describe, it, tutorial, roadmap]
sidebar_position: 1
@@ -12,7 +12,7 @@ import MidLevel from '@site/static/img/mid-level.svg';
-# Good Practices
+# 🪴 Good Practices
- Organizing tests for different needs, requirements and approaches.
diff --git a/website/sidebars.ts b/website/sidebars.ts
index 952c0b5f..57b3fccf 100644
--- a/website/sidebars.ts
+++ b/website/sidebars.ts
@@ -4,6 +4,7 @@ const sidebars: SidebarsConfig = {
docs: [
'index',
'philosophy',
+ 'comparing',
{
type: 'category',
label: 'Documentation',
@@ -15,23 +16,22 @@ const sidebars: SidebarsConfig = {
},
{
type: 'category',
- label: 'Examples',
- collapsed: true,
+ label: 'Quick Tutorials',
+ collapsed: false,
link: {
type: 'generated-index',
},
- items: [{ type: 'autogenerated', dirName: 'examples' }],
+ items: [{ type: 'autogenerated', dirName: 'tutorials' }],
},
{
type: 'category',
- label: 'Quick Tutorials',
+ label: 'Examples',
collapsed: false,
link: {
type: 'generated-index',
},
- items: [{ type: 'autogenerated', dirName: 'tutorials' }],
+ items: [{ type: 'autogenerated', dirName: 'examples' }],
},
- 'comparing',
],
};