diff --git a/.github/workflows/ci-coverage.yml b/.github/workflows/ci-coverage.yml index 1ae0ce6d..90a62e37 100644 --- a/.github/workflows/ci-coverage.yml +++ b/.github/workflows/ci-coverage.yml @@ -9,6 +9,7 @@ on: jobs: coverage: runs-on: ubuntu-latest + timeout-minutes: 1 name: Coverage steps: - name: ➕ Actions - Checkout @@ -30,7 +31,7 @@ jobs: run: npm ci - name: 🧪 Checking for Coverage - run: npm run test:ci:c8 + run: npm run test:c8 - name: ☔️ Upload coverage reports to Codecov uses: codecov/codecov-action@v4 diff --git a/README.md b/README.md index 0653fb3e..6a32612c 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ Enjoying **Poku**? Consider giving him a star ⭐️ ## Why Poku? -By creating **Poku**, my aim is to show that testing can be simpler 🌱 +**Poku** can show you how simple testing can be 🌱 - No configurations - Supports **ESM** and **CJS** @@ -127,6 +127,8 @@ assert(true, 'Poku will describe it 🐷'); +> Note that these examples use [**ESM**](https://poku.io/docs/examples/cjs-esm), but you can use [**CJS**](https://poku.io/docs/examples/cjs-esm) as well. + ### Run it 🚀 @@ -171,8 +173,10 @@ deno run npm:poku ### Essentials -- `poku` (_test runner_) -- `assert` and `assertPromise` (_test assertion_) +- [**poku**](https://poku.io/docs/category/poku) (_test runner_) +- [**assert**](https://poku.io/docs/documentation/assert) (_test assertion_) +- [**startScript**](https://poku.io/docs/documentation/startScript) (_run `package.json` scripts in a background process_) +- [**startService**](https://poku.io/docs/documentation/startService) (_run files in a background process_) ### Helpers diff --git a/package.json b/package.json index 8977fa34..7b230abf 100644 --- a/package.json +++ b/package.json @@ -4,19 +4,18 @@ "description": "🐷 Poku makes testing easy for Node.js, Bun & Deno at the same time.", "main": "./lib/index.js", "scripts": { - "test": "tsx --tsconfig ./tsconfig.test.json ./test/run.test.ts", + "test": "tsx ./test/run.test.ts", "pretest:c8": "npm run build", - "test:c8": "docker compose -f test/docker/docker-compose.c8.yml up", - "test:ci:c8": "c8 --include 'src/**' --exclude 'src/@types/**' --reporter=text --reporter=lcov tsx test/run.test.ts", + "test:c8": "c8 --include 'src/**' --exclude 'src/@types/**' --reporter=text --reporter=lcov npx poku --parallel --debug test/unit,test/integration,test/e2e", "test:ci": "tsx ./test/ci.test.ts", "test:node": "FILTER='node-' npm run test:ci", "test:deno": "FILTER='deno-' npm run test:ci", "test:bun": "FILTER='bun-' npm run test:ci", "predocker:deno": "docker compose -f ./test/docker/playground/deno/docker-compose.yml down", "docker:deno": "docker compose -f ./test/docker/playground/deno/docker-compose.yml up --build", - "prebuild": "rm -rf ./lib ./ci", + "clear": "rm -rf ./lib ./ci", "build": "tsc && tsc -p tsconfig.test.json", - "postbuild": "tsx ./tools/compatibility/node.ts && chmod +x lib/bin/index.js && npm audit", + "postbuild": "tsx ./tools/compatibility/node.ts && chmod +x lib/bin/index.js", "eslint:checker": "eslint . --ext .js,.ts", "eslint:fix": "eslint . --fix --config ./.eslintrc.json", "lint:checker": "npm run eslint:checker && npm run prettier:checker", @@ -41,9 +40,9 @@ "assert", "assertion", "testing", - "run", - "isolate", - "isolation", + "bun", + "deno", + "cli", "concurrent", "concurrency", "parallelism", @@ -52,22 +51,31 @@ "unit", "integration", "typescript", + "isolate", + "isolation", + "run", "queue", "queuing", "nodejs", "node", - "bun", - "deno", - "cli", "cli-app", "expect", "mocha", + "chai", "jest", "ava", "tap", "tape", "karma", "urun", + "supertest", + "e2e", + "end-to-end", + "tdd", + "bdd", + "framework", + "tool", + "tools", "filter", "exclude", "list", diff --git a/src/@types/background-process.ts b/src/@types/background-process.ts new file mode 100644 index 00000000..498328e2 --- /dev/null +++ b/src/@types/background-process.ts @@ -0,0 +1,42 @@ +import { Runner } from './runner.js'; +import { Configs } from './poku.js'; + +type BackgroundProcessOptions = { + /** + * - By default, it will resolve in the first console output + * - By setting a string: it will wait for a specifc string on console output to resolve + * - By setting a number: it will wait for time in milliseconds to resolve + * + * @default undefined + */ + startAfter?: string | number; + /** + * Stops the service after: + * @default 60000 + */ + timeout?: number; + /** + * Shows the output from service + */ + verbose?: boolean; + /** + * Specify a target path to start the process + * + * @default "./" + */ + cwd?: string | undefined; +}; + +export type StartScriptOptions = { + /** + * By default, Poku will use `npm`. Change it as you want. + */ + readonly runner?: Runner; +} & BackgroundProcessOptions; + +export type StartServiceOptions = { + /** + * By default, Poku will try to identify the actual platform, but you can specify it manually + */ + readonly platform?: Configs['platform']; +} & BackgroundProcessOptions; diff --git a/src/@types/runner.ts b/src/@types/runner.ts new file mode 100644 index 00000000..1487c030 --- /dev/null +++ b/src/@types/runner.ts @@ -0,0 +1 @@ +export type Runner = 'npm' | 'bun' | 'deno' | 'yarn' | 'pnpm'; diff --git a/src/helpers/runner.ts b/src/helpers/runner.ts index 60c8a65d..b9b0015c 100644 --- a/src/helpers/runner.ts +++ b/src/helpers/runner.ts @@ -1,12 +1,40 @@ +import process from 'node:process'; import path from 'node:path'; import { getRuntime } from './get-runtime.js'; import { Configs } from '../@types/poku.js'; +import { Runner } from '../@types/runner.js'; + +const isWindows = process.platform === 'win32'; export const runner = (filename: string, configs?: Configs): string[] => { const runtime = getRuntime(configs); + // Bun if (runtime === 'bun') return ['bun']; + + // Deno if (runtime === 'deno') return ['deno', 'run', '--allow-read', '--allow-env', '--allow-run']; - return path.extname(filename) === '.ts' ? ['tsx'] : ['node']; + + // Node.js + return path.extname(filename) === '.ts' + ? [isWindows ? 'npx.cmd' : 'npx', 'tsx'] + : ['node']; +}; + +export const scriptRunner = (runner: Runner): string[] => { + // Bun + if (runner === 'bun') return ['bun']; + + // Deno + if (runner === 'deno') return ['deno', 'task']; + + // Yarn + if (runner === 'yarn') return ['yarn']; + + // PNPM + if (runner === 'pnpm') return ['pnpm', 'run']; + + // Node.js + return ['npm', 'run']; }; diff --git a/src/index.ts b/src/index.ts index 4aacab82..c39acca2 100755 --- a/src/index.ts +++ b/src/index.ts @@ -6,6 +6,11 @@ export { assertPromise } from './modules/assert-promise.js'; export { beforeEach, afterEach } from './modules/each.js'; export { publicListFiles as listFiles } from './modules/list-files.js'; export { test } from './modules/test.js'; -export type { Code } from './@types/code.ts'; -export type { Configs } from './@types/poku.ts'; -export type { Configs as ListFilesConfigs } from './@types/list-files.ts'; +export { startService, startScript } from './modules/create-service.js'; +export type { Code } from './@types/code.js'; +export type { Configs } from './@types/poku.js'; +export type { Configs as ListFilesConfigs } from './@types/list-files.js'; +export type { + StartServiceOptions, + StartScriptOptions, +} from './@types/background-process.js'; diff --git a/src/modules/assert-promise.ts b/src/modules/assert-promise.ts index fcb71719..22b1868d 100644 --- a/src/modules/assert-promise.ts +++ b/src/modules/assert-promise.ts @@ -286,7 +286,7 @@ const match = async ( message?: ParseAssertionOptions['message'] ): Promise => { if (typeof version === 'number' && version < 12) { - throw new Error('doesNotMatch is available from Node.js 12 or higher'); + throw new Error('match is available from Node.js 12 or higher'); } await parseAssertion(() => nodeAssert?.match(value, regExp), { diff --git a/src/modules/assert.ts b/src/modules/assert.ts index 670c1bf8..96fdf89e 100644 --- a/src/modules/assert.ts +++ b/src/modules/assert.ts @@ -278,7 +278,7 @@ const match = ( message?: ParseAssertionOptions['message'] ): void => { if (typeof version === 'number' && version < 12) { - throw new Error('doesNotMatch is available from Node.js 12 or higher'); + throw new Error('match is available from Node.js 12 or higher'); } parseAssertion(() => nodeAssert?.match(value, regExp), { diff --git a/src/modules/create-service.ts b/src/modules/create-service.ts new file mode 100644 index 00000000..aaa163bb --- /dev/null +++ b/src/modules/create-service.ts @@ -0,0 +1,122 @@ +import process from 'node:process'; +import { spawn } from 'node:child_process'; +import { runner, scriptRunner } from '../helpers/runner.js'; +import path from 'node:path'; +import { + StartScriptOptions, + StartServiceOptions, +} from '../@types/background-process.js'; +import { sanitizePath } from './list-files.js'; + +const backgroundProcess = ( + runtime: string, + args: string[], + file: string, + options?: StartServiceOptions +): Promise<{ end: () => boolean }> => + new Promise((resolve, reject) => { + let isResolved = false; + + const service = spawn(runtime, args, { + stdio: ['inherit', 'pipe', 'pipe'], + shell: false, + cwd: options?.cwd ? sanitizePath(path.normalize(options.cwd)) : undefined, + env: process.env, + detached: true, + }); + + const end = () => { + process.kill(-service.pid!, 'SIGKILL'); + return true; + }; + + service.stdout.on('data', (data: Buffer) => { + if (!isResolved && typeof options?.startAfter !== 'number') { + const stringData = String(data); + + if ( + typeof options?.startAfter === 'undefined' || + (typeof options?.startAfter === 'string' && + stringData.includes(options.startAfter)) + ) { + resolve({ end }); + clearTimeout(timeout); + + isResolved = true; + } + } + + options?.verbose && console.log(String(data)); + }); + + service.stderr.on('data', (data: Buffer) => { + reject(new Error(`Service failed to start: ${data}`)); + }); + + service.on('error', (err) => { + reject(new Error(`Service failed to start: ${err}`)); + }); + + service.on('close', (code) => { + if (code !== 0) reject(new Error(`Service exited with code ${code}`)); + }); + + const timeout = setTimeout(() => { + if (!isResolved) { + service.kill(); + reject(`createService: Timeout\nFile: ${file}`); + } + }, options?.timeout || 10000); + + if (typeof options?.startAfter === 'number') { + setTimeout(() => { + if (!isResolved) { + resolve({ end }); + clearTimeout(timeout); + + isResolved = true; + } + }, options.startAfter); + } + }); + +/** + * + * Starts a file in a background process + * + * Useful for servers, APIs, etc. + */ +export const startService = async ( + file: string, + options?: StartServiceOptions +): Promise<{ end: () => boolean }> => { + const runtimeOptions = runner(file, { platform: options?.platform }); + const runtime = runtimeOptions.shift()!; + const runtimeArgs = [...runtimeOptions, file]; + + return await backgroundProcess( + runtime, + runtimeArgs, + path.normalize(sanitizePath(file)), + options + ); +}; + +/** + * + * Starts a script (package.json) or task (deno.json) in a background process + * + * By default, it uses **npm**, but you can costumize it using the `runner` option. + * + * Useful for servers, APIs, etc. + */ +export const startScript = async ( + script: string, + options?: StartScriptOptions +): Promise<{ end: () => boolean }> => { + const runtimeOptions = scriptRunner(options?.runner || 'npm'); + const runtime = runtimeOptions.shift()!; + const runtimeArgs = [...runtimeOptions, script]; + + return await backgroundProcess(runtime, runtimeArgs, script, options); +}; diff --git a/src/modules/describe.ts b/src/modules/describe.ts index 5787d7d9..ba37d945 100644 --- a/src/modules/describe.ts +++ b/src/modules/describe.ts @@ -22,7 +22,7 @@ export type DescribeOptions = { * By default **Poku** only shows outputs generated from itself. * This helper allows you to use an alternative to `console.log` with **Poku**. * - * Need to debug? Just use the [`debug`](https://poku.io/docs/documentation/poku/configs/debug) option from `poku`. + * Need to debug? Just use the [`debug`](https://poku.io/docs/documentation/poku/options/debug) option from `poku`. */ export const log = (message: string) => console.log(`\x1b[0m${message}\x1b[0m`); diff --git a/src/services/run-test-file.ts b/src/services/run-test-file.ts index 4976aff6..cbd87dd5 100644 --- a/src/services/run-test-file.ts +++ b/src/services/run-test-file.ts @@ -1,6 +1,6 @@ import process from 'node:process'; -import { EOL } from 'node:os'; import path from 'node:path'; +import { EOL } from 'node:os'; import { spawn } from 'node:child_process'; import { runner } from '../helpers/runner.js'; import { indentation } from '../helpers/indentation.js'; @@ -26,15 +26,8 @@ export const runTestFile = ( ): Promise => new Promise(async (resolve) => { const runtimeOptions = runner(filePath, configs); - const originalRuntime = runtimeOptions.shift(); - let runtime = originalRuntime; - let runtimeArguments = - runtimeOptions.length > 1 ? [...runtimeOptions, filePath] : [filePath]; - - if (process.platform === 'win32' && originalRuntime === 'tsx') { - runtime = 'npx.cmd'; - runtimeArguments = ['tsx', ...runtimeArguments]; - } + const runtime = runtimeOptions.shift()!; + const runtimeArguments = [...runtimeOptions, filePath]; const fileRelative = path.relative(process.cwd(), filePath); const showLogs = !isQuiet(configs); @@ -103,7 +96,7 @@ export const runTestFile = ( if (!(await beforeEach(fileRelative, configs))) return false; // Export spawn helper is not an option - const child = spawn(runtime!, runtimeArguments, { + const child = spawn(runtime, runtimeArguments, { stdio: ['inherit', 'pipe', 'pipe'], shell: false, env: { diff --git a/test/docker/docker-compose.c8.yml b/test/docker/docker-compose.c8.yml deleted file mode 100644 index a3b48cbe..00000000 --- a/test/docker/docker-compose.c8.yml +++ /dev/null @@ -1,13 +0,0 @@ -version: '3.9' - -services: - coverage: - container_name: 'coverage' - image: node:lts-alpine - working_dir: /usr/app - volumes: - - ${PWD}/ci:/usr/app/ - - ${PWD}/node_modules:/usr/app/node_modules/:ro - environment: - NODE_ENV: production - command: npx c8 --include "src/**" --exclude "src/@types/**" --reporter=text --reporter=lcov node test/run.test.js diff --git a/test/e2e/node/background-process.test.ts b/test/e2e/node/background-process.test.ts new file mode 100644 index 00000000..4a5b70e6 --- /dev/null +++ b/test/e2e/node/background-process.test.ts @@ -0,0 +1,54 @@ +import process from 'node:process'; +import { + startService, + assert, + test, + describe, + startScript, +} from '../../../src/index.js'; +import { legacyFetch } from '../../helpers/legacy-fetch.test.js'; + +const isProduction = process.env.NODE_ENV === 'production'; +const ext = isProduction ? 'js' : 'ts'; + +test(async () => { + describe('Start Service', { background: false, icon: '🔀' }); + + const server = await startService(`server-a.${ext}`, { + startAfter: 'ready', + cwd: 'test/fixtures/server', + timeout: 10000, + }); + + const res = await legacyFetch('localhost', 4000); + + assert.strictEqual(res?.statusCode, 200, 'Service is on'); + assert.deepStrictEqual( + JSON.parse(res?.body), + { name: 'Poku' }, + 'Poku service is online' + ); + + server.end(); +}); + +test(async () => { + describe('Start Script', { background: false, icon: '🔀' }); + + const server = await startScript(`start:b:${ext}`, { + startAfter: 'ready', + cwd: 'test/fixtures/server', + timeout: 10000, + }); + + const res = await legacyFetch('localhost', 4001); + + assert.strictEqual(res?.statusCode, 200, 'Script is on'); + assert.deepStrictEqual( + JSON.parse(res?.body), + { name: 'Poku' }, + 'Poku script is online' + ); + + server.end(); +}); diff --git a/test/integration/cli.test.ts b/test/e2e/node/cli.test.ts similarity index 50% rename from test/integration/cli.test.ts rename to test/e2e/node/cli.test.ts index e3f3a0c6..84ecaea4 100644 --- a/test/integration/cli.test.ts +++ b/test/e2e/node/cli.test.ts @@ -1,28 +1,19 @@ -import process from 'node:process'; import { spawn } from 'node:child_process'; -import { assert } from '../../src/index.js'; -import { runner } from '../../src/helpers/runner.js'; +import { assert, describe, test } from '../../../src/index.js'; +import { runner } from '../../../src/helpers/runner.js'; // `/_.ts`: Simulate TypeScript file for Deno const currentFile = typeof __filename === 'string' ? __filename : '/_.ts'; const runtimeOptions = runner(currentFile); -const originalRuntime = runtimeOptions.shift(); -let runtime = originalRuntime!; +const runtime = runtimeOptions.shift()!; const ext = runtime === 'node' ? 'js' : 'ts'; const executeCLI = (args: string[]): Promise => new Promise((resolve, reject) => { - let runtimeArguments = - runtimeOptions.length > 1 ? [...runtimeOptions, ...args] : [...args]; - - if (process.platform === 'win32' && originalRuntime === 'tsx') { - runtime = 'npx.cmd'; - runtimeArguments = ['tsx', ...runtimeArguments]; - } + const runtimeArguments = [...runtimeOptions, ...args]; const childProcess = spawn(runtime, runtimeArguments, { shell: false, - cwd: process.cwd(), }); let output: string = ''; @@ -35,6 +26,10 @@ const executeCLI = (args: string[]): Promise => reject(data.toString()); }); + childProcess.on('error', (error: Buffer) => { + reject(error.toString()); + }); + childProcess.on('close', (code: number) => { if (code === 0) { resolve(output); @@ -44,11 +39,14 @@ const executeCLI = (args: string[]): Promise => }); }); -executeCLI([`./src/bin/index.${ext}`, `test/integration/code.test.${ext}`]) - .then((output) => { - assert.match(JSON.stringify(output), /PASS › 1/, 'CLI needs to pass 1'); - assert.match(JSON.stringify(output), /FAIL › 0/, 'CLI needs to fail 0'); - }) - .catch((error) => { - console.error('CLI test failed:', error); - }); +test(async () => { + describe('Poku Test Runner: CLI', { background: false, icon: '🐷' }); + + const output = await executeCLI([ + `./src/bin/index.${ext}`, + `test/integration/code.test.${ext}`, + ]); + + assert(/PASS › 1/.test(JSON.stringify(output)), 'CLI needs to pass 1'); + assert(/FAIL › 0/.test(JSON.stringify(output)), 'CLI needs to fail 0'); +}); diff --git a/test/fixtures/server/package.json b/test/fixtures/server/package.json new file mode 100644 index 00000000..bcb51eba --- /dev/null +++ b/test/fixtures/server/package.json @@ -0,0 +1,8 @@ +{ + "scripts": { + "start:a:ts": "tsx server-a.ts", + "start:a:js": "node server-a.js", + "start:b:ts": "tsx server-b.ts", + "start:b:js": "node server-b.js" + } +} diff --git a/test/fixtures/server/server-a.ts b/test/fixtures/server/server-a.ts new file mode 100644 index 00000000..1e108965 --- /dev/null +++ b/test/fixtures/server/server-a.ts @@ -0,0 +1,8 @@ +import http from 'node:http'; + +const server = http.createServer((_, res) => { + res.writeHead(200, { 'Content-Type': 'application/json' }); + res.end(JSON.stringify({ name: 'Poku' })); +}); + +server.listen(4000, () => console.log("I'm ready 🚀")); diff --git a/test/fixtures/server/server-b.ts b/test/fixtures/server/server-b.ts new file mode 100644 index 00000000..1bfc95dd --- /dev/null +++ b/test/fixtures/server/server-b.ts @@ -0,0 +1,8 @@ +import http from 'node:http'; + +const server = http.createServer((_, res) => { + res.writeHead(200, { 'Content-Type': 'application/json' }); + res.end(JSON.stringify({ name: 'Poku' })); +}); + +server.listen(4001, () => console.log("I'm ready 🚀")); diff --git a/test/helpers/legacy-fetch.test.ts b/test/helpers/legacy-fetch.test.ts new file mode 100644 index 00000000..c7af28a3 --- /dev/null +++ b/test/helpers/legacy-fetch.test.ts @@ -0,0 +1,33 @@ +import http from 'node:http'; + +export const legacyFetch = ( + hostname: string, + port: number +): Promise<{ statusCode?: number; body: string }> => { + const options = { + hostname, + port, + path: '/', + method: 'GET', + }; + + return new Promise((resolve, reject) => { + const req = http.request(options, (res) => { + let data = ''; + + res.on('data', (chunk) => { + data += chunk; + }); + + res.on('end', () => { + resolve({ statusCode: res.statusCode, body: data }); + }); + }); + + req.on('error', (error) => { + reject(error); + }); + + req.end(); + }); +}; diff --git a/test/integration/code.test.ts b/test/integration/code.test.ts index b6664422..03e3d279 100644 --- a/test/integration/code.test.ts +++ b/test/integration/code.test.ts @@ -1,79 +1,79 @@ -import { poku, assert } from '../../src/index.js'; - -(async () => { - { - const code = await poku(['./test/fixtures/success', 'test/fixtures/fail'], { - noExit: true, - quiet: true, - }); - - assert.deepStrictEqual(code, 1, 'Testing all paths as a string array'); - } - - { - const code = await poku('./test/fixtures/fail', { - noExit: true, - quiet: true, - }); - - assert.deepStrictEqual(code, 1, 'Testing a fail path as string'); - } - - { - const code = await poku('./test/fixtures/success', { - noExit: true, - quiet: true, - }); - - assert.deepStrictEqual(code, 0, 'Testing a success path as string'); - } - - { - const code = await poku(['./test/fixtures/success'], { - noExit: true, - quiet: true, - }); - - assert.deepStrictEqual(code, 0); - } - - { - const code = await poku(['./test/fixtures/success', 'test/fixtures/fail'], { - noExit: true, - filter: /success/, - quiet: true, - }); - - assert.deepStrictEqual(code, 0, 'Filter paths that contains "success"'); - } - - { - const code = await poku(['./test/fixtures/success', 'test/fixtures/fail'], { - noExit: true, - filter: /fail/, - quiet: true, - }); - - assert.deepStrictEqual(code, 1, 'Filter paths that contains "fail"'); - } - - { - const code = await poku(['test/fixtures/fail'], { - noExit: true, - filter: /success/, - quiet: true, - }); - - assert.deepStrictEqual(code, 0, 'No files (success filter)'); - } - - { - const code = await poku(['./test/fixtures/success', 'test/fixtures/fail'], { - noExit: true, - filter: /\.(m)?(j|t)?s$/, - quiet: true, - }); - - assert.deepStrictEqual(code, 1, 'Filter by extension'); - } -})(); +import { poku, assert, describe, test } from '../../src/index.js'; + +describe('Poku Runner Suite', { background: false, icon: '🐷' }); + +test(async () => { + const code = await poku(['./test/fixtures/success', 'test/fixtures/fail'], { + noExit: true, + quiet: true, + }); + + assert.deepStrictEqual(code, 1, 'Testing all paths as a string array'); +}); + +test(async () => { + const code = await poku('./test/fixtures/fail', { + noExit: true, + quiet: true, + }); + + assert.deepStrictEqual(code, 1, 'Testing a fail path as string'); +}); + +test(async () => { + const code = await poku('./test/fixtures/success', { + noExit: true, + quiet: true, + }); + + assert.deepStrictEqual(code, 0, 'Testing a success path as string'); +}); + +test(async () => { + const code = await poku(['./test/fixtures/success'], { + noExit: true, + quiet: true, + }); + + assert.deepStrictEqual(code, 0); +}); + +test(async () => { + const code = await poku(['./test/fixtures/success', 'test/fixtures/fail'], { + noExit: true, + filter: /success/, + quiet: true, + }); + + assert.deepStrictEqual(code, 0, 'Filter paths that contains "success"'); +}); + +test(async () => { + const code = await poku(['./test/fixtures/success', 'test/fixtures/fail'], { + noExit: true, + filter: /fail/, + quiet: true, + }); + + assert.deepStrictEqual(code, 1, 'Filter paths that contains "fail"'); +}); + +test(async () => { + const code = await poku(['test/fixtures/fail'], { + noExit: true, + filter: /success/, + quiet: true, + }); + + assert.deepStrictEqual(code, 0, 'No files (success filter)'); +}); + +test(async () => { + const code = await poku(['./test/fixtures/success', 'test/fixtures/fail'], { + noExit: true, + filter: /\.(m)?(j|t)?s$/, + quiet: true, + }); + + assert.deepStrictEqual(code, 1, 'Filter by extension'); +}); diff --git a/test/integration/import.test.ts b/test/integration/import.test.ts index 67b0d58d..e3053ab1 100644 --- a/test/integration/import.test.ts +++ b/test/integration/import.test.ts @@ -1,6 +1,14 @@ import * as index from '../../src/index.js'; +index.describe('Import Suite', { background: false, icon: '🔬' }); + index.assert.ok(index.poku, 'Importing poku method'); -index.assert.ok(index.exit, 'Importing exit method'); -index.assert.ok(index.listFiles, 'Importing listFiles'); index.assert.ok(index.assert, 'Importing assert method'); +index.assert.ok(index.assertPromise, 'Importing assertPromise method'); +index.assert.ok(index.describe, 'Importing describe helper'); +index.assert.ok(index.beforeEach, 'Importing beforeEach helper'); +index.assert.ok(index.afterEach, 'Importing afterEach helper'); +index.assert.ok(index.log, 'Importing log helper'); +index.assert.ok(index.test, 'Importing test helper'); +index.assert.ok(index.exit, 'Importing exit helper'); +index.assert.ok(index.listFiles, 'Importing listFiles helper'); diff --git a/test/run.test.ts b/test/run.test.ts index 3db44b4e..2ba43a7c 100644 --- a/test/run.test.ts +++ b/test/run.test.ts @@ -1,8 +1,6 @@ import { poku } from '../src/index.js'; -poku(['./test/unit', './test/integration'], { +poku(['test/unit', 'test/integration'], { parallel: true, debug: true, }); - -// poku(['./test/unit']); diff --git a/test/unit/assert-promise.test.ts b/test/unit/assert-promise.test.ts index d924821b..d06debfd 100644 --- a/test/unit/assert-promise.test.ts +++ b/test/unit/assert-promise.test.ts @@ -1,4 +1,6 @@ -import { assertPromise as assert } from '../../src/index.js'; +import { assertPromise as assert, describe } from '../../src/index.js'; + +describe('Assert (Promise) Suite', { background: false, icon: '🔬' }); assert.ok(true, 'ok with true'); assert.ok(1, 'ok with 1'); @@ -36,13 +38,3 @@ assert.notDeepStrictEqual( { a: '1' }, 'notDeepStrictEqual with loosely equal but not strictly deep equal objects' ); - -// TODO: Document compatibility from Node.js 12 -// assert.match('hello world', /world/, 'match with matching string and regex'); - -// TODO: Document compatibility from Node.js 12 -// assert.doesNotMatch( -// 'hello', -// /world/, -// 'doesNotMatch with non-matching string and regex' -// ); diff --git a/test/unit/assert.test.ts b/test/unit/assert.test.ts index 92945a0e..07ae7db5 100644 --- a/test/unit/assert.test.ts +++ b/test/unit/assert.test.ts @@ -1,4 +1,6 @@ -import { assert } from '../../src/index.js'; +import { assert, describe } from '../../src/index.js'; + +describe('Assert Suite', { background: false, icon: '🔬' }); assert.ok(true, 'ok with true'); assert.ok(1, 'ok with 1'); @@ -36,13 +38,3 @@ assert.notDeepStrictEqual( { a: '1' }, 'notDeepStrictEqual with loosely equal but not strictly deep equal objects' ); - -// TODO: Document compatibility from Node.js 12 -// assert.doesNotMatch( -// 'hello', -// /world/, -// 'doesNotMatch with non-matching string and regex' -// ); - -// TODO: Document compatibility from Node.js 12 -// assert.match('hello world', /world/, 'match with matching string and regex'); diff --git a/test/unit/run-test-file.test.ts b/test/unit/run-test-file.test.ts index fc713e0c..ac9ad3db 100644 --- a/test/unit/run-test-file.test.ts +++ b/test/unit/run-test-file.test.ts @@ -1,25 +1,25 @@ import process from 'node:process'; -import { assert } from '../../src/index.js'; +import { assert, describe, test } from '../../src/index.js'; import { runTestFile } from '../../src/services/run-test-file.js'; import { getRuntime } from '../../src/helpers/get-runtime.js'; const isProduction = process.env.NODE_ENV === 'production'; const ext = getRuntime() === 'deno' ? 'ts' : isProduction ? 'js' : 'ts'; -(async () => { - { - const code = await runTestFile(`./test/fixtures/fail/exit.test.${ext}`, { - quiet: true, - }); +describe('Service: runTestFile', { background: false, icon: '🔬' }); - assert.deepStrictEqual(code, false, 'Failure test file case'); - } +test(async () => { + const code = await runTestFile(`./test/fixtures/fail/exit.test.${ext}`, { + quiet: true, + }); - { - const code = await runTestFile(`./test/fixtures/success/exit.test.${ext}`, { - quiet: true, - }); + assert.deepStrictEqual(code, false, 'Failure test file case'); +}); - assert.deepStrictEqual(code, true, 'Success test file case'); - } -})(); +test(async () => { + const code = await runTestFile(`./test/fixtures/success/exit.test.${ext}`, { + quiet: true, + }); + + assert.deepStrictEqual(code, true, 'Success test file case'); +}); diff --git a/test/unit/run-tests.test.ts b/test/unit/run-tests.test.ts index 121e1b03..8dc8c0a3 100644 --- a/test/unit/run-tests.test.ts +++ b/test/unit/run-tests.test.ts @@ -1,22 +1,22 @@ -import { assert } from '../../src/index.js'; +import { assert, describe, test } from '../../src/index.js'; import { runTests } from '../../src/services/run-tests.js'; -(async () => { - { - const code = await runTests('./test/fixtures/fail', { - noExit: true, - quiet: true, - }); +describe('Service: runTests', { background: false, icon: '🔬' }); - assert.deepStrictEqual(code, false, 'Failure test directory case'); - } +test(async () => { + const code = await runTests('./test/fixtures/fail', { + noExit: true, + quiet: true, + }); - { - const code = await runTests('./test/fixtures/success', { - noExit: true, - quiet: true, - }); + assert.deepStrictEqual(code, false, 'Failure test directory case'); +}); - assert.deepStrictEqual(code, true, 'Success test directory case'); - } -})(); +test(async () => { + const code = await runTests('./test/fixtures/success', { + noExit: true, + quiet: true, + }); + + assert.deepStrictEqual(code, true, 'Success test directory case'); +}); diff --git a/website/docs/comparing.mdx b/website/docs/comparing.mdx index 8ceae1f5..6e9f8ce1 100644 --- a/website/docs/comparing.mdx +++ b/website/docs/comparing.mdx @@ -18,7 +18,12 @@ import TabItem from '@theme/TabItem'; npm i -D poku tsx ``` -> ~10M + + +
@@ -66,7 +71,12 @@ Adopt a Poku for yourself 🩵 npm i -D jest @types/jest ts-jest ``` -> ~65M + + +
@@ -126,22 +136,37 @@ npx jest ### Installation ```bash -npm i -D mocha @types/mocha chai @types/chai tsx +npm i -D mocha @types/mocha chai @types/chai ts-node ``` -> ~18M + + +
+### Configuring ts-node + +> _ts-loader.js_ + +```js +import { register } from 'node:module'; +import { pathToFileURL } from 'node:url'; + +register('ts-node/esm', pathToFileURL('./')); +``` + ### Configuring Mocha > _.mocharc.json_ ```json { - "require": "tsx", - "extension": ["ts"], - "spec": "./test/**/*.test.ts" + "spec": "./test/**/*.test.ts", + "require": "ts-loader.js" } ``` @@ -180,7 +205,12 @@ npx mocha npm i -D vitest ts-node ``` -> ~66M + + +
@@ -235,7 +265,12 @@ npx vitest run npm i -D ava tsimp ``` -> ~55M + + +
diff --git a/website/docs/documentation/assert/index.mdx b/website/docs/documentation/assert/index.mdx index 5bf297e4..66fa030b 100644 --- a/website/docs/documentation/assert/index.mdx +++ b/website/docs/documentation/assert/index.mdx @@ -6,7 +6,7 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import { FAQ } from '@site/src/components/FAQ'; -# `assert` +# Assert **Poku** includes the `assert` method native from [**Node.js**][node-version-url], keeping everything as it is, but providing human readability.
It supports both [**Bun**][bun-version-url] and [**Deno**][deno-version-url]. diff --git a/website/docs/documentation/helpers/log.mdx b/website/docs/documentation/helpers/log.mdx index d75d817a..6ebf44ba 100644 --- a/website/docs/documentation/helpers/log.mdx +++ b/website/docs/documentation/helpers/log.mdx @@ -15,5 +15,5 @@ console.log("Poku won't show that"); ``` :::tip -Need to debug? Just use the [`debug`](/docs/documentation/poku/configs/debug) option from `poku`. +Need to debug? Just use the [`debug`](/docs/documentation/poku/options/debug) option from `poku`. ::: diff --git a/website/docs/documentation/poku/_category_.json b/website/docs/documentation/poku/_category_.json index 718b0706..c95685fc 100644 --- a/website/docs/documentation/poku/_category_.json +++ b/website/docs/documentation/poku/_category_.json @@ -1,5 +1,5 @@ { - "label": "poku", + "label": "Poku", "collapsed": false, "link": { "type": "generated-index" diff --git a/website/docs/documentation/poku/configs/_category_.json b/website/docs/documentation/poku/configs/_category_.json deleted file mode 100644 index 5b7d7c3e..00000000 --- a/website/docs/documentation/poku/configs/_category_.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "label": "Configs", - "collapsed": true, - "link": { - "type": "generated-index" - }, - "position": 2 -} diff --git a/website/docs/documentation/poku/include-files.mdx b/website/docs/documentation/poku/include-files.mdx index 99643476..2c1f85d6 100644 --- a/website/docs/documentation/poku/include-files.mdx +++ b/website/docs/documentation/poku/include-files.mdx @@ -6,21 +6,7 @@ sidebar_position: 1 > `poku(targetPaths: string | string[])` > -> By default, **Poku** searches for _`.test.`_ and `.spec.` files, but you can customize it using the [`filter`](/docs/documentation/poku/configs/filter) option. - -## API (_in-code_) - -```ts -poku('targetePath'); -``` - -```ts -poku(['targetePathA', 'targetePathB']); -``` - -```ts -poku('./'); -``` +> By default, **Poku** searches for _`.test.`_ and `.spec.` files, but you can customize it using the [`filter`](/docs/documentation/poku/options/filter) option. ## CLI @@ -29,11 +15,11 @@ By setting the directories as the **last argument**: > _Since **1.3.0**_ ```bash -npx poku targetePath +npx poku targetPath ``` ```bash -npx poku targetePathA,targetePathB +npx poku targetPathA,targetPathB ``` ```bash @@ -44,13 +30,27 @@ npx poku By using `--include` option, you can use it in any order: ```bash -npx poku --include='targetePath' +npx poku --include='targetPath' ``` ```bash -npx poku --include='targetePathA,targetePathB' +npx poku --include='targetPathA,targetPathB' ``` ```bash npx poku --include='./' ``` + +## API (_in-code_) + +```ts +poku('targetPath'); +``` + +```ts +poku(['targetPathA', 'targetPathB']); +``` + +```ts +poku('./'); +``` diff --git a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/poku/configs/_category_.json b/website/docs/documentation/poku/options/_category_.json similarity index 80% rename from website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/poku/configs/_category_.json rename to website/docs/documentation/poku/options/_category_.json index 5b7d7c3e..4b1fee44 100644 --- a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/poku/configs/_category_.json +++ b/website/docs/documentation/poku/options/_category_.json @@ -1,5 +1,5 @@ { - "label": "Configs", + "label": "Options", "collapsed": true, "link": { "type": "generated-index" diff --git a/website/docs/documentation/poku/configs/debug.mdx b/website/docs/documentation/poku/options/debug.mdx similarity index 100% rename from website/docs/documentation/poku/configs/debug.mdx rename to website/docs/documentation/poku/options/debug.mdx diff --git a/website/docs/documentation/poku/configs/exclude.mdx b/website/docs/documentation/poku/options/exclude.mdx similarity index 100% rename from website/docs/documentation/poku/configs/exclude.mdx rename to website/docs/documentation/poku/options/exclude.mdx diff --git a/website/docs/documentation/poku/configs/filter.mdx b/website/docs/documentation/poku/options/filter.mdx similarity index 100% rename from website/docs/documentation/poku/configs/filter.mdx rename to website/docs/documentation/poku/options/filter.mdx diff --git a/website/docs/documentation/poku/configs/no-exit.mdx b/website/docs/documentation/poku/options/no-exit.mdx similarity index 100% rename from website/docs/documentation/poku/configs/no-exit.mdx rename to website/docs/documentation/poku/options/no-exit.mdx diff --git a/website/docs/documentation/poku/configs/parallel.mdx b/website/docs/documentation/poku/options/parallel.mdx similarity index 100% rename from website/docs/documentation/poku/configs/parallel.mdx rename to website/docs/documentation/poku/options/parallel.mdx diff --git a/website/docs/documentation/poku/configs/platform.mdx b/website/docs/documentation/poku/options/platform.mdx similarity index 100% rename from website/docs/documentation/poku/configs/platform.mdx rename to website/docs/documentation/poku/options/platform.mdx diff --git a/website/docs/documentation/poku/configs/quiet.mdx b/website/docs/documentation/poku/options/quiet.mdx similarity index 100% rename from website/docs/documentation/poku/configs/quiet.mdx rename to website/docs/documentation/poku/options/quiet.mdx diff --git a/website/docs/documentation/startScript.mdx b/website/docs/documentation/startScript.mdx new file mode 100644 index 00000000..61cdedfe --- /dev/null +++ b/website/docs/documentation/startScript.mdx @@ -0,0 +1,151 @@ +--- +sidebar_position: 3 +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import { FAQ } from '@site/src/components/FAQ'; +import Success from '@site/static/img/success.svg'; + +# Start Script + +Run your `package.json` scripts in a background process and test them 🧑🏻‍🔬 + +> startScript(filePath: string, options?: startScriptOptions); +> +> _Since **1.9.0**_ + +`startScript` execute a script directly from your `package.json` or `deno.json` and keep it running in a background process until you release it. + +
+
+ + + Really useful to test your + [**NextJS**](https://github.com/vercel/next.js), + [**NuxtJS**](https://github.com/nuxt/nuxt), + [**nodemon**](https://github.com/remy/nodemon) and every project app 🚀 + +
+
+ + Allows **cookies** to persist (_or not_) 🍪 +
+
+ + + **Poku** allows you to use the requester you want, such as + [**Axios**](https://github.com/axios/axios), the native `fetch` and + everyone ✨ + +
+
+ + + No need to add external plugins to something so simple, just run it as it + is 🌱 + +
+
+ + + Stop changing your code due to tester rules, you created your code, not + **Poku** 🩵 + +
+
+ +
+ +[See practical examples using **fetch**, [**Axios**](https://github.com/axios/axios), a **persistent session** and more](/docs/examples/local-server). + +
+ +## Good Practices 👮🏽 + +### ✅ Sinalize the "ready" status + +When possible, set a console output to indicate that the service is ready.
+This will allow you to avoid premature executions and port leaks. + +### ✅ Set a timeout + +By defining a timeout, you avert indefinite processes that conclude neither in success nor failure. + +### ✅ End your service when the job is done + +You don't necessarily have to end your service running in the background as the last line of the test, if it's no longer used. + +```ts +import { startScript } from 'poku'; // 'npm:poku' for Deno + +const server = await startScript('start', { + /** + * Wait for the "ready" console output + */ + startAfter: 'Ready', + + /** + * By default, the `timeout` is `60000` (1 minute) for neither in success nor failure + */ + timeout: 60000, +}); + +server.end(); +``` + + + +Releasing a leaking port: + +```bash +lsof -i :PORT +``` + +- Replace `PORT` with the port number you're investigating. + +Then, use the `PID` returned with the `kill` command: + +```bash +kill -9 PID +``` + +- Replace `PID` with the actual process ID you found using the `lsof` command. + + + +
+ +## Available Options + +```ts +type StartScriptOptions = { + /** + * - By default, it will resolve in the first console output + * - By setting a string: it will wait for a specifc string on console output to resolve + * - By setting a number: it will wait for time in milliseconds to resolve + * + * @default undefined + */ + startAfter?: string | number; + /** + * Stops the service after: + * @default 60000 + */ + timeout?: number; + /** + * Shows the output from service + */ + verbose?: boolean; + /** + * Specify a target path to start the process + * + * @default "./" + */ + cwd?: string | undefined; + /** + * By default, Poku will use `npm`. Change it as you want. + */ + runner?: 'npm' | 'bun' | 'deno' | 'yarn' | 'pnpm'; +}; +``` diff --git a/website/docs/documentation/startService.mdx b/website/docs/documentation/startService.mdx new file mode 100644 index 00000000..0208341e --- /dev/null +++ b/website/docs/documentation/startService.mdx @@ -0,0 +1,140 @@ +--- +sidebar_position: 4 +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import { FAQ } from '@site/src/components/FAQ'; +import Success from '@site/static/img/success.svg'; + +# Start Service + +Run your services in a background process and test them 🧑🏻‍🔬 + +> startService(filePath: string, options?: StartServiceOptions); +> +> _Since **1.9.0**_ + +`startService` execute a file directly and keep it running in a background process until you release it. + +
+
+ + Allows **cookies** to persist (_or not_) 🍪 +
+
+ + + **Poku** allows you to use the requester you want, such as **Axios**, the + native `fetch` and everyone ✨ + +
+
+ + + No need to export your app, server or any service, just run it as it is 🚀 + +
+
+ + + Stop changing your code due to tester rules, you created your code, not + **Poku** 🩵 + +
+
+ +
+ +[See practical examples using **fetch**, **Axios**, a **persistent session** and more](/docs/examples/local-server). + +
+ +## Good Practices 👮🏽 + +### ✅ Sinalize the "ready" status + +When possible, set a console output to indicate that the service is ready.
+This will allow you to avoid premature executions and port leaks. + +### ✅ Set a timeout + +By defining a timeout, you avert indefinite processes that conclude neither in success nor failure. + +### ✅ End your service when the job is done + +You don't necessarily have to end your service running in the background as the last line of the test, if it's no longer used. + +```ts +import { startService } from 'poku'; // 'npm:poku' for Deno + +const server = await startService('server.js', { + /** + * Wait for the "ready" console output + */ + startAfter: 'ready', + + /** + * By default, the `timeout` is `60000` (1 minute) for neither in success nor failure + */ + timeout: 60000, +}); + +server.end(); +``` + + + +Releasing a leaking port: + +```bash +lsof -i :PORT +``` + +- Replace `PORT` with the port number you're investigating. + +Then, use the `PID` returned with the `kill` command: + +```bash +kill -9 PID +``` + +- Replace `PID` with the actual process ID you found using the `lsof` command. + + + +
+ +## Available Options + +```ts +type StartServiceOptions = { + /** + * - By default, it will resolve in the first console output + * - By setting a string: it will wait for a specifc string on console output to resolve + * - By setting a number: it will wait for time in milliseconds to resolve + * + * @default undefined + */ + startAfter?: string | number; + /** + * Stops the service after: + * @default 60000 + */ + timeout?: number; + /** + * Shows the output from service + */ + verbose?: boolean; + /** + * Specify a target path to start the process + * + * @default "./" + */ + cwd?: string | undefined; + /** + * By default, Poku will try to identify the actual platform, but you can specify it manually + */ + platform?: 'node' | 'bun' | 'deno'; +}; +``` diff --git a/website/docs/examples/DOM.mdx b/website/docs/examples/DOM.mdx deleted file mode 100644 index 886b0a5c..00000000 --- a/website/docs/examples/DOM.mdx +++ /dev/null @@ -1,25 +0,0 @@ ---- -sidebar_position: 3 ---- - -# Virtual DOM - -Let's simule a **Virtual DOM** (Browser) by using [**jsdom**](https://github.com/jsdom/jsdom), then testing its results with **Poku**: - -```ts -import { assert } from 'poku'; -import { JSDOM } from 'jsdom'; - -const dom = new JSDOM('
Poku
'); -const document = dom.window.document; - -const name = document.querySelector('#name'); - -assert.strictEqual(name?.textContent, 'Poku', 'My div contains a Poku 🐷'); -``` - -Then: - -```bash -npx poku -``` diff --git a/website/docs/examples/browser/DOM.mdx b/website/docs/examples/browser/DOM.mdx new file mode 100644 index 00000000..73ddebd0 --- /dev/null +++ b/website/docs/examples/browser/DOM.mdx @@ -0,0 +1,29 @@ +--- +sidebar_position: 3 +--- + +# Virtual DOM + +Let's simule a **Virtual DOM** (Browser) by using [**Happy DOM**](https://github.com/capricorn86/happy-dom), then testing its results with **Poku**: + +```ts +import { assert } from 'poku'; +// highlight-start +import { Window } from 'happy-dom'; + +const window = new Window(); +const document = window.document; + +document.body.innerHTML = '
Poku
'; + +const name = document.querySelector('#name'); +// highlight-end + +assert.strictEqual(name?.textContent, 'Poku', 'My div contains a Poku 🐷'); +``` + +Then: + +```bash +npx poku +``` diff --git a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/poku/_category_.json b/website/docs/examples/browser/_category_.json similarity index 65% rename from website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/poku/_category_.json rename to website/docs/examples/browser/_category_.json index 718b0706..e3f67d69 100644 --- a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/poku/_category_.json +++ b/website/docs/examples/browser/_category_.json @@ -1,8 +1,8 @@ { - "label": "poku", + "label": "Browser", "collapsed": false, "link": { "type": "generated-index" }, - "position": 1 + "position": 2 } diff --git a/website/docs/examples/browser/react.mdx b/website/docs/examples/browser/react.mdx new file mode 100644 index 00000000..757735c9 --- /dev/null +++ b/website/docs/examples/browser/react.mdx @@ -0,0 +1,68 @@ +--- +sidebar_position: 1 +--- + +# ReactJS + +To effectively test **React** components, we can combine **Poku** and your preferred web scraper tool. + +For this example, let's create a simple **Vite React** app and then navigate on it using **Puppeteer** to interact with the page: + +```bash +# highlight-start +npm create vite@latest my-project -- --template react +# highlight-end +``` + +> It will create a default **Vite React** app in the `my-project` directory. + +Test steps: + +- ✅ Start the `dev` script from `my-project/package.json` in the background +- ✅ Verify the initial couter is **zero** +- ✅ Click on button to increment the counter +- ✅ Check the updated couter value +- ✅ Close the background process + +```ts +import { assert, startScript } from 'poku'; +// highlight-start +import puppeteer from 'puppeteer'; +// highlight-end + +const server = await startScript('dev', { + cwd: 'my-project', +}); + +// highlight-start +const API = 'http://localhost:5173'; + +const browser = await puppeteer.launch(); +const page = await browser.newPage(); + +await page.goto(API); + +const button = await page.waitForSelector('button'); +// highlight-end + +assert.strictEqual( + await button.evaluate((e) => e.textContent), + 'count is 0', + 'Initial Counter needs to be 0' +); + +// highlight-start +await button.click(); +// highlight-end + +assert.strictEqual( + await button.evaluate((e) => e.textContent), + 'count is 1', + 'After click, needs to be 1' +); + +// highlight-start +await browser.close(); +// highlight-end +server.end(); +``` diff --git a/website/docs/examples/cjs-esm.mdx b/website/docs/examples/cjs-esm.mdx index e9339793..77f2d0cb 100644 --- a/website/docs/examples/cjs-esm.mdx +++ b/website/docs/examples/cjs-esm.mdx @@ -8,23 +8,23 @@ import TabItem from '@theme/TabItem'; # CJS and ESM Just set your **package.json** as usual and that's it.
-**Poku** doesn't require any configuration 🐷 +**Poku** doesn't require any configuration for this 🐷 - + ```json { - "type": "commonjs" + "type": "module" } ``` - + ```json { - "type": "module" + "type": "commonjs" } ``` diff --git a/website/docs/examples/local-server.mdx b/website/docs/examples/local-server.mdx new file mode 100644 index 00000000..6944fcb7 --- /dev/null +++ b/website/docs/examples/local-server.mdx @@ -0,0 +1,199 @@ +--- +sidebar_position: 1 +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import { FAQ } from '@site/src/components/FAQ'; + +# Local Server + +Let's create a simple server: + + + + +```js +// highlight-start +import { createServer } from 'node:http'; + +createServer((_, res) => { + res.writeHead(200, { 'Content-Type': 'application/json' }); + res.end(JSON.stringify({ name: 'Poku' })); +}).listen(4000, () => console.log('ready')); + +// highlight-end +``` + + + + +```js +// highlight-start +Bun.serve({ + port: 4000, + fetch: () => + new Response(JSON.stringify({ name: 'Poku' }), { + headers: { 'Content-Type': 'application/json' }, + }), +}); + +console.log('ready'); +// highlight-end +``` + + + + +```ts +// highlight-start +Deno.serve({ + port: 4000, + handler: () => + new Response(JSON.stringify({ name: 'Poku' }), { + headers: { 'Content-Type': 'application/json' }, + }), + onListen: () => console.log('ready'), +}); +// highlight-end +``` + + + + +And now, test it: + + + + +```js +import { assert, startService } from 'poku'; // 'npm:poku' for Deno + +const server = await startService('server.js', { + // Wait for the "ready" console output + startAfter: 'ready', +}); + +// Use the requester you want +// highlight-start +const res = await fetch('http://localhost:4000'); +const data = await res.json(); +// highlight-end + +assert.strictEqual(res.status, 200, 'Server is on'); +assert.deepStrictEqual(data, { name: 'Poku' }, 'Poku is here'); + +server.end(); +``` + + + + + + +**Just do it** 🚀 + +Here's an example using [**Axios**](https://github.com/axios/axios): + +```js +import { assert, startService } from 'poku'; +// highlight-start +import axios from 'axios'; +import axiosCookieJarSupport from 'axios-cookiejar-support'; +import { CookieJar } from 'tough-cookie'; + +// highlight-end +const server = await startService('server.js'); + +// highlight-start +axiosCookieJarSupport(axios); + +const cookieJar = new CookieJar(); + +export const api = axios.create({ + withCredentials: true, + jar: cookieJar, +}); + +const { data } = await api.get('http://localhost:4000'); +// highlight-end + +assert.deepStrictEqual(data, { name: 'Poku' }, 'Poku is here'); +``` + + + +:::tip + +- **Requester:** You can use [**Axios**](https://github.com/axios/axios), [**Node Fetch**](https://github.com/node-fetch/node-fetch) and everyone you want 💙 +- **Server:** you can use every server you want, such as [**Express**](https://github.com/expressjs/express), [**Koa**](https://github.com/koajs/koa), etc. +- [**NextJS**](https://github.com/vercel/next.js), [**ViteJS**](https://github.com/vitejs/vite), [**nodemon**](https://github.com/remy/nodemon) and more? See bellow 👇🏻 + +::: + +
+ +You also can start your server using the `startScript`. + + + + +```js +import { assert, startScript } from 'poku'; + +const server = await startScript('start', { + // Wait for the "ready" console output + startAfter: 'Ready', +}); + +// Use the requester you want +// highlight-start +const res = await fetch('http://localhost:4000'); +const data = await res.json(); +// highlight-end + +assert.strictEqual(res.status, 200, 'Server is on'); +assert.deepStrictEqual(data, { name: 'Poku' }, 'Poku is here'); + +server.end(); +``` + + + + +```json +{ + "script": { + "serve": "node server.js" + } +} +``` + + + + +```json +{ + "script": { + "serve": "bun server.js" + } +} +``` + + + + +```json +{ + "tasks": { + "serve": "deno run --allow-net server.js" + } +} +``` + + + + +:::tip +Using `startScript`, you can execute [**NextJS**](https://github.com/vercel/next.js), [**SvelteJS**](https://github.com/sveltejs/svelte), [**nodemon**](https://github.com/remy/nodemon) and all the scripts you've always used 🐷 +::: diff --git a/website/docs/examples/mock/_category_.json b/website/docs/examples/mock/_category_.json index 71abb29d..508ce472 100644 --- a/website/docs/examples/mock/_category_.json +++ b/website/docs/examples/mock/_category_.json @@ -4,5 +4,5 @@ "link": { "type": "generated-index" }, - "position": 2 + "position": 3 } diff --git a/website/docs/examples/mock/cjs.mdx b/website/docs/examples/mock/cjs.mdx index 6f498499..6d75851e 100644 --- a/website/docs/examples/mock/cjs.mdx +++ b/website/docs/examples/mock/cjs.mdx @@ -5,6 +5,8 @@ import TabItem from '@theme/TabItem'; You can use your favorite **Mock** framework or tool and **Poku** together 🐷➕ +> By not locking you into a specific set of plugins or mocking/spying tools, **Poku** promotes an open ecosystem where developers are free to integrate the tools that best suit their needs. + For this example, let's use the [**quibble**](https://github.com/testdouble/quibble), then testing its results with **Poku**: diff --git a/website/docs/examples/mock/esm.mdx b/website/docs/examples/mock/esm.mdx index fe0120f8..3f86ff0f 100644 --- a/website/docs/examples/mock/esm.mdx +++ b/website/docs/examples/mock/esm.mdx @@ -5,6 +5,8 @@ import TabItem from '@theme/TabItem'; You can use your favorite **Mock** framework or tool and **Poku** together 🐷➕ +> By not locking you into a specific set of plugins or mocking/spying tools, **Poku** promotes an open ecosystem where developers are free to integrate the tools that best suit their needs. + For this example, let's use the [**quibble**](https://github.com/testdouble/quibble), then testing its results with **Poku**: diff --git a/website/docs/index.mdx b/website/docs/index.mdx index 626aebbe..f2a78151 100644 --- a/website/docs/index.mdx +++ b/website/docs/index.mdx @@ -54,7 +54,7 @@ Enjoying **Poku**? Consider giving him a star ⭐️ ## Why Poku? -By creating **Poku**, my aim is to show that testing can be simpler 🌱 +**Poku** can show you how simple testing can be 🌱
@@ -80,10 +80,11 @@ By creating **Poku**, my aim is to show that testing can be simpler 🌱
> 🔬 Start by seeing how to use `assert`
+> 🧑🏻‍🔬 Need to test an API? Check the `startService` and `startScript`
> 🧪 Then learn how to use `poku` CLI to run all your test files at once
> 🧙🏻 So, just if you want to, go deeper into learning about **Poku**
> -> 🩵 Take your time +> 🩵 Take Your Time - [**Compare Poku with the Most Popular Test Runners 🧪**](/docs/comparing) @@ -129,8 +130,7 @@ You can also use **Poku** with [**esm.sh**](https://esm.sh): import { poku } from 'https://esm.sh/poku'; ``` - - + ### **Test it** 🔬 @@ -156,6 +156,8 @@ assert(true, 'Poku will describe it 🐷'); +> Note that these examples use [**ESM**](/docs/examples/cjs-esm), but you can use [**CJS**](/docs/examples/cjs-esm) as well. + ### **Run it** 🚀 @@ -198,13 +200,14 @@ deno run npm:poku ### Essentials -- `poku` (_test runner_) -- `assert` and `assertPromise` (_test assertion_) +- [**poku**](/docs/category/poku) (_test runner_) +- [**assert**](/docs/documentation/assert) (_test assertion_) +- [**startScript**](/docs/documentation/startScript) and [**startService**](/docs/documentation/startService) (_run scripts and services in a background process_) ### Helpers -- `beforeEach` and `afterEach` - `test` +- `beforeEach` and `afterEach` - `describe` and `log` - `listFiles` - `exit` @@ -215,7 +218,7 @@ deno run npm:poku ## Documentation -> Initially, the [**documentation**](/docs/category/documentation) and [**examples**](/docs/category/examples) are based on **Node.js** usage, but you can use all the options normally for both **Bun** and **Deno**. +> Initially, the [**documentation**](/docs/category/documentation) and [**examples**](/docs/category/examples) are based on **Node.js** and **ESM** usage, but you can use all the options normally for both **Bun** and **Deno**, including **CJS**.
diff --git a/website/docs/overview.mdx b/website/docs/overview.mdx index 0fa5f538..9d36d477 100644 --- a/website/docs/overview.mdx +++ b/website/docs/overview.mdx @@ -13,7 +13,7 @@ import ASSERT_NODE from '@site/static/img/assert-node.png'; | | | - By default, **Poku**: - - Searches for all _`.test.`_ and `.spec.` files, but you can customize it using the option [**`filter`**](/docs/documentation/poku/configs/filter). + - Searches for all _`.test.`_ and `.spec.` files, but you can customize it using the option [**`filter`**](/docs/documentation/poku/options/filter). - Uses `sequential` mode. - You can use concurrecy by using the flag `--parallel` for **CLI** or setting the option `parallel` to `true` in **API** (_in-code_) usage. diff --git a/website/docs/security.mdx b/website/docs/security.mdx index 62cdff6c..3c113769 100644 --- a/website/docs/security.mdx +++ b/website/docs/security.mdx @@ -15,7 +15,7 @@ Some test runners use **`eval`**, **Poku** prefers to use **`spawn`** to create - `\` for **Windows** - `/` for **Linux** and **macOS** - Normalizes paths by filtering unusual path characters, for example: - - `<>:|^?*` + - `<>|^?*` - Prevents shell scripts by setting `shell` to `false` in **`spawn`** options, ensuring that only secure arguments will be used. - Every **RegExp** is prev-tested using the [**ReDoS Checker**](https://devina.io/redos-checker). diff --git a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/assert/index.mdx b/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/assert/index.mdx deleted file mode 100644 index c5432caa..00000000 --- a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/assert/index.mdx +++ /dev/null @@ -1,96 +0,0 @@ ---- -sidebar_position: 2 ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -# `assert` - -**Poku** includes the `assert` method native from [**Node.js**][node-version-url], keeping everything as it is, but providing human readability.
-It supports both [**Bun**][bun-version-url] and [**Deno**][deno-version-url]. - -[node-version-url]: https://github.com/nodejs/node -[bun-version-url]: https://github.com/oven-sh/bun -[deno-version-url]: https://github.com/denoland/deno - -- [**Node.js**][node-version-url], [**Bun**][bun-version-url] and [**Deno**][deno-version-url] compatible. - -> The `assert` is used to write tests and verify if your code works as expected by comparing values and throwing errors, otherwise 🧑🏻‍🎓 -> -> _Since **1.3.0**_ - -## Migrating to **Poku**'s `assert` - -_But only if you want to, of course._ - - - - - ```diff - - import assert from 'node:assert'; - + import { assert } from 'poku'; - ``` - - - - - ```diff - - import assert from 'node:assert'; - + import { assert } from 'npm:poku'; - ``` - - - - -```ts -assert(true); -assert.deepStrictEqual(1, '1', 'My optional custom message'); -// ... -``` - -:::tip -**Poku**'s `assert` will use the message exactly as it is when using `describe` and `it`.
-Your **Poku** is waiting for you 🐷✨ -::: - -
- -## Available methods - -```ts -import { assert, assertPromise } from 'poku'; -``` - -> You can combine promise **assert** with beforeEach and afterEach helpers. - -- `assert(value[, message])` -- `assert.deepEqual(actual, expected[, message])` -- `assert.deepStrictEqual(actual, expected[, message])` -- `assert.doesNotMatch(string, regexp[, message])` -- `assert.doesNotReject(asyncFn[, error][, message])` -- `assert.doesNotThrow(fn[, error][, message])` -- `assert.equal(actual, expected[, message])` -- `assert.fail([message])` -- `assert.ifError(value)` -- `assert.match(string, regexp[, message])` -- `assert.notDeepEqual(actual, expected[, message])` -- `assert.notDeepStrictEqual(actual, expected[, message])` -- `assert.notEqual(actual, expected[, message])` -- `assert.notStrictEqual(actual, expected[, message])` -- `assert.ok(value[, message])` -- `assert.rejects(asyncFn[, error][, message])` -- `assert.strictEqual(actual, expected[, message])` -- `assert.throws(fn[, error][, message])` - -You can follow the [**assert documentation**](https://nodejs.org/api/assert.html) from **Node.js**'s documentation. - -:::info - -To use `assert` with **TypeScript**, you may will need to instal **@types/node**: - -```bash -npm i -D @types/node -``` - -::: diff --git a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/helpers/_category_.json b/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/helpers/_category_.json deleted file mode 100644 index cc6797db..00000000 --- a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/helpers/_category_.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "label": "Helpers", - "collapsed": false, - "link": { - "type": "generated-index" - } -} diff --git a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/helpers/before-after-each/_category_.json b/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/helpers/before-after-each/_category_.json deleted file mode 100644 index 93043d1d..00000000 --- a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/helpers/before-after-each/_category_.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "label": "beforeEach and afterEach", - "collapsed": true, - "link": { - "type": "generated-index" - }, - "position": 2 -} diff --git a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/helpers/before-after-each/in-code.mdx b/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/helpers/before-after-each/in-code.mdx deleted file mode 100644 index cce908f0..00000000 --- a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/helpers/before-after-each/in-code.mdx +++ /dev/null @@ -1,255 +0,0 @@ ---- -sidebar_position: 2 ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -# In-Code - -## How can I combine `beforeEach`, `afterEach` and `assert`? - -Both `beforeEach`, `afterEach` are recommended for tests that consume a particular global state for each test.
-For example, by populating or resetting a database before and/or after multiple assertions. - -### See how Poku solve it 🧙🏻 - - - - - ```ts - import { assert, beforeEach, afterEach } from 'poku'; - - const prepareService = () => true; - const resetService = () => true; - - beforeEach(() => prepareService()); - afterEach(() => resetService()); - - assert(true, 'Test A'); - assert(true, 'Test B'); - assert(true, 'Test C'); - assert(true, 'Test D'); - ``` - -:::tip - -- ✅ Handling **global** and **external** services (_preparing a database, for example_) -- ✅ It's made for **exclusive use** in combination with **Poku**'s **`assert`** methods -- ✅ You can combine `beforeEach`, `afterEach` and all `assert` methods, except for `assert.fail(message?: string)`. - -::: - -:::info - -- Although `beforeEach` and `afterEach` accepts local variables changes, it's strongly encouraged ([_you can use a mock instead_](/docs/category/mock)). - -See why (_note the `immediate` option_): - -```ts -import { assert, beforeEach, afterEach } from 'poku'; - -let value = 0; - -beforeEach(() => ++value, { immediate: true }); -afterEach(() => ++value); - -assert.equal(value, 1); // ✅ -assert.equal(value, 3); // ✅ - -// ✋ In the `eachBefore` context, `value` is now `4`, while locally it's `5` -console.log(value); -``` - -::: - - - - - ```ts - import { assert } from 'poku'; - - const prepareService = () => true; - const resetService = () => true; - - prepareService(); - assert(true, 'Test A'); - resetService(); - - prepareService(); - assert(true, 'Test B'); - resetService(); - - prepareService(); - assert(true, 'Test C'); - resetService(); - - prepareService(); - assert(true, 'Test D'); - resetService(); - ``` - - - - -**Poku** provides three optional methods from both `beforeEach` and `afterEach`: - - - `.pause()` - - `.continue()` - - `.reset()` - - ```ts - import { assert, beforeEach, afterEach } from 'poku'; - - const prepareService = () => true; - const resetService = () => true; - - const before = beforeEach(() => prepareService()); - const after = afterEach(() => resetService()); - - assert.ok(true, 'Test A'); - assert.ok(true, 'Test B'); - - before.pause(); - - assert.ok(true, 'Test C'); - assert.ok(true, 'Test D'); - - before.continue(); - - assert.ok(true, 'Test E'); - - // From now, it will not run beforeEach until you declare it again. - before.reset(); - - assert.ok(true, 'Test F'); - ``` - -:::tip -You can overwriting both `beforeEach` and `afterEach` by declaring them again anytime. -::: - - - - -### By using Promises - - - - - ```ts - import { assertPromise as assert, beforeEach, afterEach } from 'poku'; - - const prepareService = () => new Promise((resolve) => resolve(true)); - const resetService = () => new Promise((resolve) => resolve(true)); - - beforeEach(async () => await prepareService()); - afterEach(async () => await resetService()); - - await assert(true, 'Test A'); - await assert(true, 'Test B'); - await assert(true, 'Test C'); - await assert(true, 'Test D'); - ``` - -:::tip - -- ✅ Handling **global** and **external** services (_preparing a database, for example_) -- ✅ It's made for **exclusive use** in combination with **Poku**'s **`assert`** methods -- ✅ You can combine `beforeEach`, `afterEach` and all `assert` methods, except for `assert.fail(message?: string)`. - -::: - -:::info - -- Although `beforeEach` and `afterEach` accepts local variables changes, it's strongly encouraged ([_you can use a mock instead_](/docs/category/mock)). - -See why (_note the `immediate` option_): - -```ts -import { assertPromise as assert, beforeEach, afterEach } from 'poku'; - -let value = 0; - -beforeEach(async () => new Promise((resolve) => resolve(++value)), { - immediate: true, -}); -afterEach(async () => new Promise((resolve) => resolve(++value))); - -await assert.equal(value, 1); // ✅ -await assert.equal(value, 3); // ✅ - -// ✋ In the `eachBefore` context, `value` is now `4`, while locally it's `5` -console.log(value); -``` - -::: - - - - - ```ts - import { assert } from 'poku'; - - const prepareService = () => new Promise((resolve) => resolve(true)); - const resetService = () => new Promise((resolve) => resolve(true)); - - await prepareService(); - assert(true, 'Test A'); - await resetService(); - - await prepareService(); - assert(true, 'Test B'); - await resetService(); - - await prepareService(); - assert(true, 'Test C'); - await resetService(); - - await prepareService(); - assert(true, 'Test D'); - await resetService(); - ``` - - - - - **Poku** provides three optional methods from both `beforeEach` and `afterEach`: - - - `.pause()` - - `.continue()` - - `.reset()` - - ```ts - import { assertPromise as assert, beforeEach, afterEach } from 'poku'; - - const prepareService = () => new Promise((resolve) => resolve(true)); - const resetService = () => new Promise((resolve) => resolve(true)); - - const before = await beforeEach(async () => await prepareService()); - const after = await afterEach(async () => await resetService()); - - await assert.ok(true, 'Test A'); - await assert.ok(true, 'Test B'); - - before.pause(); - - await assert.ok(true, 'Test C'); - await assert.ok(true, 'Test D'); - - before.continue(); - - await assert.ok(true, 'Test E'); - - // From now, it will not run beforeEach until you declare it again. - before.reset(); - - await assert.ok(true, 'Test F'); - ``` - -:::tip -You can overwriting both `beforeEach` and `afterEach` by declaring them again anytime. -::: - - - diff --git a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/helpers/before-after-each/per-file.mdx b/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/helpers/before-after-each/per-file.mdx deleted file mode 100644 index 6a1083f0..00000000 --- a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/helpers/before-after-each/per-file.mdx +++ /dev/null @@ -1,58 +0,0 @@ ---- -sidebar_position: 1 ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; -import { FAQ } from '@site/src/components/FAQ'; -import Success from '@site/static/img/each-success.png'; -import Failure from '@site/static/img/each-fail.png'; - -# Per File - -## Running a callback before and after each test file - -- [x] `poku` **API (_in-code_)** -- [ ] `poku` **CLI** - -**Poku** brings a simple way to perform a callback before and/or after every test file. - - - - - ```ts - import { poku } from 'poku'; - - const prepareService = () => new Promise((resolve) => resolve(undefined)); - const resetService = () => new Promise((_, reject) => reject('Let\'s crash it')); - - await poku('test/unit', { - beforeEach: prepareService, - afterEach: resetService, - }); - ``` - - ```bash - npx poku test/run.test.js - ``` - - - - - - - - - - - - - - - - -
- -:::info -Although it also works with `parallel` runs, it's strongly discouraged to use these features for sequential tests. -::: diff --git a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/helpers/describe.mdx b/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/helpers/describe.mdx deleted file mode 100644 index 8fc16509..00000000 --- a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/helpers/describe.mdx +++ /dev/null @@ -1,124 +0,0 @@ ---- -sidebar_position: 1 ---- - -import { FAQ } from '@site/src/components/FAQ'; -import Example from '@site/static/img/describe-example.png'; - -# describe - -On **Poku**, `describe` is just a pretty `console.log` to title your test suites in the terminal. - -```ts -import { describe, assert } from 'poku'; - -describe('Group A'); -assert(true, '1'); -assert(true, '2'); - -describe('Group B'); -assert(true, '1'); -assert(true, '2'); -``` - -## Personalization - -> `describe(title: string, options?: DescribeOptions)` - -### pad - -Skips a line before to console it. - -```ts -import { describe, assert } from 'poku'; - -describe('Group A', { pad: true }); -assert.ok(true, '1'); -assert.ok(true, '2'); -``` - -### background - -Change the background color for your personal title. - -> Set `false` to disable it. - -```ts -import { describe, assert } from 'poku'; - -describe('Group A', { background: 'blue' }); -assert.ok(true, '1'); -assert.ok(true, '2'); -``` - - - -- `white` -- `black` -- `grey` -- `red` -- `green` -- `yellow` -- `blue` -- `magenta` -- `cyan` -- `brightRed` -- `brightGreen` -- `brightYellow` -- `brightBlue` -- `brightMagenta` -- `brightCyan` - - - -### icon (prefix) - -**Poku** also allows the prefix customization. - -> The default icon is `☰`. - -```ts -import { describe, assert } from 'poku'; - -describe('Group A', { icon: '🚀' }); -assert.ok(true, '1'); -assert.ok(true, '2'); -``` - -
- -## Overview - - - - ```ts - import { assert, describe } from 'poku'; - - describe('Needs to Succeed', { - pad: true, - background: false, - icon: '🚀', - }); - - assert.ok(true, 'Test 1'); - assert.ok(true, 'Test 2'); - - describe('Needs to Fail', { - pad: true, - background: 'yellow', - icon: '🚫', - }); - - assert.throws(() => { throw new Error() }, 'Test 1'); - assert.throws(() => { throw new Error() }, 'Test 2'); - ``` - - - -
- - - -
- -
diff --git a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/helpers/list-files.mdx b/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/helpers/list-files.mdx deleted file mode 100644 index 88285cfe..00000000 --- a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/helpers/list-files.mdx +++ /dev/null @@ -1,23 +0,0 @@ -# `listFiles` - -> `listFiles(targetDir: string, configs?: ListFilesConfigs)` - -Returns all files in a directory, independent of their depth. - -> _Since **1.2.0**_ - -```ts -listFiles('some-dir'); -``` - -- You can use the `filter` and `exclude` options, as well as they are for **`poku`** method. - -:::info - -To use `listFiles` with **TypeScript**, you will need to instal **@types/node**: - -```bash -npm i -D @types/node -``` - -::: diff --git a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/helpers/log.mdx b/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/helpers/log.mdx deleted file mode 100644 index 009c1639..00000000 --- a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/helpers/log.mdx +++ /dev/null @@ -1,19 +0,0 @@ ---- -sidebar_position: 3 ---- - -# log - -Since by default **Poku** only shows outputs generated from itself, this helper allows you to use an alternative to `console.log` with **Poku** runner. - -```ts -import { log } from 'poku'; - -log('Poku will show it'); - -console.log("Poku won't show that"); -``` - -:::tip -Need to debug? Just use the [`debug`](/docs/documentation/poku/configs/debug) option from `poku`. -::: diff --git a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/poku/configs/debug.mdx b/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/poku/configs/debug.mdx deleted file mode 100644 index cc5efb07..00000000 --- a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/poku/configs/debug.mdx +++ /dev/null @@ -1,27 +0,0 @@ ---- -sidebar_position: 6 ---- - -# `debug` - -> `poku(targetPaths: string | string[], configs?: Configs)` -> -> `debug: boolean` - -By default **Poku** doesn't shows logs that doesn't comes from **Poku**'s **`assert`**, but you can enable them: - -> _Since **1.5.0**_ - -## API (_in-code_) - -```ts -poku(['...'], { - debug: true, -}); -``` - -## CLI - -```bash -npx poku --debug ./test -``` diff --git a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/poku/configs/exclude.mdx b/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/poku/configs/exclude.mdx deleted file mode 100644 index 4e1656f7..00000000 --- a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/poku/configs/exclude.mdx +++ /dev/null @@ -1,89 +0,0 @@ ---- -sidebar_position: 4 ---- - -# `exclude` - -> `poku(targetPaths: string | string[], configs?: Configs)` -> -> `exclude: RegExp | RegExp[]` - -Exclude by path using Regex to match only the files that should be performed. - -> _Since **1.2.0**_ - -## API (_in-code_) - -```ts -/** - * Excluding directories from tests - */ - -poku(['...'], { - exclude: /\/(helpers|tools)\//, -}); -``` - -```ts -/** - * Excluding directories from tests - */ - -poku(['...'], { - exclude: [/\/helpers\//, /\/tools\//], -}); -``` - -```ts -/** - * Excluding specific files from tests - */ - -poku(['...'], { - exclude: /(index|common).test.ts/, -}); -``` - -```ts -/** - * Excluding specific files from tests - */ - -poku(['...'], { - exclude: [/index.test.ts/, /common.test.ts/], -}); -``` - -```ts -/** - * Excluding directories and files from tests - */ - -poku(['...'], { - exclude: /\/(helpers|tools)\/|(index|common).test.ts/, -}); -``` - -```ts -/** - * Excluding directories and files from tests - */ - -poku(['...'], { - exclude: [/\/helpers\//, /\/tools\//, /index.test.ts/, /common.test.ts/], -}); -``` - -## CLI - -```bash -# Excluding directories and files from tests - -npx poku --exclude='some-file-or-dir' ./test -``` - -```bash -# Excluding directories and files from tests - -npx poku --exclude='some-file-or-dir|other-file-or-dir' ./test -``` diff --git a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/poku/configs/filter.mdx b/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/poku/configs/filter.mdx deleted file mode 100644 index 7d8c97c1..00000000 --- a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/poku/configs/filter.mdx +++ /dev/null @@ -1,85 +0,0 @@ ---- -sidebar_position: 2 ---- - -# `filter` - -> `poku(targetPaths: string | string[], configs?: Configs)` -> -> `filter: RegExp` - -Filter by path using **Regex** to match only the files that should be performed.
-By default, **Poku** searches for _`.test.`_ and `.spec.` files, but you can customize it using the `filter` option. - -## API (_in-code_) - -```ts -/** - * @default - * - * Testing all `*.test.*` files. - */ - -poku(['...'], { - filter: /\.test\./, -}); -``` - -```ts -/** - * Testing all `ts`, `js`, `mts` and `mjs` files - */ - -poku(['...'], { - filter: /\.(m)?(j|t)s$/, - // filter: /\.(js|ts|mjs|mts)$/, -}); -``` - -## CLI - -```bash -# Testing only a specific file - -npx poku --filter='some-file' ./test -``` - -```bash -# Testing only a specific file - -npx poku --filter='some-file|other-file' ./test -``` - -```bash -# Testing only paths that contains "unit" - -npx poku --filter='unit' ./test -``` - -## Environment Variable - -By using `FILTER` from **Environment Variable**, it will overwrite the `filter` option. - -```bash -# Testing only a specific file - -FILTER='some-file' npx poku ./test -``` - -```bash -# Testing only a specific file - -FILTER='some-file|other-file' npx poku ./test -``` - -```bash -# Testing only paths that contains "unit" - -FILTER='unit' npx poku ./test -``` - -```bash -# Testing only paths that contains "unit" by using Poku as a NPM script - -FILTER='unit' npm run tests -``` diff --git a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/poku/configs/no-exit.mdx b/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/poku/configs/no-exit.mdx deleted file mode 100644 index bcf57767..00000000 --- a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/poku/configs/no-exit.mdx +++ /dev/null @@ -1,39 +0,0 @@ ---- -sidebar_position: 7 ---- - -# `noExit` - -> `poku(targetPaths: string | string[], configs?: Configs)` -> -> `noExit: boolean` - -By setting `noExit` to `true`, **Poku** won't exit the process and will return the exit code (`0` or `1`).
-You can combine this option with **Poku**'s `exit` method or just use the result, for example: `process.exit(code)`. - -## API (_in-code_) - -```ts -import { poku, exit } from 'poku'; - -const unit = await poku('test/unit', { - noExit: true, - parallel: true, - quiet: true, -}); - -// do something - -const integration = await poku('test/integration', { - noExit: true, - quiet: true, -}); - -// do something more - -const code = unit === 0 && integration === 0 ? 0 : 1; - -// do something more again - -exit(code); -``` diff --git a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/poku/configs/parallel.mdx b/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/poku/configs/parallel.mdx deleted file mode 100644 index ad6f3c62..00000000 --- a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/poku/configs/parallel.mdx +++ /dev/null @@ -1,41 +0,0 @@ ---- -sidebar_position: 1 ---- - -# `parallel` - -> `poku(targetPaths: string | string[], configs?: Configs)` -> -> `parallel: boolean` - -## API (_in-code_) - -```ts -/** - * @default - * - * Sequential mode - */ - -poku(['...'], { - parallel: false, -}); -``` - -```ts -/** - * Parallel mode - */ - -poku(['...'], { - parallel: true, -}); -``` - -## CLI - -```bash -# Parallel mode - -npx poku --parallel ./test -``` diff --git a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/poku/configs/platform.mdx b/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/poku/configs/platform.mdx deleted file mode 100644 index 6937bdbe..00000000 --- a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/poku/configs/platform.mdx +++ /dev/null @@ -1,72 +0,0 @@ ---- -sidebar_position: 3 ---- - -# `platform` - -> `poku(targetPaths: string | string[], configs?: Configs)` -> -> `platform: "node" | "bun" | "deno"` - -> _Since **1.2.0**_ - -By default, **Poku** tries to identify the platform automatically, but you can set it manually: - -## API (_in-code_) - -```ts -/** - * Force Node.js (or tsx for TypeScript) - * - * @default 'node' - */ - -poku('...', { - platform: 'node', -}); -``` - -```ts -/** - * Force Bun - */ - -poku('...', { - platform: 'bun', -}); -``` - -```ts -/** - * Force Deno - */ - -poku('...', { - platform: 'deno', -}); -``` - -## CLI - -```bash -# Normal - -npx poku --platform=node ./test -bun poku --platform=bun ./test -deno run npm:poku --platform=deno ./test -``` - -```bash -# Custom -# When you're developing using a platform, but maintain compatibility with others - -npx poku --platform=bun ./test -bun poku --platform=deno ./test -deno run npm:poku --platform=node ./test - -# ... -``` - -:::tip -Useful when there is more than one common platform installed. -::: diff --git a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/poku/configs/quiet.mdx b/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/poku/configs/quiet.mdx deleted file mode 100644 index 8984a43c..00000000 --- a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/poku/configs/quiet.mdx +++ /dev/null @@ -1,28 +0,0 @@ ---- -sidebar_position: 5 ---- - -# `quiet` - -> `poku(targetPaths: string | string[], configs?: Configs)` -> -> `quiet: boolean` - -Perform tests with no logs.
-This option overwrites all `log` settings by exiting with code and no logs (see bellow). - -## API (_in-code_) - -```ts -poku(['...'], { - quiet: true, -}); -``` - -## CLI - -> _Since **1.3.1**_ - -```bash -npx poku --quiet ./test -``` diff --git a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/poku/include-files.mdx b/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/poku/include-files.mdx deleted file mode 100644 index 99643476..00000000 --- a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/documentation/poku/include-files.mdx +++ /dev/null @@ -1,56 +0,0 @@ ---- -sidebar_position: 1 ---- - -# Include Directories and Files - -> `poku(targetPaths: string | string[])` -> -> By default, **Poku** searches for _`.test.`_ and `.spec.` files, but you can customize it using the [`filter`](/docs/documentation/poku/configs/filter) option. - -## API (_in-code_) - -```ts -poku('targetePath'); -``` - -```ts -poku(['targetePathA', 'targetePathB']); -``` - -```ts -poku('./'); -``` - -## CLI - -By setting the directories as the **last argument**: - -> _Since **1.3.0**_ - -```bash -npx poku targetePath -``` - -```bash -npx poku targetePathA,targetePathB -``` - -```bash -# Same as ./ -npx poku -``` - -By using `--include` option, you can use it in any order: - -```bash -npx poku --include='targetePath' -``` - -```bash -npx poku --include='targetePathA,targetePathB' -``` - -```bash -npx poku --include='./' -``` diff --git a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/examples/DOM.mdx b/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/examples/DOM.mdx deleted file mode 100644 index 886b0a5c..00000000 --- a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/examples/DOM.mdx +++ /dev/null @@ -1,25 +0,0 @@ ---- -sidebar_position: 3 ---- - -# Virtual DOM - -Let's simule a **Virtual DOM** (Browser) by using [**jsdom**](https://github.com/jsdom/jsdom), then testing its results with **Poku**: - -```ts -import { assert } from 'poku'; -import { JSDOM } from 'jsdom'; - -const dom = new JSDOM('
Poku
'); -const document = dom.window.document; - -const name = document.querySelector('#name'); - -assert.strictEqual(name?.textContent, 'Poku', 'My div contains a Poku 🐷'); -``` - -Then: - -```bash -npx poku -``` diff --git a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/examples/cases/_category_.json b/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/examples/cases/_category_.json deleted file mode 100644 index f7ce81ca..00000000 --- a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/examples/cases/_category_.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "label": "Use Cases", - "collapsed": true, - "link": { - "type": "generated-index" - } -} diff --git a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/examples/cases/compexy-no-exit.mdx b/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/examples/cases/compexy-no-exit.mdx deleted file mode 100644 index 3735cc61..00000000 --- a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/examples/cases/compexy-no-exit.mdx +++ /dev/null @@ -1,76 +0,0 @@ -# A Complex Case - -**Imagine these steps to perform a test:** - -1. Perform **Unit Tests** suite in parallel -2. Clear and Populate the Database -3. Check for **Expected Successes Integration** suite sequentially -4. Clear and Populate the Database — again -5. Check for **Expected Failures Integration** suite sequentially - -**Requirements:** - -Each step requires success to be processed. - -**Directory Structure:** - -```bash -├── . -├── test -│ ├── unit -│ ├── integration -│ │ ├── successes -│ │ │ └── **/.spec.js -│ │ └── failures -│ │ └── **/.spec.js -│ ├─ run.test.js # The runner -│ ├─ tools.test.js -``` - -> Do we really need to complicate things even more by creating advanced tests runs to run our already complex tests? 😅 - -### Poku's Solution ✨ - -```ts -import { poku, assert } from 'poku'; -import { recreateDatabase } from './tools.test.js'; - -const unitCode = await poku('test/unit', { - parallel: true, - noExit: true, -}); - -assert.strictEqual(0, unitCode, 'Running Unit Tests'); - -await assert.doesNotReject( - recreateDatabase(), - 'Preparing DB for Successes Integration Tests' -); - -const successesCode = await poku('test/integration/successes', { - noExit: true, -}); - -assert.strictEqual(0, successesCode, 'Running Successes Integration Tests'); - -await assert.doesNotReject( - recreateDatabase(), - 'Preparing DB for Successes Integration Tests' -); - -const failuresCode = await poku('test/integration/failures', { - noExit: true, -}); - -assert.strictEqual(0, failuresCode, 'Running Failures Integration Tests'); -``` - -> Why comment the code if we can do it better? 🧙🏻 - -**Finally** - -```bash -npx poku test/run.test.js -``` - -> Or `npx poku test/run.test.ts` for **TypeScript**. diff --git a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/examples/cjs-esm.mdx b/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/examples/cjs-esm.mdx deleted file mode 100644 index e9339793..00000000 --- a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/examples/cjs-esm.mdx +++ /dev/null @@ -1,32 +0,0 @@ ---- -sidebar_position: 4 ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -# CJS and ESM - -Just set your **package.json** as usual and that's it.
-**Poku** doesn't require any configuration 🐷 - - - - -```json -{ - "type": "commonjs" -} -``` - - - - -```json -{ - "type": "module" -} -``` - - - diff --git a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/examples/mock/_category_.json b/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/examples/mock/_category_.json deleted file mode 100644 index 71abb29d..00000000 --- a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/examples/mock/_category_.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "label": "Mock", - "collapsed": true, - "link": { - "type": "generated-index" - }, - "position": 2 -} diff --git a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/examples/mock/cjs.mdx b/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/examples/mock/cjs.mdx deleted file mode 100644 index 6f498499..00000000 --- a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/examples/mock/cjs.mdx +++ /dev/null @@ -1,64 +0,0 @@ -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -# Mock using CJS - -You can use your favorite **Mock** framework or tool and **Poku** together 🐷➕ - -For this example, let's use the [**quibble**](https://github.com/testdouble/quibble), then testing its results with **Poku**: - - - - - ```js - const { assert } = require('poku'); - const quibble = require('quibble'); - - (async () => { - await quibble('../lib/funds.js', { - // Original: 100 - getFunds: () => 200, - }); - - const { withdraw } = require('../lib/withdraw.js'); - - assert.strictEqual(withdraw(200), true, 'Mocking my funds to 200'); - - assert.strictEqual(withdraw(300), false, "I can't get more than I have"); - - await quibble.reset(); - })(); - ``` - - - - - ```js - const getFunds = () => 100; - - module.exports = { getFunds }; - ``` - - - - - ```js - const { getFunds } = require('./funds.js'); - - const withdraw = (value) => { - const wallet = getFunds(); - - return value <= wallet; - }; - - module.exports = { withdraw }; - ``` - - - - -Then: - -```bash -npx poku -``` diff --git a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/examples/mock/esm.mdx b/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/examples/mock/esm.mdx deleted file mode 100644 index fe0120f8..00000000 --- a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/examples/mock/esm.mdx +++ /dev/null @@ -1,58 +0,0 @@ -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -# Mock using ESM - -You can use your favorite **Mock** framework or tool and **Poku** together 🐷➕ - -For this example, let's use the [**quibble**](https://github.com/testdouble/quibble), then testing its results with **Poku**: - - - - - ```js - import { assert } from 'poku'; - import quibble from 'quibble'; - - await quibble.esm('../lib/funds.js', { - // Original: 100 - getFunds: () => 200, - }); - - const { withdraw } = await import('../lib/withdraw.test.js'); - - assert.strictEqual(withdraw(200), true, 'Mocking my funds to 200'); - - assert.strictEqual(withdraw(300), false, "I can't get more than I have"); - - await quibble.reset(); - ``` - - - - - ```js - export const getFunds = () => 100; - ``` - - - - - ```js - import { getFunds } from './funds.js'; - - export const withdraw = (value) => { - const wallet = getFunds(); - - return value <= wallet; - }; - ``` - - - - -Then: - -```bash -npx poku -``` diff --git a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/index.mdx b/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/index.mdx index 0ea8074a..4f96db2e 100644 --- a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/index.mdx +++ b/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/index.mdx @@ -129,8 +129,7 @@ Você também pode usar o **Poku** via [**esm.sh**](https://esm.sh): import { poku } from 'https://esm.sh/poku'; ``` - - + ### **Teste** 🔬 @@ -147,6 +146,8 @@ assert(true, 'Poku irá descrever isso 🐷'); +> Note que os exemplos são baseados em [**ESM**](/docs/examples/cjs-esm), mas você pode usar [**CJS**](/docs/examples/cjs-esm) normalmente. + ### **Execute** 🚀 @@ -185,9 +186,29 @@ deno run npm:poku
+## Métodos Disponíveis + +### Essenciais + +- `poku` (_test runner_) +- `assert` e `assertPromise` (_testes de asserção_) +- `startService` e `startScript` (_excecutar serviços em plano de fundo_) + +### Auxiliares + +- `test` +- `beforeEach` e `afterEach` +- `describe` e `log` +- `listFiles` +- `exit` + +[**Veja a documentação completa**](/docs/category/documentation). + +
+ ## Documentação -> Inicialmente, a [**documentação**](/docs/category/documentation) e [**exemplos**](/docs/category/examples) são baseados no **Node.js**, mas você pode usar tudo normalmente para **Bun** and **Deno**. +> Inicialmente, a [**documentação**](/docs/category/documentation) e [**exemplos**](/docs/category/examples) são baseados no **Node.js** e **ESM**, mas você pode usar tudo normalmente para **Bun** e **Deno**, além do **CJS**.
@@ -226,21 +247,21 @@ Verifique o [**SECURITY.md**](https://github.com/wellwelwel/poku/blob/main/SECUR style={{ textDecoration: 'none', color: 'inherit' }} > Contribuidores
-## Autor +## Author wellwelwel
@wellwelwel diff --git a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/overview.mdx b/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/overview.mdx index 20be5ce3..43432bce 100644 --- a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/overview.mdx +++ b/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/overview.mdx @@ -13,7 +13,7 @@ import ASSERT_NODE from '@site/static/img/assert-node.png'; | | | - Por padrão, o **Poku**: - - Procura por todos os arquivos _`.test.`_ e `.spec.`, mas você pode personalizar isso usando a opção [**`filter`**](/docs/documentation/poku/configs/filter). + - Procura por todos os arquivos _`.test.`_ e `.spec.`, mas você pode personalizar isso usando a opção [**`filter`**](/docs/documentation/poku/options/filter). - Usa o modo `sequencial`. - Você pode usar concorrência ao definir a opção `--parallel` no terminal ou definindo a opção `parallel` como `true` ao usar a **API** (_in-code_). diff --git a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/security.mdx b/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/security.mdx index be49ef12..422639e0 100644 --- a/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/security.mdx +++ b/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/security.mdx @@ -15,7 +15,7 @@ Alguns _Test Runners_ usam **`eval`**, o **Poku** prefere usar o **`spawn`** par - `\` para **Windows** - `/` para **Linux** e **macOS** - Normaliza os caminhos ao filtrar caractéres incomuns para caminhos, por exemplo: - - `<>:|^?*` + - `<>|^?*` - Previne _shell scripts_ ao definir `shell` como `false` no **`spawn`**, garantindo que apenas argumentos seguros serão usados. - Cada **RegExp** é previamente testado usando o [**ReDoS Checker**](https://devina.io/redos-checker). diff --git a/website/src/css/custom.scss b/website/src/css/custom.scss index 8c69ed21..e03fc7f3 100644 --- a/website/src/css/custom.scss +++ b/website/src/css/custom.scss @@ -41,7 +41,7 @@ } .theme-code-block-highlighted-line { - opacity: 0.35; + opacity: 0.5; font-style: italic; font-size: 0.8rem; background-color: unset !important;