From 94caefe8ea29ad6a7714a9daad3d7558b7358e2b Mon Sep 17 00:00:00 2001 From: Ben Merckx Date: Wed, 19 Jun 2024 12:48:04 +0200 Subject: [PATCH] Conditional exports --- .github/workflows/jsr.yml | 7 ++-- .gitignore | 3 +- .vscode/settings.json | 17 +++++++++ biome.json | 49 +++++++++++++++++++++++++ bun.lockb | Bin 3123 -> 3837 bytes bunfig.toml | 2 ++ deno.json | 5 +++ jsr.json | 9 +++-- jsr.ts | 10 ++++++ mod.ts | 5 --- package.json | 27 ++++++++++---- src/suite.bun.js | 22 ++++++++++++ suite.d.ts => src/suite.d.ts | 68 +++++++++++++++++------------------ src/suite.deno.js | 26 ++++++++++++++ src/suite.node.js | 17 +++++++++ suite.js | 68 ----------------------------------- suite.test.js | 6 ++-- 17 files changed, 219 insertions(+), 122 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 biome.json create mode 100644 bunfig.toml create mode 100644 deno.json create mode 100644 jsr.ts delete mode 100644 mod.ts create mode 100644 src/suite.bun.js rename suite.d.ts => src/suite.d.ts (80%) create mode 100644 src/suite.deno.js create mode 100644 src/suite.node.js delete mode 100644 suite.js diff --git a/.github/workflows/jsr.yml b/.github/workflows/jsr.yml index 9259173..531cf75 100644 --- a/.github/workflows/jsr.yml +++ b/.github/workflows/jsr.yml @@ -14,6 +14,9 @@ jobs: steps: - uses: actions/checkout@v4 - + - name: Install dependencies + run: bun i --frozen-lockfile + - name: Build package + run: bun run build - name: Publish package - run: npx jsr publish \ No newline at end of file + run: npx jsr publish diff --git a/.gitignore b/.gitignore index b512c09..b8aeac5 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -node_modules \ No newline at end of file +/node_modules +/dist \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..013d400 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,17 @@ +{ + "editor.formatOnSave": true, + "editor.tabSize": 2, + "editor.codeActionsOnSave": { + "source.organizeImports": "explicit", + "quickfix.biome": "explicit" + }, + "[typescript]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[javascript]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "[json]": { + "editor.defaultFormatter": "biomejs.biome" + } +} diff --git a/biome.json b/biome.json new file mode 100644 index 0000000..48d608b --- /dev/null +++ b/biome.json @@ -0,0 +1,49 @@ +{ + "$schema": "https://biomejs.dev/schemas/1.7.1/schema.json", + "organizeImports": { + "enabled": true + }, + "javascript": { + "formatter": { + "quoteStyle": "single", + "semicolons": "asNeeded", + "bracketSpacing": false, + "trailingComma": "none", + "arrowParentheses": "asNeeded" + } + }, + "formatter": { + "enabled": true, + "formatWithErrors": false, + "indentStyle": "space", + "indentWidth": 2, + "lineWidth": 80, + "lineEnding": "lf", + "ignore": [] + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true, + "correctness": { + "noConstructorReturn": "off" + }, + "style": { + "noNonNullAssertion": "off", + "useEnumInitializers": "off", + "noParameterAssign": "off", + "useShorthandFunctionType": "off" + }, + "complexity": { + "noBannedTypes": "off" + }, + "suspicious": { + "noExplicitAny": "off", + "noConstEnum": "off", + "noAssignInExpressions": "off", + "noConfusingLabels": "off", + "noExportsInTest": "off" + } + } + } +} diff --git a/bun.lockb b/bun.lockb index 3a37b70fad5b966bd0e37fd68d6694646772627a..5c532e11e56c5f0e12ecc8ce26ef86070a5589f8 100644 GIT binary patch delta 1051 zcmbVLT}V@57(U<5=FZvXZzkF@gT%k;oU_$xGygz^&@M{Qh1tw-)uyh^9YYOtN|{lC z^Hb`gOp&0hh_Y^Kg+z9F-=z(|7-o4NJ@$EU!8BJVD z?%^_L=CAcF-5d~(kCs>2v&*s;tG-*=!nq3S@lcuTwDChj6cq&PHl|q3>`FsX&L)d! zh9({=hN4`1f#ZM`z)-GfU=X`f5Jf40Yk^h33Bcrc7zcHBE_>WEGq`rorin9wFQ$<| zd5>fF^*5dFvF6xR&})Ha z3#pIJ$Bt~j`${=TFHF%Hw+bsu;)|3;7T4DY%%W>iwWRisy}o#3pWNs8;pvx7eaoR3 z&rn@)%+DQb>5E(X<)LieKk9*-N?RmsJ$t3 zzVesHiX$uEPY%7a`=hUP6?dK7-|JArbr2PZ4gk}*gEr!BX(XPdOOXs~q(-clMdE&G zDUxHK)QA{tkUi-|8FwP;5IzubP;oW%>^&@QlIN}oEUzHw5`26LjTr@=kaO#ZvBWlF zYy=cBR!_nKs3MXyj(8k?9>jaHLS*3;!abptRwXtuCS5pf;j~DQN#L|v9j6WFFPtBk zXgGlrC~6u%WRkXpb2t3#Ld#|AltqHt^qh{<2vj(sZocwd+Pz!@Otb>0(Q^7)gjH-} z>feGaxEaAyNHzhZ!aLc5V5V?4E2PhY!zAn{^t$J$IVzxshQJ(pmlQco`n>fTY-f`2 zPd2{2!0K$|onmcub&b<$ZWND*qTQLz^EP_}2P4jMlyBoT8vaimzw+m|aN^i>O8NGY%9gI-~^GHsMo$Rxi2qPYjP delta 606 zcmew>yIEp_o~D$X7;od1C+ioyGW~lcWAP^`6TUrnU)n!hm$kUcc+IZ4i@6!VfPG@P zyjM0mgu}p4T$)*u3gmD>aDyk1=44=KmPX&xZm0~H5SAhitzdR9j>uP>09 z_@IJOWb#c$d&Z#2l1%nY3m7IxG1)OaW0*XP$&OKd@=Ydt#`MXO%+`|w7+DgTfVvrh zm>GycY*r|r4M>9khz7~Sod;xt)Df+3@=fNF$$weAC(mHvogB*Q&B#1?A#3<#4_4mE ztZd$ltdj%T!YBU#^0u<=-aLann~`e+)UG4!lk+)kWf&O#{f7XcwP5#rfGXhNn0$;= zPYmRA79a*W-GT#106_>yN=*&sdYI2(N56*y}*P=TqQk(r(e zPyr;)ChAA^s%^EkWMb3;ihw`|FiJt-1n1-yZimSyxDBMDf#D2_*cJ=ZGmI5{|9(J~ U%;ugf#A7x2C9l%vA3Ur~0PpB~l>h($ diff --git a/bunfig.toml b/bunfig.toml new file mode 100644 index 0000000..c484560 --- /dev/null +++ b/bunfig.toml @@ -0,0 +1,2 @@ +[install.scopes] +"@jsr" = "https://npm.jsr.io" \ No newline at end of file diff --git a/deno.json b/deno.json new file mode 100644 index 0000000..a12d03b --- /dev/null +++ b/deno.json @@ -0,0 +1,5 @@ +{ + "imports": { + "#suite": "./dist/suite.deno.js" + } +} diff --git a/jsr.json b/jsr.json index 2aa04b2..a43590c 100644 --- a/jsr.json +++ b/jsr.json @@ -1,5 +1,8 @@ { "name": "@benmerckx/suite", - "version": "0.2.0", - "exports": "./mod.ts" -} \ No newline at end of file + "version": "0.3.0", + "exports": "./jsr.ts", + "publish": { + "exclude": ["!dist"] + } +} diff --git a/jsr.ts b/jsr.ts new file mode 100644 index 0000000..4a4a88a --- /dev/null +++ b/jsr.ts @@ -0,0 +1,10 @@ +import type {Suite} from './src/suite' + +/** Define a test suite */ +export const suite: Suite = ( + await ('Bun' in globalThis + ? import('./src/suite.bun.js') + : 'Deno' in globalThis + ? import('./dist/suite.deno.js') + : import('./src/suite.node.js')) +).suite diff --git a/mod.ts b/mod.ts deleted file mode 100644 index f00ad0a..0000000 --- a/mod.ts +++ /dev/null @@ -1,5 +0,0 @@ -import {suite as untypedSuite} from './suite.js' -import type {Suite} from './suite.d.ts' - -/** Define a test suite */ -export const suite: Suite = untypedSuite \ No newline at end of file diff --git a/package.json b/package.json index 5d281d4..d3e69a4 100644 --- a/package.json +++ b/package.json @@ -1,24 +1,39 @@ { - "version": "0.2.0", + "version": "0.3.0", "name": "@benmerckx/suite", "module": "suite.js", "types": "suite.d.ts", "type": "module", - "files": [ - "suite.js", - "suite.d.ts" - ], + "files": ["./dist", "./src"], "devDependencies": { + "@jsr/std__assert": "^0.225.2", "@types/bun": "latest" }, "peerDependencies": { "typescript": "^5.0.0" }, "scripts": { + "build": "bun build src/suite.deno.js --outdir=dist --minify", "test": "node --test && deno test && bun test", "deploy": "npm publish && npx jsr publish" }, "publishConfig": { "access": "public" + }, + "exports": { + ".": { + "deno": "./dist/suite.deno.js", + "bun": "./src/suite.bun.js", + "node": "./src/suite.node.js", + "types": "./src/suite.d.ts" + } + }, + "imports": { + "#suite": { + "deno": "./dist/suite.deno.js", + "bun": "./src/suite.bun.js", + "node": "./src/suite.node.js", + "types": "./src/suite.d.ts" + } } -} \ No newline at end of file +} diff --git a/src/suite.bun.js b/src/suite.bun.js new file mode 100644 index 0000000..7192e56 --- /dev/null +++ b/src/suite.bun.js @@ -0,0 +1,22 @@ +export function setup(meta) { + // @ts-ignore + const native = Bun.jest(meta.path) + const test = native.test.bind() + test.skip = native.test.skip + test.only = native.test.only + test.ok = a => native.expect(a).toBeTruthy() + test.is = (a, b) => native.expect(a).toBe(b) + test.equal = (a, b) => native.expect(a).toEqual(b) + test.throws = (fn, err) => + err === undefined + ? native.expect(fn).toThrow() + : native.expect(fn).toThrow(err) + test.not = { + ok: a => native.expect(a).toBeFalsy(), + is: (a, b) => native.expect(a).not.toBe(b), + equal: (a, b) => native.expect(a).not.toEqual(b) + } + return test +} + +export const suite = (meta, define) => define(setup(meta)) diff --git a/suite.d.ts b/src/suite.d.ts similarity index 80% rename from suite.d.ts rename to src/suite.d.ts index 45c2eeb..d8e75ad 100644 --- a/suite.d.ts +++ b/src/suite.d.ts @@ -1,35 +1,35 @@ -/** Describe a test */ -export type Describe = - (name: string, run: ()=> void | Promise) => void - -/** Define a test suite */ -export interface DefineTest extends Describe { - /** Skip the test */ - skip: Describe - /** Only run this test */ - only: Describe - /** Assert that actual is a truthy value */ - ok(actual: any): void - /** Assert that actual strictly equals (===) the expects value */ - is(actual: any, expects: any): void - /** Assert that actual is deeply equal to the expects value */ - equal(actual: any, expects: any): void - /** Assert that the fn function throws an Error */ - throws(fn: () => void, messageIncludes?: string): void - /** Assert inverse */ - not: { - /** Assert that actual is a falsy value */ - ok(actual: any): void - /** Assert that actual does not strictly equal (===) the expects value */ - is(actual: any, expects: any): void - /** Assert that actual is not deeply equal to the expects value */ - equal(actual: any, expects: any): void - } -} - -/** Define a test suite */ -export type Suite = - (meta: ImportMeta, define: (test: DefineTest) => void) => void - -/** Define a test suite */ +/** Describe a test */ +export type Describe = (name: string, run: () => void | Promise) => void + +/** Define a test suite */ +export interface DefineTest extends Describe { + /** Skip the test */ + skip: Describe + /** Only run this test */ + only: Describe + /** Assert that actual is a truthy value */ + ok(actual: any): void + /** Assert that actual strictly equals (===) the expects value */ + is(actual: any, expects: any): void + /** Assert that actual is deeply equal to the expects value */ + equal(actual: any, expects: any): void + /** Assert that the fn function throws an Error */ + throws(fn: () => void, messageIncludes?: string): void + /** Assert inverse */ + not: { + /** Assert that actual is a falsy value */ + ok(actual: any): void + /** Assert that actual does not strictly equal (===) the expects value */ + is(actual: any, expects: any): void + /** Assert that actual is not deeply equal to the expects value */ + equal(actual: any, expects: any): void + } +} + +/** Define a test suite */ +export interface Suite { + (meta: ImportMeta, define: (test: DefineTest) => void): void + // runtime: 'node' | 'deno' | 'bun' +} + export const suite: Suite \ No newline at end of file diff --git a/src/suite.deno.js b/src/suite.deno.js new file mode 100644 index 0000000..368fd6d --- /dev/null +++ b/src/suite.deno.js @@ -0,0 +1,26 @@ +import { + assert, + assertEquals, + assertFalse, + assertNotEquals, + assertNotStrictEquals, + assertStrictEquals, + assertThrows +} from '../node_modules/@jsr/std__assert/mod.js' + +// @ts-ignore +const native = Deno.test +const test = native.bind() +test.skip = native.ignore +test.only = native.only +test.ok = assert +test.is = assertStrictEquals +test.equal = assertEquals +test.throws = assertThrows +test.not = { + ok: assertFalse, + is: assertNotStrictEquals, + equal: assertNotEquals +} + +export const suite = (meta, define) => define(test) diff --git a/src/suite.node.js b/src/suite.node.js new file mode 100644 index 0000000..23c2347 --- /dev/null +++ b/src/suite.node.js @@ -0,0 +1,17 @@ +import * as asserts from 'node:assert' +import * as native from 'node:test' + +const test = native.test.bind() +test.skip = native.skip +test.only = native.only +test.ok = asserts.ok +test.is = asserts.strictEqual +test.equal = asserts.deepStrictEqual +test.throws = asserts.throws +test.not = { + ok: a => asserts.ok(!a), + is: asserts.notStrictEqual, + equal: asserts.notDeepStrictEqual +} + +export const suite = (meta, define) => define(test) diff --git a/suite.js b/suite.js deleted file mode 100644 index 5e4242d..0000000 --- a/suite.js +++ /dev/null @@ -1,68 +0,0 @@ -var isBun = 'Bun' in globalThis -var isDeno = !isBun && 'Deno' in globalThis -var isNode = !isDeno && 'process' in globalThis - -var setup - -if (isBun) { - setup = meta => { - const native = Bun.jest(meta.path) - const test = native.test.bind() - test.skip = native.test.skip - test.only = native.test.only - test.ok = a => native.expect(a).toBeTruthy() - test.is = (a, b) => native.expect(a).toBe(b) - test.equal = (a, b) => native.expect(a).toEqual(b) - test.throws = (fn, err) => - err === undefined ? native.expect(fn).toThrow() : native.expect(fn).toThrow(err) - test.not = { - ok: a => native.expect(a).toBeFalsy(), - is: (a, b) => native.expect(a).not.toBe(b), - equal: (a, b) => native.expect(a).not.toEqual(b) - } - return test - } -} else if (isNode) { - try { - const asserts = await import('node:assert') - const native = await import('node:test') - const test = native.test.bind() - test.skip = native.skip - test.only = native.only - test.ok = asserts.ok - test.is = asserts.strictEqual - test.equal = asserts.deepStrictEqual - test.throws = asserts.throws - test.not = { - ok: a => asserts.ok(!a), - is: asserts.notStrictEqual, - equal: asserts.notDeepStrictEqual - } - setup = () => test - } catch { - console.error(`Node.js built-in test module not found`) - process.exit(1) - } -} else if (isDeno) { - const asserts = await import('jsr:@std/testing@0.225.1/asserts') - const native = Deno.test - const test = native.bind() - test.skip = native.ignore - test.only = native.only - test.ok = asserts.assert - test.is = asserts.assertStrictEquals - test.equal = asserts.assertEquals - test.throws = asserts.assertThrows - test.not = { - ok: asserts.assertFalse, - is: asserts.assertNotStrictEquals, - equal: asserts.assertNotEquals - } - setup = () => test -} else { - throw new Error(`Unsupported runtime`) -} - -export function suite(meta, define) { - return define(setup(meta)) -} diff --git a/suite.test.js b/suite.test.js index 346afe9..7c5e7b4 100644 --- a/suite.test.js +++ b/suite.test.js @@ -1,6 +1,6 @@ -import {suite} from './suite.js' +import {suite} from '#suite' -suite(import.meta, (test) => { +suite(import.meta, test => { test('truthy', () => { test.ok(true) }) @@ -48,4 +48,4 @@ suite(import.meta, (test) => { /*test.only('only', () => { test.ok(true) })*/ -}) \ No newline at end of file +})