From a4343556195329041f887ccbf443bcb88bf8305a Mon Sep 17 00:00:00 2001 From: filmaj Date: Sun, 6 Apr 2025 18:24:17 -0400 Subject: [PATCH 1/6] test: nested semicolons fail lexing --- test/00-lexer-test.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/00-lexer-test.js b/test/00-lexer-test.js index 1811e23..1391eb2 100644 --- a/test/00-lexer-test.js +++ b/test/00-lexer-test.js @@ -14,6 +14,10 @@ false false false # comment with spaces foo bar + +thing + nested thing + semi;colons ` test('lex', t => { From f23a2ce4f45bbb19efb68eb22060a3b7e6aa62c0 Mon Sep 17 00:00:00 2001 From: filmaj Date: Sun, 6 Apr 2025 23:40:55 -0400 Subject: [PATCH 2/6] chore: drop support for node 18 and below. drop many testing related dev dependencies and use native node test runner --- .github/workflows/build.yml | 11 +---- changelog.md | 8 ++++ package.json | 11 ++--- readme.md | 2 +- test/00-lexer-test.js | 18 ++++----- test/01-ast-scalar-test.js | 14 +++---- test/02-ast-complex-test.js | 32 +++++++-------- test/03-errors-test.js | 76 +++++++++++++++++------------------ test/04-compiler-test.js | 80 ++++++++++++++++++------------------- test/05-parser-test.js | 50 +++++++++++------------ test/06-compat-test.js | 22 +++++----- test/07-stringify-test.js | 4 +- test/08-values-test.js | 68 +++++++++++++++---------------- test/09-architect-test.js | 50 +++++++++++------------ 14 files changed, 219 insertions(+), 227 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4f66594..d0e5af4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -15,7 +15,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - node-version: [ 16.x, 18.x, 20.x ] + node-version: [ 20.x, 22.x ] os: [ windows-latest, ubuntu-latest, macOS-latest ] # Go @@ -46,14 +46,7 @@ jobs: - name: Install run: npm install - - name: Test (Node.js <= 16.x only) - if: matrix.node-version <= '16.x' - run: npm run test:nolint - env: - CI: true - - name: Test - if: matrix.node-version > '16.x' run: npm test env: CI: true @@ -61,7 +54,7 @@ jobs: - name: Notify uses: sarisia/actions-status-discord@v1 # Only fire alert once - if: github.ref == 'refs/heads/main' && failure() && matrix.node-version == '20.x' && matrix.os == 'ubuntu-latest' + if: github.ref == 'refs/heads/main' && failure() && matrix.node-version == '22.x' && matrix.os == 'ubuntu-latest' with: webhook: ${{ secrets.DISCORD_WEBHOOK }} title: "build and test" diff --git a/changelog.md b/changelog.md index 740d2be..2f8545c 100644 --- a/changelog.md +++ b/changelog.md @@ -2,6 +2,14 @@ --- +## [8.0.0] 2025-04-06 + +### Changed + +- Breaking change: dropped node 16, 18 support + +--- + ## [7.0.0 - 7.0.1] 2024-01-08 ### Changed diff --git a/package.json b/package.json index 85e15ea..27f4f2d 100644 --- a/package.json +++ b/package.json @@ -7,9 +7,8 @@ "deno:test": "deno test -A --unstable mod.test.ts", "deno:fmt": "deno fmt mod.ts && deno fmt mod.test.ts", "lint": "eslint . --fix", - "test:unit": "cross-env tape 'test/*-test.js' | tap-arc", - "coverage": "nyc --reporter=lcov --reporter=text-summary npm run test:unit", - "test:nolint": "npm run coverage", + "test:unit": "node --test", + "coverage": "node --test --experimental-test-coverage", "test": "npm run lint && npm run coverage", "rc": "npm version prerelease --preid RC", "build": "rollup -c", @@ -17,7 +16,7 @@ "vendor": "npm run vendor:js-yaml" }, "engines": { - "node": ">=16" + "node": ">=20" }, "repository": { "type": "git", @@ -34,13 +33,9 @@ "@rollup/plugin-json": "^6.0.0", "@rollup/plugin-terser": "~0.4.3", "browserify": "~17.0.0", - "cross-env": "~7.0.3", "eslint": "~9.1.1", "js-yaml": "~4.1.0", - "nyc": "^15.1.0", "rollup": "^3.27.0", - "tap-arc": "~1.2.2", - "tape": "~5.7.5", "terser": "~5.31.0" } } diff --git a/readme.md b/readme.md index 31528a5..80177c8 100644 --- a/readme.md +++ b/readme.md @@ -59,7 +59,7 @@ Parsing the file with the following code: ```javascript #!/usr/bin/env node const parse = require('@architect/parser') -const fs = require('fs') +const fs = require('node:fs') const text = fs.readFileSync('./some-arc-file.txt').toString() const result = parse(text) diff --git a/test/00-lexer-test.js b/test/00-lexer-test.js index 1391eb2..8e6e4fc 100644 --- a/test/00-lexer-test.js +++ b/test/00-lexer-test.js @@ -1,4 +1,4 @@ -let test = require('tape') +let test = require('node:test') let lex = require('../src/lexer') let arcfile = ` @@ -15,28 +15,24 @@ false false false # comment with spaces foo bar -thing - nested thing - semi;colons +#semi;colons? ` test('lex', t => { t.plan(5) // can lex - t.ok(lex, 'exists') + t.assert.ok(lex, 'exists') let result = lex(arcfile) // got an array - t.ok(Array.isArray(result), 'lexed') + t.assert.ok(Array.isArray(result), 'lexed') let first = result[0] let second = result[1] let third = result[2] // ensure the arcfile parses as we'd expect - t.ok(first.type === 'newline' && first.line === 1 && first.column === 1, 'line 1 column 1 is a newline') - t.ok(second.type === 'newline' && second.line === 2 && first.column === 1, 'line 2 column 1 is a newline') - t.ok(third.type === 'pragma' && third.value === 'pragma1' && third.line === 3 && third.column === 1, 'hunp') - - console.log(result) + t.assert.ok(first.type === 'newline' && first.line === 1 && first.column === 1, 'line 1 column 1 is a newline') + t.assert.ok(second.type === 'newline' && second.line === 2 && first.column === 1, 'line 2 column 1 is a newline') + t.assert.ok(third.type === 'pragma' && third.value === 'pragma1' && third.line === 3 && third.column === 1, 'hunp') }) diff --git a/test/01-ast-scalar-test.js b/test/01-ast-scalar-test.js index 3ee0976..e78430a 100644 --- a/test/01-ast-scalar-test.js +++ b/test/01-ast-scalar-test.js @@ -1,4 +1,4 @@ -let test = require('tape') +let { test } = require('node:test') let parse = require('../') test('ast empty', t => { @@ -32,8 +32,8 @@ test('ast empty', t => { } let parsed = parse.parser(parse.lexer(mock)) - console.dir(parsed, { depth: null }) - t.same(parsed, expected, 'successfully parsed ast for empty types') + // console.dir(parsed, { depth: null }) + t.assert.deepEqual(parsed, expected, 'successfully parsed ast for empty types') }) test('ast scalars', t => { @@ -74,8 +74,8 @@ true` } let parsed = parse.parser(parse.lexer(mock)) - console.dir(parsed, { depth: null }) - t.same(parsed, expected, 'successfully parsed ast for scalar types') + // console.dir(parsed, { depth: null }) + t.assert.deepEqual(parsed, expected, 'successfully parsed ast for scalar types') }) test('ast arrays', t => { @@ -127,6 +127,6 @@ one true 3 # comment2` let tokens = parse.lexer(mock) let parsed = parse.parser(tokens) - console.dir(parsed, { depth: null }) - t.same(parsed, expected, 'successfully parsed array') + // console.dir(parsed, { depth: null }) + t.assert.deepEqual(parsed, expected, 'successfully parsed array') }) diff --git a/test/02-ast-complex-test.js b/test/02-ast-complex-test.js index 75d45ff..7266243 100644 --- a/test/02-ast-complex-test.js +++ b/test/02-ast-complex-test.js @@ -1,4 +1,4 @@ -let test = require('tape') +let { test } = require('node:test') let parse = require('../') let isVector = require('../src/parser/_is-vector') let isMap = require('../src/parser/_is-map') @@ -15,7 +15,7 @@ vec # hi some stuff here` let tokens = parse.lexer(mock) let start = tokens.slice(3, tokens.length) // start at 'vec' - t.ok(isVector(start), 'found a valid vector') + t.assert.ok(isVector(start), 'found a valid vector') }) test('is not a vector', t => { @@ -26,7 +26,7 @@ map one two` let tokens = parse.lexer(mock) let start = tokens.slice(3, tokens.length) // start at 'map' token - t.ok(isVector(start) === false, 'did not find a valid vector') + t.assert.ok(isVector(start) === false, 'did not find a valid vector') }) test('ast vectors', t => { @@ -106,8 +106,8 @@ this should be ignored` ], } let parsed = parse.parser(parse.lexer(mock)) - console.dir(parsed, { depth: null }) - t.same(parsed, expected, 'successfully parsed vector') + // console.dir(parsed, { depth: null }) + t.assert.deepEqual(parsed, expected, 'successfully parsed vector') }) test('isMap', t => { @@ -123,8 +123,8 @@ map ` let tokens = parse.lexer(mock) let start = tokens.slice(3, tokens.length) - console.log(start) - t.ok(isMap(start)) + // console.log(start) + t.assert.ok(isMap(start)) }) test('map has three keys (vectors)', t => { @@ -137,11 +137,11 @@ m1 # also cool three 3` let tokens = parse.lexer(mock) let ast = parse.parser(tokens) - console.dir(ast, { depth: null }) + // console.dir(ast, { depth: null }) let pragma = ast.values.find(t => t.type === 'pragma' && t.name === 'map-test') let map = pragma.values.find(t => t.type === 'map' && t.name === 'm1') let keys = map.values.filter(t => t.type === 'vector') - t.ok(keys.length === 3, 'has three keys') + t.assert.ok(keys.length === 3, 'has three keys') }) test('map with vector', t => { @@ -157,10 +157,10 @@ m1 #comment2 false` let tokens = parse.lexer(mock) let mapTokens = tokens.slice(5, tokens.length) - t.ok(isVector(mapTokens) === false, 'isVector is false') - t.ok(isMap(mapTokens) === true, 'isMap is true') - let parsed = parse.parser(tokens) - console.dir(parsed, { depth: null }) + t.assert.ok(isVector(mapTokens) === false, 'isVector is false') + t.assert.ok(isMap(mapTokens) === true, 'isMap is true') + /* let parsed = */parse.parser(tokens) + // console.dir(parsed, { depth: null }) }) test('map with scalars and vectors', t => { @@ -185,7 +185,7 @@ m1 #comment2 let map = pragma.values.find(t => t.type === 'map') let keys = map.values.filter( t => t.type === 'vector') let bools = keys.find(t => t.name === 'bools') - t.ok(keys.length === 4, 'has four keys') - t.ok(bools.values.filter(t => t.type === 'boolean').length === 2, 'bools has two booleans') - console.dir(parsed, { depth: null }) + t.assert.ok(keys.length === 4, 'has four keys') + t.assert.ok(bools.values.filter(t => t.type === 'boolean').length === 2, 'bools has two booleans') + // console.dir(parsed, { depth: null }) }) diff --git a/test/03-errors-test.js b/test/03-errors-test.js index 3468768..c6a965d 100644 --- a/test/03-errors-test.js +++ b/test/03-errors-test.js @@ -1,4 +1,4 @@ -let test = require('tape') +let { test } = require('node:test') let parse = require('../') /* lex errors */ @@ -9,9 +9,9 @@ test('pragma errors', t => { parse.lexer(`@pragm&`) } catch (e) { - t.ok(e.name === 'PragmaSyntaxError', e.name) - t.ok(e.line === 1, 'line one') - console.log(e) + t.assert.ok(e.name === 'PragmaSyntaxError', e.name) + t.assert.ok(e.line === 1, 'line one') + // console.log(e) } }) @@ -22,9 +22,9 @@ test('missing end quote', t => { "uh oh`) } catch (e) { - t.ok(e.name === 'CloseQuoteNotFoundError', e.name) - t.ok(e.line === 2, 'on line two') - console.log(e) + t.assert.ok(e.name === 'CloseQuoteNotFoundError', e.name) + t.assert.ok(e.line === 2, 'on line two') + // console.log(e) } }) @@ -34,9 +34,9 @@ test('unknown! (you can quote this to get it working)', t => { parse.lexer(`🤠`) } catch (e) { - t.ok(e.name === 'UnknownCharacterError', e.name) - t.ok(e.line === 1, 'on line one') - console.log(e) + t.assert.ok(e.name === 'UnknownCharacterError', e.name) + t.assert.ok(e.line === 1, 'on line one') + // console.log(e) } }) @@ -48,8 +48,8 @@ test('InvalidTokens', t => { parse.parser('blep') } catch (e) { - t.ok(e.name === 'InvalidTokensError', 'got an InvalidTokensError') - console.log(e) + t.assert.ok(e.name === 'InvalidTokensError', 'got an InvalidTokensError') + // console.log(e) } }) @@ -59,8 +59,8 @@ test('PragmaNotFound', t => { parse.parser(parse.lexer('# nothin to see')) } catch (e) { - t.ok(e.name === 'PragmaNotFound', 'got an PragmaNotFound') - console.log(e) + t.assert.ok(e.name === 'PragmaNotFound', 'got an PragmaNotFound') + // console.log(e) } }) @@ -74,8 +74,8 @@ test('PragmaAlreadyDefined', t => { parse.parser(parse.lexer(arcfile)) } catch (e) { - t.ok(e.name === 'PragmaAlreadyDefined', 'got an PragmaAlreadyDefined') - console.log(e) + t.assert.ok(e.name === 'PragmaAlreadyDefined', 'got an PragmaAlreadyDefined') + // console.log(e) } }) @@ -86,8 +86,8 @@ test('array space; not an error!', t => { @pragma arr val here uh oh`)) - t.ok(value, 'did not parse') - console.dir(value, { depth: null }) + t.assert.ok(value, 'did not parse') + // console.dir(value, { depth: null }) }) // context; this was an error in parser 4.x and lower @@ -100,8 +100,8 @@ map ` let tokens = parse.lexer(arcfile) let ast = parse.parser(tokens) - t.ok(ast) - console.dir(ast, { depth: null }) + t.assert.ok(ast) + // console.dir(ast, { depth: null }) }) // context; this was an error in parser 4.x and lower @@ -114,8 +114,8 @@ map ` let tokens = parse.lexer(arcfile) let ast = parse.parser(tokens) - t.ok(ast) - console.dir(ast, { depth: null }) + t.assert.ok(ast) + // console.dir(ast, { depth: null }) }) test('map name not string error', t => { @@ -128,9 +128,9 @@ false parse.parser(parse.lexer(arcfile)) } catch (e) { - t.same(e.name, 'MapNameNotString') - t.ok(e.line === 2, 'on line 2') - console.log(e) + t.assert.deepEqual(e.name, 'MapNameNotString') + t.assert.ok(e.line === 2, 'on line 2') + // console.log(e) } }) @@ -145,9 +145,9 @@ test('vector name not string error', t => { parse.parser(parse.lexer(arcfile)) } catch (e) { - t.same(e.name, 'VectorNameNotString') - t.ok(e.line === 2, 'on line 2') - console.log(e) + t.assert.deepEqual(e.name, 'VectorNameNotString') + t.assert.ok(e.line === 2, 'on line 2') + // console.log(e) } }) @@ -165,9 +165,9 @@ map t.fail() } catch (e) { - t.same('MapKeyNotString', e.name) - t.ok(e.line === 4, 'on line 4') - console.log(e) + t.assert.deepEqual('MapKeyNotString', e.name) + t.assert.ok(e.line === 4, 'on line 4') + // console.log(e) } }) @@ -184,9 +184,9 @@ map parse.parser(parse.lexer(arcfile)) } catch (e) { - t.same(e.name, 'MapKeyNotString') - t.ok(e.line === 4, 'on line 4') - console.log(e) + t.assert.deepEqual(e.name, 'MapKeyNotString') + t.assert.ok(e.line === 4, 'on line 4') + // console.log(e) } }) @@ -202,8 +202,8 @@ asdfasdfa` console.log(parsed) } catch (e) { - t.ok(e, 'failed on bad input') - console.log(e) + t.assert.ok(e, 'failed on bad input') + // console.log(e) } }) @@ -220,7 +220,7 @@ obj parse.parser(parse.lexer(mock)) } catch (e) { - t.ok(e.name === 'MapKeyUndefinedValue', 'MayKeyUndefinedValue') - console.log(e) + t.assert.ok(e.name === 'MapKeyUndefinedValue', 'MayKeyUndefinedValue') + // console.log(e) } }) diff --git a/test/04-compiler-test.js b/test/04-compiler-test.js index ee13f8b..1fe39a2 100644 --- a/test/04-compiler-test.js +++ b/test/04-compiler-test.js @@ -1,4 +1,4 @@ -let test = require('tape') +let { test } = require('node:test') let parse = require('../') test('can compile scalar values', t => { @@ -13,8 +13,8 @@ true` let tokens = parse.lexer(arcfile) let ast = parse.parser(tokens) let arc = parse.compiler(ast) - t.same(arc, { hello: [ 'world', 2, true ] }) - console.log(arc) + t.assert.deepEqual(arc, { hello: [ 'world', 2, true ] }) + // console.log(arc) }) test('can compile array values', t => { @@ -25,8 +25,8 @@ one 2 true` let tokens = parse.lexer(arcfile) let ast = parse.parser(tokens) let arc = parse.compiler(ast) - t.same(arc, { hello: [ [ 'one', 2, true ] ] }) - console.log(arc) + t.assert.deepEqual(arc, { hello: [ [ 'one', 2, true ] ] }) + // console.log(arc) }) test('can compile array values with quotes (js)', t => { @@ -39,12 +39,12 @@ ssr "node_modules/@enhance/ssr"` let tokens = parse.lexer(arcfile) let ast = parse.parser(tokens) let arc = parse.compiler(ast) - t.same(arc, { bundles: [ + t.assert.deepEqual(arc, { bundles: [ [ 'my-package', 'node_modules/my-package' ], [ 'store', 'node_modules/@enhance/store' ], [ 'ssr', 'node_modules/@enhance/ssr' ], ] }) - console.log(arc) + // console.log(arc) }) test('can compile array values with quotes (arc)', t => { @@ -57,10 +57,10 @@ ssr "node_modules/@enhance/ssr"` let tokens = parse.lexer(arcfile) let ast = parse.parser(tokens) let arc = parse.compiler(ast, 'arc') - t.ok(arc.includes(`my-package node_modules/my-package`)) - t.ok(arc.includes(`store 'node_modules/@enhance/store'`)) - t.ok(arc.includes(`ssr "node_modules/@enhance/ssr"`)) - console.log(arc) + t.assert.ok(arc.includes(`my-package node_modules/my-package`)) + t.assert.ok(arc.includes(`store 'node_modules/@enhance/store'`)) + t.assert.ok(arc.includes(`ssr "node_modules/@enhance/ssr"`)) + // console.log(arc) }) test('can compile array values with quotes (yaml)', t => { @@ -73,10 +73,10 @@ ssr "node_modules/@enhance/ssr"` let tokens = parse.lexer(arcfile) let ast = parse.parser(tokens) let arc = parse.compiler(ast, 'yaml') - t.ok(arc.includes(`my-package, node_modules/my-package`)) - t.ok(arc.includes(`store, 'node_modules/@enhance/store'`)) - t.ok(arc.includes(`ssr, "node_modules/@enhance/ssr"`)) - console.log(arc) + t.assert.ok(arc.includes(`my-package, node_modules/my-package`)) + t.assert.ok(arc.includes(`store, 'node_modules/@enhance/store'`)) + t.assert.ok(arc.includes(`ssr, "node_modules/@enhance/ssr"`)) + // console.log(arc) }) test('can compile scalar and array values', t => { @@ -90,8 +90,8 @@ one 2 true` let tokens = parse.lexer(arcfile) let ast = parse.parser(tokens) let arc = parse.compiler(ast) - t.same(arc, { hello: [ 'world', 'two', false, [ 'one', 2, true ] ] }) - console.log(arc) + t.assert.deepEqual(arc, { hello: [ 'world', 'two', false, [ 'one', 2, true ] ] }) + // console.log(arc) }) test('can compile vector', t => { @@ -103,8 +103,8 @@ hi let tokens = parse.lexer(arcfile) let ast = parse.parser(tokens) let arc = parse.compiler(ast) - t.same(arc, { hello: [ { hi: [ 'world' ] } ] }) - console.dir(arc, { depth: null }) + t.assert.deepEqual(arc, { hello: [ { hi: [ 'world' ] } ] }) + // console.dir(arc, { depth: null }) }) test('can compile map', t => { @@ -116,8 +116,8 @@ cat let tokens = parse.lexer(arcfile) let ast = parse.parser(tokens) let arc = parse.compiler(ast) - t.same(arc, { pets: [ { cat: { name: 'sutro' } } ] }) - console.dir(arc, { depth: null }) + t.assert.deepEqual(arc, { pets: [ { cat: { name: 'sutro' } } ] }) + // console.dir(arc, { depth: null }) }) test('can compile map with vector', t => { @@ -131,12 +131,12 @@ cat let tokens = parse.lexer(arcfile) let ast = parse.parser(tokens) let arc = parse.compiler(ast) - t.same(arc, { + t.assert.deepEqual(arc, { pets: [ { cat: { names: [ 'sutr0', 'tux3d0' ] } }, ], }) - console.dir(arc, { depth: null }) + // console.dir(arc, { depth: null }) }) test('can compile a simple arc plaintext string', t => { @@ -148,7 +148,7 @@ hello 1 true` let tokens = parse.lexer(origin) let ast = parse.parser(tokens) let arc = parse.compiler(ast, 'arc') - t.ok(arc === origin) + t.assert.ok(arc === origin) }) test('can compile arc plaintext string with vector', t => { @@ -163,7 +163,7 @@ hello let tokens = parse.lexer(origin) let ast = parse.parser(tokens) let arc = parse.compiler(ast, 'arc') - t.ok(arc === origin) + t.assert.ok(arc === origin) }) test('can compile arc plaintext string with map', t => { @@ -177,7 +177,7 @@ hello let tokens = parse.lexer(origin) let ast = parse.parser(tokens) let arc = parse.compiler(ast, 'arc') - t.ok(arc === origin) + t.assert.ok(arc === origin) }) test('can compile arc plaintext string with map with vector', t => { @@ -195,8 +195,8 @@ hello let tokens = parse.lexer(origin) let ast = parse.parser(tokens) let arc = parse.compiler(ast, 'arc') - console.log(origin, arc) - t.ok(arc === origin) + // console.log(origin, arc) + t.assert.ok(arc === origin) }) test('line breaks are preserved across all primitive types', t => { @@ -269,7 +269,7 @@ array a b let tokens = parse.lexer(origin) let ast = parse.parser(tokens) let arc = parse.compiler(ast, 'arc') - t.ok(arc === origin) + t.assert.ok(arc === origin) }) test('can compile simple yaml string', t => { @@ -285,7 +285,7 @@ hi: let tokens = parse.lexer(origin) let ast = parse.parser(tokens) let arc = parse.compiler(ast, 'yaml') - t.same(arc, expected) + t.assert.deepEqual(arc, expected) }) test('js compilation strips escape quotes', t => { @@ -300,10 +300,10 @@ docsearch-css \`node_modules/@docsearch/css/dist/style.css\`` let first = js.bundles[0][1] let second = js.bundles[1][1] let third = js.bundles[2][1] - t.ok(first.includes("'") === false) - t.ok(second.includes('"') === false) - t.ok(third.includes('`') === false) - console.dir([ first, second, third ], { depth: null }) + t.assert.ok(first.includes("'") === false) + t.assert.ok(second.includes('"') === false) + t.assert.ok(third.includes('`') === false) + // console.dir([ first, second, third ], { depth: null }) }) test('js compilation does not strip heterogenous quotes in a string literal', t => { @@ -319,10 +319,10 @@ hello \`"howdy"\` let tokens = parse.lexer(arcfile) let ast = parse.parser(tokens) let js = parse.compiler(ast, 'js') - t.equal(js.bundles[0][1], '\`howdy\`', 'Single quoted string literal returned string with escaped backticks') - t.equal(js.bundles[1][1], '"howdy"', 'Single quoted string literal returned string with escaped double quotes') - t.equal(js.bundles[2][1], '\`howdy\`', 'Double quoted string literal returned string with escaped backticks') - t.equal(js.bundles[3][1], "'howdy'", 'Double quoted string literal returned string with escaped single quotes') - t.equal(js.bundles[4][1], `'howdy'`, 'Backtick quoted string literal returned string with escaped single quotes') - t.equal(js.bundles[5][1], `"howdy"`, 'Backtick quoted string literal returned string with escaped double quotes') + t.assert.equal(js.bundles[0][1], '\`howdy\`', 'Single quoted string literal returned string with escaped backticks') + t.assert.equal(js.bundles[1][1], '"howdy"', 'Single quoted string literal returned string with escaped double quotes') + t.assert.equal(js.bundles[2][1], '\`howdy\`', 'Double quoted string literal returned string with escaped backticks') + t.assert.equal(js.bundles[3][1], "'howdy'", 'Double quoted string literal returned string with escaped single quotes') + t.assert.equal(js.bundles[4][1], `'howdy'`, 'Backtick quoted string literal returned string with escaped single quotes') + t.assert.equal(js.bundles[5][1], `"howdy"`, 'Backtick quoted string literal returned string with escaped double quotes') }) diff --git a/test/05-parser-test.js b/test/05-parser-test.js index faf79d0..54730b7 100644 --- a/test/05-parser-test.js +++ b/test/05-parser-test.js @@ -1,12 +1,12 @@ -let test = require('tape') +let { test } = require('node:test') let lex = require('../src/lexer') let parse = require('../src/parser') let compile = require('../src/compiler') test('lex, parse and compile', t => { t.plan(3) - t.ok(lex, 'lex') - t.ok(parse, 'parse') + t.assert.ok(lex, 'lex') + t.assert.ok(parse, 'parse') let arcfile = ` # comment with spaces @pragma1 @@ -19,7 +19,7 @@ one 2 false` let tokens = lex(arcfile) let ast = parse(tokens) let arc = compile(ast) - t.ok(Array.isArray(arc.pragma1), 'parsed') + t.assert.ok(Array.isArray(arc.pragma1), 'parsed') }) test('vertical vector', t => { @@ -34,7 +34,7 @@ vert let tokens = lex(arcfile) let ast = parse(tokens) let arc = compile(ast) - t.ok(arc.simple[0].vert.length === 3) + t.assert.ok(arc.simple[0].vert.length === 3) }) test('anon vertical', t => { @@ -48,9 +48,9 @@ true false let tokens = lex(arcfile) let ast = parse(tokens) let arc = compile(ast) - t.ok(arc.anon[0].length === 3) - t.ok(arc.anon[1].length === 4) - t.ok(arc.anon[2].length === 2) + t.assert.ok(arc.anon[0].length === 3) + t.assert.ok(arc.anon[1].length === 4) + t.assert.ok(arc.anon[2].length === 2) }) test('map', t => { @@ -64,12 +64,12 @@ orca let tokens = lex(arcfile) let ast = parse(tokens) let arc = compile(ast) - t.ok(Array.isArray(arc.whales) && arc.whales.length === 1, 'arc.whales') - t.ok(arc.whales[0].orca, 'arc.whales[0].orca') - t.ok(arc.whales[0].orca.name, 'fin') - t.ok(arc.whales[0].orca.awesome, 'awesome') - t.ok(Array.isArray(arc.whales[0].orca.foods), 'yum') - console.dir({ arc }, { depth: null }) + t.assert.ok(Array.isArray(arc.whales) && arc.whales.length === 1, 'arc.whales') + t.assert.ok(arc.whales[0].orca, 'arc.whales[0].orca') + t.assert.ok(arc.whales[0].orca.name, 'fin') + t.assert.ok(arc.whales[0].orca.awesome, 'awesome') + t.assert.ok(Array.isArray(arc.whales[0].orca.foods), 'yum') + // console.dir({ arc }, { depth: null }) }) test('map with vector', t => { @@ -88,12 +88,12 @@ cats let tokens = lex(arcfile) let ast = parse(tokens) let arc = compile(ast) - t.ok(Array.isArray(arc.animals)) - t.ok(arc.animals[0].cats) - t.ok(arc.animals[0].cats.house.length === 2) - t.ok(arc.animals[0].cats.jungle.length === 2) - t.ok(arc.animals[0].cats.ocean === 'sealion') - console.dir({ arc }, { depth: null }) + t.assert.ok(Array.isArray(arc.animals)) + t.assert.ok(arc.animals[0].cats) + t.assert.ok(arc.animals[0].cats.house.length === 2) + t.assert.ok(arc.animals[0].cats.jungle.length === 2) + t.assert.ok(arc.animals[0].cats.ocean === 'sealion') + // console.dir({ arc }, { depth: null }) }) test('funky trailing whitespace in complex formats', t => { @@ -112,14 +112,14 @@ vert two three ` - t.doesNotThrow(run, 'Did not throw') + t.assert.doesNotThrow(run, 'Did not throw') arcfile = ` @whales orca name fin ` - t.doesNotThrow(run, 'Did not throw') + t.assert.doesNotThrow(run, 'Did not throw') arcfile = ` @animals @@ -133,7 +133,7 @@ cats ocean sealion ` - t.doesNotThrow(run, 'Did not throw') + t.assert.doesNotThrow(run, 'Did not throw') }) test('AST quote information is retained', t => { @@ -142,6 +142,6 @@ test('AST quote information is retained', t => { let tokens = lex(arcfile) let ast = parse(tokens) let str = ast.values[0].values.find(v => v.type === 'string' && v.quote && v.quote === '"') - t.ok(str, 'found the quote on a string value') - console.dir(str, { depth: null }) + t.assert.ok(str, 'found the quote on a string value') + // console.dir(str, { depth: null }) }) diff --git a/test/06-compat-test.js b/test/06-compat-test.js index 083e121..e880ecc 100644 --- a/test/06-compat-test.js +++ b/test/06-compat-test.js @@ -1,4 +1,4 @@ -let test = require('tape') +let test = require('node:test') let { readFileSync } = require('fs') let parse = require('../') let expected = require('./mock/arc.json') @@ -7,24 +7,24 @@ test('Should parse JSON with core Arc pragmas represented as arrays', t => { t.plan(1) let mock = readFileSync('./test/mock/arc-item-arrays.json').toString() let parsed = parse.json(mock) - console.dir(parsed, { depth: null }) - t.same(parsed, expected, 'parsed json') + // console.dir(parsed, { depth: null }) + t.assert.deepEqual(parsed, expected, 'parsed json') }) test('Should parse JSON with core Arc pragmas represented as objects', t => { t.plan(1) let mock = readFileSync('./test/mock/arc-item-objects.json').toString() let parsed = parse.json(mock) - console.dir(parsed, { depth: null }) - t.same(parsed, expected, 'parsed json') + // console.dir(parsed, { depth: null }) + t.assert.deepEqual(parsed, expected, 'parsed json') }) test('Should parse YAML (by way of JSON)', t => { t.plan(1) let mock = readFileSync('./test/mock/arc.yaml').toString() let parsed = parse.yaml(mock) - console.dir(parsed, { depth: null }) - t.same(parsed, expected, 'parsed json') + // console.dir(parsed, { depth: null }) + t.assert.deepEqual(parsed, expected, 'parsed json') }) test('Should serialize JSON to app.arc', t => { @@ -38,12 +38,12 @@ test('Should serialize JSON to app.arc', t => { mock = readFileSync('./test/mock/arc-item-arrays.json').toString() parsed = parse.json(mock) result = parse.stringify(parsed) - console.dir(result, { depth: null }) - t.same(result, expectedArc, 'parsed json') + // console.dir(result, { depth: null }) + t.assert.deepEqual(result, expectedArc, 'parsed json') mock = readFileSync('./test/mock/arc-item-objects.json').toString() parsed = parse.json(mock) result = parse.stringify(parsed) - console.dir(result, { depth: null }) - t.same(result, expectedArc, 'parsed json') + // console.dir(result, { depth: null }) + t.assert.deepEqual(result, expectedArc, 'parsed json') }) diff --git a/test/07-stringify-test.js b/test/07-stringify-test.js index 21cf80d..0403ece 100644 --- a/test/07-stringify-test.js +++ b/test/07-stringify-test.js @@ -1,4 +1,4 @@ -const test = require('tape') +const test = require('node:test') const fs = require('fs') const parse = require('../') @@ -8,5 +8,5 @@ test('parse.stringify', t => { let parsed = parse(mock) let string = JSON.stringify(parsed) let actual = JSON.stringify(parse(parse.stringify(parsed))) - t.equal(string, actual, 'Stringified parsed arc file 🙌') + t.assert.equal(string, actual, 'Stringified parsed arc file 🙌') }) diff --git a/test/08-values-test.js b/test/08-values-test.js index 6af7b0d..e2df3ad 100644 --- a/test/08-values-test.js +++ b/test/08-values-test.js @@ -1,4 +1,4 @@ -let test = require('tape') +let { test } = require('node:test') let parse = require('../') let isVector = require('../src/parser/_is-vector') @@ -11,11 +11,11 @@ test('parse quoted string', t => { 'yet another string w spaces' ` let output = parse(arcfile) - t.ok(output, 'parsed') - t.ok(Array.isArray(output.mystr), 'output.mystr') - t.ok(output.mystr[0] === 'string with spaces', 'greedy double quote') - t.ok(output.mystr[1] === 'string also with spaces', 'greedy backtick') - t.ok(output.mystr[2] === 'yet another string w spaces', 'greedy single quote') + t.assert.ok(output, 'parsed') + t.assert.ok(Array.isArray(output.mystr), 'output.mystr') + t.assert.ok(output.mystr[0] === 'string with spaces', 'greedy double quote') + t.assert.ok(output.mystr[1] === 'string also with spaces', 'greedy backtick') + t.assert.ok(output.mystr[2] === 'yet another string w spaces', 'greedy single quote') }) test('parse quoted string with illegal chars', t => { @@ -26,11 +26,11 @@ test('parse quoted string with illegal chars', t => { and otherwise '#illegal' b@brian.io" ` - t.ok(arcfile, '.arc') - console.log(arcfile) + t.assert.ok(arcfile, '.arc') + // console.log(arcfile) let output = parse(arcfile) - t.ok(output, 'parsed result') - console.log(output) + t.assert.ok(output, 'parsed result') + // console.log(output) }) test('string[]', t => { @@ -39,11 +39,11 @@ test('string[]', t => { @mystr "string with spaces " and another true 2 ` - t.ok(arcfile, '.arc') - console.log(arcfile) + t.assert.ok(arcfile, '.arc') + // console.log(arcfile) let output = parse(arcfile) - t.ok(output, 'parsed result') - console.log(output) + t.assert.ok(output, 'parsed result') + // console.log(output) }) test('obj str', t => { @@ -53,11 +53,11 @@ test('obj str', t => { myobj mykey "string with spaces " and another true 2 ` - t.ok(arcfile, '.arc') - console.log(arcfile) + t.assert.ok(arcfile, '.arc') + // console.log(arcfile) let output = parse(arcfile) - t.ok(output, 'parsed result') - console.log(JSON.stringify(output, null, 2)) + t.assert.ok(output, 'parsed result') + // console.log(JSON.stringify(output, null, 2)) }) test('floats and hashes; plus signals string; quoted values', t => { @@ -77,11 +77,11 @@ asdf-787 @email "b@brian.io" ` - t.ok(arcfile, '.arc') - console.log(arcfile) + t.assert.ok(arcfile, '.arc') + // console.log(arcfile) let output = parse(arcfile) - t.ok(output, 'parsed result') - console.log(JSON.stringify(output, null, 2)) + t.assert.ok(output, 'parsed result') + // console.log(JSON.stringify(output, null, 2)) }) test('isVec', t => { @@ -99,11 +99,11 @@ nested obj "invoice-#333" value here wut wut` - t.ok(true) + t.assert.ok(true) let tokens = parse.lexer(arcfile) let slice = tokens.slice(2, tokens.length) - let isV = isVector(slice) - console.dir({ slice, isV }, { depth: null }) + /* let isV = */isVector(slice) + // console.dir({ slice, isV }, { depth: null }) }) test('nested floats and hashes; plus signals string; quoted values', t => { @@ -121,16 +121,16 @@ nested obj "invoice-#333" value here ` - t.ok(arcfile, '.arc') - console.log(arcfile) + t.assert.ok(arcfile, '.arc') + // console.log(arcfile) let tokens = parse.lexer(arcfile) let ast = parse.parser(tokens) let arc = parse.compiler(ast) - t.ok(arc) - t.ok(Array.isArray(arc.values), 'values pragma exists') - t.ok(Array.isArray(arc.values[0].nested), 'nested array exists') - t.ok(Number.isInteger(arc.values[0].nested[0]) === false, 'is a float') - t.ok(Math.sign(arc.values[0].nested[1]) === -1, 'is a negative value') - t.ok(Object.keys(arc.values[1].obj)[0] === 'invoice-#333', 'obj key exists') - t.ok(Array.isArray(arc.values[1].obj['invoice-#333']), 'obj key has expected value') + t.assert.ok(arc) + t.assert.ok(Array.isArray(arc.values), 'values pragma exists') + t.assert.ok(Array.isArray(arc.values[0].nested), 'nested array exists') + t.assert.ok(Number.isInteger(arc.values[0].nested[0]) === false, 'is a float') + t.assert.ok(Math.sign(arc.values[0].nested[1]) === -1, 'is a negative value') + t.assert.ok(Object.keys(arc.values[1].obj)[0] === 'invoice-#333', 'obj key exists') + t.assert.ok(Array.isArray(arc.values[1].obj['invoice-#333']), 'obj key has expected value') }) diff --git a/test/09-architect-test.js b/test/09-architect-test.js index b846928..6732a57 100644 --- a/test/09-architect-test.js +++ b/test/09-architect-test.js @@ -1,4 +1,4 @@ -let test = require('tape') +let { test } = require('node:test') let fs = require('fs') let path = require('path') let parse = require('../') @@ -10,41 +10,38 @@ test('test base mock file', t => { let tokens = parse.lexer(mock) let ast = parse.parser(tokens) let parsed = parse.compiler(ast) - t.ok(parsed, 'parsed mock') + t.assert.ok(parsed, 'parsed mock') // eslint-disable-next-line - t.ok(parsed.hasOwnProperty('attr'), 'has attr') - t.ok(Array.isArray(parsed.attr), 'attr is array') - t.ok(parsed.attr[0] === 'single', "1st member is string 'single'") - t.ok(parsed.attr[1] === false, '2nd member is a false') - t.ok(parsed.attr[2] === 1, '3rd member is a 1') - t.ok(parsed.attr[3] === -1, '4th member is a 1') - t.ok(Array.isArray(parsed.attr[4]), '5th member is an array with two members') - t.ok(parsed.attr[4].length === 2, '6th member is a tuple') - t.ok(parsed.attr[5].length === 7, '7th member is a vector of seven members') - t.ok(typeof parsed.attr[6] === 'object' && parsed.attr[6] !== null, '8th member is a plain object') - t.ok(parsed.attr[4].length === 2, '9th member is also a tuple') + t.assert.ok(parsed.hasOwnProperty('attr'), 'has attr') + t.assert.ok(Array.isArray(parsed.attr), 'attr is array') + t.assert.ok(parsed.attr[0] === 'single', "1st member is string 'single'") + t.assert.ok(parsed.attr[1] === false, '2nd member is a false') + t.assert.ok(parsed.attr[2] === 1, '3rd member is a 1') + t.assert.ok(parsed.attr[3] === -1, '4th member is a 1') + t.assert.ok(Array.isArray(parsed.attr[4]), '5th member is an array with two members') + t.assert.ok(parsed.attr[4].length === 2, '6th member is a tuple') + t.assert.ok(parsed.attr[5].length === 7, '7th member is a vector of seven members') + t.assert.ok(typeof parsed.attr[6] === 'object' && parsed.attr[6] !== null, '8th member is a plain object') + t.assert.ok(parsed.attr[4].length === 2, '9th member is also a tuple') }) test('test aws arc by parsing mock-arc', t => { t.plan(1) var mock = fs.readFileSync(path.join(__dirname, 'mock', 'aws.arc')).toString() var parsed = parse(mock) - t.ok(parsed, 'parsed mock') - console.log(JSON.stringify(parsed, null, 2)) + t.assert.ok(parsed, 'parsed mock') + // console.log(JSON.stringify(parsed, null, 2)) }) test('@scheduled', t => { t.plan(1) var mock = fs.readFileSync(path.join(__dirname, 'mock', 'scheduled.arc')).toString() var parsed = parse(mock) - t.ok(parsed, 'read out scheduled') - console.log(parsed) + t.assert.ok(parsed, 'read out scheduled') + // console.log(parsed) }) test('Test full Architect project manifest mock', t => { - let mock = fs.readFileSync(path.join(__dirname, 'mock', 'arc.arc')).toString() - let arc = parse(mock) - t.ok(arc, 'parsed mock') let pragmas = [ 'app', 'aws', @@ -58,6 +55,10 @@ test('Test full Architect project manifest mock', t => { 'tables', 'indexes', ] + t.plan(1 + (pragmas.length * 2)) + let mock = fs.readFileSync(path.join(__dirname, 'mock', 'arc.arc')).toString() + let arc = parse(mock) + t.assert.ok(arc, 'parsed mock') let pragmaConfig = { app: 1, aws: 12, @@ -71,10 +72,9 @@ test('Test full Architect project manifest mock', t => { tables: 2, indexes: 2, } - t.plan(1 + (pragmas.length * 2)) let isArray = i => Array.isArray(i) - pragmas.forEach(pragma => { - t.ok(isArray(arc[pragma]), `${pragma} parsed to array`) - t.equal(arc[pragma].length, pragmaConfig[pragma], `${pragma} has ${arc[pragma].length} items`) - }) + for (const pragma of pragmas) { + t.assert.ok(isArray(arc[pragma]), `${pragma} parsed to array`) + t.assert.equal(arc[pragma].length, pragmaConfig[pragma], `${pragma} has ${arc[pragma].length} items`) + } }) From ce1b4327b12255838b6214169ff7a7f4e3470e73 Mon Sep 17 00:00:00 2001 From: filmaj Date: Sun, 13 Apr 2025 22:50:27 -0400 Subject: [PATCH 3/6] exclude test/ dir from coverage report --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 27f4f2d..cf44af3 100644 --- a/package.json +++ b/package.json @@ -7,8 +7,8 @@ "deno:test": "deno test -A --unstable mod.test.ts", "deno:fmt": "deno fmt mod.ts && deno fmt mod.test.ts", "lint": "eslint . --fix", - "test:unit": "node --test", - "coverage": "node --test --experimental-test-coverage", + "test:unit": "node --test --test-reporter=spec", + "coverage": "npm run test:unit -- --experimental-test-coverage --test-coverage-exclude=test/*.js", "test": "npm run lint && npm run coverage", "rc": "npm version prerelease --preid RC", "build": "rollup -c", From 0f518552e6fe0bbe6bc23cf0b8afc25941f2c1f2 Mon Sep 17 00:00:00 2001 From: filmaj Date: Fri, 18 Apr 2025 08:47:32 -0400 Subject: [PATCH 4/6] ci: provide test runner scripts for node v20 vs. newer versions, which support more specific coverage reporting. --- .github/workflows/build.yml | 10 +++++++++- package.json | 4 +++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d0e5af4..890d3eb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -46,8 +46,16 @@ jobs: - name: Install run: npm install + - name: Test (Node.js <= 20.x) + if: matrix.node-version <= '20.x' + # node 20 doesnt support excluding files from coverage report, and by default includes test files themselves. + run: npm run test:node20 + env: + CI: true + - name: Test - run: npm test + if: matrix.node-version > '20.x' + run: npm test env: CI: true diff --git a/package.json b/package.json index cf44af3..218f694 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,9 @@ "deno:fmt": "deno fmt mod.ts && deno fmt mod.test.ts", "lint": "eslint . --fix", "test:unit": "node --test --test-reporter=spec", - "coverage": "npm run test:unit -- --experimental-test-coverage --test-coverage-exclude=test/*.js", + "coverage:node20": "npm run test:unit -- --experimental-test-coverage", + "coverage": "npm run coverage:node20 -- --test-coverage-exclude=test/*.js", + "test:node20": "npm run lint && npm run coverage:node20", "test": "npm run lint && npm run coverage", "rc": "npm version prerelease --preid RC", "build": "rollup -c", From ad50addeefd59316272b7ecbba7eafc88696002e Mon Sep 17 00:00:00 2001 From: filmaj Date: Sat, 3 May 2025 13:31:35 -0400 Subject: [PATCH 5/6] 8.0.0-RC.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 218f694..e3b2ad7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@architect/parser", - "version": "7.0.1", + "version": "8.0.0-RC.0", "description": "Architect Parser accepts plaintext, JSON, or YAML .arc manifests and returns a plain JavaScript Object", "main": "./src/index.js", "scripts": { From 643a5e15750eeeb6cc848c433a4234982b1dc566 Mon Sep 17 00:00:00 2001 From: filmaj Date: Sat, 10 May 2025 09:34:31 -0400 Subject: [PATCH 6/6] chore: test on node 24, too --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 890d3eb..d43c7f5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -15,7 +15,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - node-version: [ 20.x, 22.x ] + node-version: [ 20.x, 22.x, 24.x ] os: [ windows-latest, ubuntu-latest, macOS-latest ] # Go @@ -62,7 +62,7 @@ jobs: - name: Notify uses: sarisia/actions-status-discord@v1 # Only fire alert once - if: github.ref == 'refs/heads/main' && failure() && matrix.node-version == '22.x' && matrix.os == 'ubuntu-latest' + if: github.ref == 'refs/heads/main' && failure() && matrix.node-version == '24.x' && matrix.os == 'ubuntu-latest' with: webhook: ${{ secrets.DISCORD_WEBHOOK }} title: "build and test"