From 0d042ac5bd0c450b07995801ae3b1cc6f690c785 Mon Sep 17 00:00:00 2001 From: Brian LeRoux Date: Fri, 28 Nov 2025 10:05:24 -0800 Subject: [PATCH 01/12] fix: move to node native test runner --- package.json | 13 +- test/integration/cli-test.js | 83 +++++----- test/unit/cli-test.js | 67 ++++---- test/unit/src/_get-name-test.js | 61 ++++---- test/unit/src/bootstrap/_arc-package-test.js | 143 ++++++++++-------- .../src/write-functions/write-code-test.js | 84 ++++++---- 6 files changed, 249 insertions(+), 202 deletions(-) diff --git a/package.json b/package.json index 0714b70..3f39d9f 100644 --- a/package.json +++ b/package.json @@ -13,9 +13,9 @@ "scripts": { "test": "npm run lint && npm run test:integration && npm run coverage", "test:nolint": "npm run test:integration && npm run coverage", - "test:unit": "cross-env PORT=6666 tape 'test/unit/**/*-test.js' | tap-arc", - "test:integration": "cross-env tape 'test/integration/**/*-test.js' | tap-arc", - "coverage": "nyc --reporter=lcov --reporter=text npm run test:unit", + "test:unit": "node --test 'test/unit/**/*-test.js'", + "test:integration": "node --test 'test/integration/**/*-test.js'", + "coverage": "node --test --experimental-test-coverage 'test/unit/**/*-test.js' 'test/integration/**/*-test.js'", "lint": "eslint . --fix", "rc": "npm version prerelease --preid RC" }, @@ -29,12 +29,7 @@ }, "devDependencies": { "@architect/eslint-config": "~3.0.0", - "cross-env": "~10.0.0", "eslint": "~9.36.0", - "fs-extra": "~11.3.2", - "nyc": "~17.1.0", - "proxyquire": "^2.1.3", - "tap-arc": "^1.2.2", - "tape": "~5.9.0" + "fs-extra": "~11.3.2" } } diff --git a/test/integration/cli-test.js b/test/integration/cli-test.js index f384e88..fab7002 100644 --- a/test/integration/cli-test.js +++ b/test/integration/cli-test.js @@ -1,4 +1,5 @@ -let test = require('tape') +let { describe, it, before, after } = require('node:test') +let assert = require('node:assert/strict') let cli = require('../../src/cli') let { join } = require('path') let fs = require('fs-extra') @@ -8,52 +9,46 @@ let origCwd = process.cwd() let argv = process.argv let args = s => process.argv = [ 'fake-env', 'fake-file', ...s.split(' ') ] -test('integration test setup', async t => { - t.plan(1) - fs.emptyDirSync(tmp) - process.chdir(tmp) - t.pass('integration test environment setup complete') -}) +describe('CLI Integration Tests', () => { + before(async () => { + fs.emptyDirSync(tmp) + process.chdir(tmp) + }) -test('should build the basic templated node runtime project', async t => { - t.plan(2) - fs.emptyDirSync(tmp) - args('--no-install --runtime node.js') - await cli() - t.ok(existsSync(join(tmp, 'src', 'http', 'get-index', 'index.mjs')), 'src/http/get-index/index.mjs created') - t.ok(readFileSync(join(tmp, 'app.arc'), 'utf-8').match(/runtime node/), '"runtime node" present somewhere in manifest') -}) + it('should build the basic templated node runtime project', async () => { + fs.emptyDirSync(tmp) + args('--no-install --runtime node.js') + await cli() + assert.ok(existsSync(join(tmp, 'src', 'http', 'get-index', 'index.mjs')), 'src/http/get-index/index.mjs created') + assert.ok(readFileSync(join(tmp, 'app.arc'), 'utf-8').match(/runtime node/), '"runtime node" present somewhere in manifest') + }) -test('should build the basic templated deno runtime project', async t => { - t.plan(2) - fs.emptyDirSync(tmp) - args('--no-install --runtime deno') - await cli() - t.ok(existsSync(join(tmp, 'src', 'http', 'get-index', 'mod.ts')), 'src/http/get-index/mod.ts created') - t.ok(readFileSync(join(tmp, 'app.arc'), 'utf-8').match(/runtime deno/), '"runtime deno" present somewhere in manifest') -}) + it('should build the basic templated deno runtime project', async () => { + fs.emptyDirSync(tmp) + args('--no-install --runtime deno') + await cli() + assert.ok(existsSync(join(tmp, 'src', 'http', 'get-index', 'mod.ts')), 'src/http/get-index/mod.ts created') + assert.ok(readFileSync(join(tmp, 'app.arc'), 'utf-8').match(/runtime deno/), '"runtime deno" present somewhere in manifest') + }) -test('should build the basic templated python runtime project', async t => { - t.plan(2) - fs.emptyDirSync(tmp) - args('--no-install --runtime python') - await cli() - t.ok(existsSync(join(tmp, 'src', 'http', 'get-index', 'lambda.py')), 'src/http/get-index/lambda.py created') - t.ok(readFileSync(join(tmp, 'app.arc'), 'utf-8').match(/runtime python/), '"runtime python" present somewhere in manifest') -}) + it('should build the basic templated python runtime project', async () => { + fs.emptyDirSync(tmp) + args('--no-install --runtime python') + await cli() + assert.ok(existsSync(join(tmp, 'src', 'http', 'get-index', 'lambda.py')), 'src/http/get-index/lambda.py created') + assert.ok(readFileSync(join(tmp, 'app.arc'), 'utf-8').match(/runtime python/), '"runtime python" present somewhere in manifest') + }) -test('should build the basic templated ruby runtime project', async t => { - t.plan(2) - fs.emptyDirSync(tmp) - args('--no-install --runtime ruby') - await cli() - t.ok(existsSync(join(tmp, 'src', 'http', 'get-index', 'lambda.rb')), 'src/http/get-index/lambda.rb created') - t.ok(readFileSync(join(tmp, 'app.arc'), 'utf-8').match(/runtime ruby/), '"runtime ruby" present somewhere in manifest') -}) + it('should build the basic templated ruby runtime project', async () => { + fs.emptyDirSync(tmp) + args('--no-install --runtime ruby') + await cli() + assert.ok(existsSync(join(tmp, 'src', 'http', 'get-index', 'lambda.rb')), 'src/http/get-index/lambda.rb created') + assert.ok(readFileSync(join(tmp, 'app.arc'), 'utf-8').match(/runtime ruby/), '"runtime ruby" present somewhere in manifest') + }) -test('integration test teardown', t => { - t.plan(1) - process.argv = argv - process.chdir(origCwd) - t.pass('integration test environment setup removed') + after(() => { + process.argv = argv + process.chdir(origCwd) + }) }) diff --git a/test/unit/cli-test.js b/test/unit/cli-test.js index e3b90b7..f97a068 100644 --- a/test/unit/cli-test.js +++ b/test/unit/cli-test.js @@ -1,102 +1,117 @@ -let proxyquire = require('proxyquire') -let test = require('tape') +const { test } = require('node:test') +const assert = require('node:assert') +const Module = require('module') + let createParams -let create = p => createParams = p +const argv = process.argv +const args = s => process.argv = [ 'fake-env', 'fake-file', ...s.split(' ').filter(Boolean) ] let reset = () => { process.argv = argv createParams = undefined } -let cli = proxyquire('../../src/cli', { - '.': create, -}) -let argv = process.argv -let args = s => process.argv = [ 'fake-env', 'fake-file', ...s.split(' ').filter(Boolean) ] -test('CLI flags and params', async t => { - t.plan(15) +// Mock the create module by intercepting require +const originalRequire = Module.prototype.require +let cli + +test('CLI flags and params', async () => { + // Setup: Mock the create module + Module.prototype.require = function (id) { + if (id === '.' || id === './index.js') { + return (p) => { createParams = p } + } + return originalRequire.apply(this, arguments) + } + + // Clear require cache and reload cli + delete require.cache[require.resolve('../../src/cli')] + cli = require('../../src/cli') + + // Restore require after loading + Module.prototype.require = originalRequire + args('') await cli() Object.entries(createParams).forEach(([ k, v ]) => { if (k === 'update' || k === 'standalone') return - if (v !== undefined) t.fail(`${k} should be undefined`) + if (v !== undefined) assert.fail(`${k} should be undefined`) }) - t.pass('By default the CLI passes no controlling params') reset() // Name let name = 'hi' args(`--name ${name}`) await cli() - t.equal(createParams.name, name, 'Got name from CLI --name') + assert.equal(createParams.name, name, 'Got name from CLI --name') reset() args(`-n ${name}`) await cli() - t.equal(createParams.name, name, 'Got name from CLI -n') + assert.equal(createParams.name, name, 'Got name from CLI -n') reset() // Install / no-install await cli({ install: true }) - t.not(createParams.install, 'Got install: true from module params') + assert.ok(createParams.install, 'Got install: true from module params') reset() await cli({ install: false }) - t.notOk(createParams.install, 'Got install: false from module params') + assert.ok(!createParams.install, 'Got install: false from module params') reset() args(`--noinstall`) await cli() - t.notOk(createParams.install, 'Got install: false from CLI --noinstall') + assert.ok(!createParams.install, 'Got install: false from CLI --noinstall') reset() args(`--no-install`) await cli() - t.notOk(createParams.install, 'Got install: false from CLI --no-install') + assert.ok(!createParams.install, 'Got install: false from CLI --no-install') reset() // Runtime let runtime = 'python' args(`--runtime ${runtime}`) await cli() - t.equal(createParams.runtime, runtime, 'Got runtime from CLI --runtime') + assert.equal(createParams.runtime, runtime, 'Got runtime from CLI --runtime') reset() args(`-r ${runtime}`) await cli() - t.equal(createParams.runtime, runtime, 'Got runtime from CLI -r') + assert.equal(createParams.runtime, runtime, 'Got runtime from CLI -r') reset() // Standalone await cli({ standalone: true }) - t.ok(createParams.standalone, 'Got standalone from module params') + assert.ok(createParams.standalone, 'Got standalone from module params') reset() // Plugin args('--plugin') await cli() - t.ok(createParams.plugin, 'Got plugin from CLI') + assert.ok(createParams.plugin, 'Got plugin from CLI') reset() // Verbose args('--verbose') await cli() - t.ok(createParams.verbose, 'Got verbose from CLI') + assert.ok(createParams.verbose, 'Got verbose from CLI') reset() args('-v') await cli() - t.ok(createParams.verbose, 'Got verbose from CLI') + assert.ok(createParams.verbose, 'Got verbose from CLI') reset() // Folder let folder = './foo' args(folder) await cli() - t.equal(createParams.folder, folder, 'Got folder from CLI') + assert.equal(createParams.folder, folder, 'Got folder from CLI') reset() args(`create ${folder}`) // Ignore create await cli() - t.equal(createParams.folder, folder, `Got folder from CLI, ignored 'create'`) + assert.equal(createParams.folder, folder, `Got folder from CLI, ignored 'create'`) reset() }) diff --git a/test/unit/src/_get-name-test.js b/test/unit/src/_get-name-test.js index a4591e6..50fe6b5 100644 --- a/test/unit/src/_get-name-test.js +++ b/test/unit/src/_get-name-test.js @@ -1,4 +1,5 @@ -let test = require('tape') +let { test } = require('node:test') +let assert = require('node:assert/strict') let { join, sep } = require('path') let os = require('os') let cwd = process.cwd() @@ -7,78 +8,74 @@ let getName = require(sut) let defaultName = 'create' let s = str => str[0].replace(/\//g, sep) -test('Set up env', t => { - t.plan(1) - t.ok(getName, 'Loaded getName') +test('Set up env', () => { + assert.ok(getName, 'Loaded getName') }) -test('No name/folder specified', t => { - t.plan(2) +test('No name/folder specified', () => { let result = getName({ cwd }) - t.equal(result.name, defaultName, 'Got default name of current directory') - t.equal(result.folder, cwd, 'Got default folder of current directory') + assert.equal(result.name, defaultName, 'Got default name of current directory') + assert.equal(result.folder, cwd, 'Got default folder of current directory') }) -test('Name specified', t => { - t.plan(2) +test('Name specified', () => { let name = 'hi' let result = getName({ cwd, name }) - t.equal(result.name, name, 'Name passed through') - t.equal(result.folder, cwd, 'Got default folder of current directory') + assert.equal(result.name, name, 'Name passed through') + assert.equal(result.folder, cwd, 'Got default folder of current directory') }) -test('Folder specified', t => { - t.plan(18) +test('Folder specified', () => { let folder let result folder = cwd result = getName({ cwd, folder }) - t.equal(result.name, defaultName, 'Got default name of current directory') - t.equal(result.folder, folder, `Got specified folder: ${folder}`) + assert.equal(result.name, defaultName, 'Got default name of current directory') + assert.equal(result.folder, folder, `Got specified folder: ${folder}`) folder = s`foo` result = getName({ cwd, folder }) - t.equal(result.name, 'foo', 'Got default name of current directory') - t.equal(result.folder, join(cwd, 'foo'), `Got specified folder: ${folder}`) + assert.equal(result.name, 'foo', 'Got default name of current directory') + assert.equal(result.folder, join(cwd, 'foo'), `Got specified folder: ${folder}`) folder = s`./foo` result = getName({ cwd, folder }) - t.equal(result.name, 'foo', 'Got default name of current directory') - t.equal(result.folder, join(cwd, 'foo'), `Got specified folder: ${folder}`) + assert.equal(result.name, 'foo', 'Got default name of current directory') + assert.equal(result.folder, join(cwd, 'foo'), `Got specified folder: ${folder}`) folder = s`../foo` result = getName({ cwd, folder }) - t.equal(result.name, 'foo', 'Got default name of current directory') - t.equal(result.folder, join(cwd, '..', 'foo'), `Got specified folder: ${folder}`) + assert.equal(result.name, 'foo', 'Got default name of current directory') + assert.equal(result.folder, join(cwd, '..', 'foo'), `Got specified folder: ${folder}`) folder = s`../../foo` result = getName({ cwd, folder }) - t.equal(result.name, 'foo', 'Got default name of current directory') - t.equal(result.folder, join(cwd, '..', '..', 'foo'), `Got specified folder: ${folder}`) + assert.equal(result.name, 'foo', 'Got default name of current directory') + assert.equal(result.folder, join(cwd, '..', '..', 'foo'), `Got specified folder: ${folder}`) folder = s`/foo` result = getName({ cwd, folder }) let root = os.platform == 'win32' ? process.cwd().split(sep)[0] : sep - t.equal(result.name, 'foo', 'Got default name of current directory') - t.equal(result.folder, join(root, 'foo'), `Got specified folder: ${folder}`) + assert.equal(result.name, 'foo', 'Got default name of current directory') + assert.equal(result.folder, join(root, 'foo'), `Got specified folder: ${folder}`) folder = s`./` result = getName({ cwd, folder }) - t.equal(result.name, defaultName, 'Got default name of current directory') - t.equal(result.folder, cwd, `Got specified folder: ${folder}`) + assert.equal(result.name, defaultName, 'Got default name of current directory') + assert.equal(result.folder, cwd, `Got specified folder: ${folder}`) let path let pop = p => p.split(sep).reverse().shift() folder = s`../` path = join(cwd, '..') result = getName({ cwd, folder }) - t.equal(result.name, pop(path), `Got name from directory: ${result.name}`) - t.equal(result.folder, path, `Got specified folder: ${folder}`) + assert.equal(result.name, pop(path), `Got name from directory: ${result.name}`) + assert.equal(result.folder, path, `Got specified folder: ${folder}`) folder = s`../../` path = join(cwd, '..', '..') result = getName({ cwd, folder }) - t.equal(result.name, pop(path), `Got name from directory: ${result.name}`) - t.equal(result.folder, path, `Got specified folder: ${folder}`) + assert.equal(result.name, pop(path), `Got name from directory: ${result.name}`) + assert.equal(result.folder, path, `Got specified folder: ${folder}`) }) diff --git a/test/unit/src/bootstrap/_arc-package-test.js b/test/unit/src/bootstrap/_arc-package-test.js index abb01d1..a612435 100644 --- a/test/unit/src/bootstrap/_arc-package-test.js +++ b/test/unit/src/bootstrap/_arc-package-test.js @@ -1,6 +1,7 @@ -let test = require('tape') +let { describe, it, beforeEach, afterEach } = require('node:test') +let assert = require('node:assert/strict') let { join } = require('path') -let proxyquire = require('proxyquire') +let Module = require('module') let exists = false let destination @@ -9,71 +10,89 @@ let arcAsDep = { dependencies: { '@architect/architect': 'latest' } } let arcAsDevDep = { devDependencies: { '@architect/architect': 'latest' } } let pkg = arcAsDep -let fsStub = { - existsSync: () => exists, - readFileSync: () => JSON.stringify(pkg), - writeFileSync: (dest, data) => { - destination = dest - written = data - }, - '@noCallThru': false, -} -let arcPackage = proxyquire('../../../../src/bootstrap/_arc-package', { - fs: fsStub, -}) let foo = 'foo' let name = foo let folder = __dirname let argv = process.argv -let reset = () => { - destination = '' - written = '' - process.argv = argv -} - -test('Set up env', t => { - t.plan(1) - t.ok(arcPackage, 'Loaded getName') -}) -test('Package writer bails when Architect is called from a global install', t => { - t.plan(2) - process.argv = [ '/usr/local/bin/node', '/usr/local/bin/arc', 'create' ] - let result = arcPackage({}) - t.notOk(result, 'Invocation from global install should opt out of Arc installation') - reset() - - process.argv = [ '/usr/local/bin/node', '/usr/local/bin/arc', 'init' ] - result = arcPackage({}) - t.notOk(result, 'Invocation from global install should opt out of Arc installation') - reset() -}) +// Store original require +let originalRequire = Module.prototype.require -test('Package writer writes a package file when none exists', t => { - t.plan(3) - process.argv = [] - let result = arcPackage({ name, folder }) - t.ok(result, 'Missing package file found should opt into Arc installation') - t.equal(destination, join(__dirname, 'package.json'), 'Wrote package.json to specified folder') - t.equal(JSON.parse(written)['name'], foo, 'package.json uses specified app name') - reset() -}) +describe('_arc-package', () => { + let arcPackage + + beforeEach(() => { + // Reset state + destination = '' + written = '' + exists = false + pkg = arcAsDep + process.argv = argv + + // Mock fs module + Module.prototype.require = function (id) { + if (id === 'fs') { + return { + existsSync: () => exists, + readFileSync: () => Buffer.from(JSON.stringify(pkg)), + writeFileSync: (dest, data) => { + destination = dest + written = data + }, + } + } + return originalRequire.apply(this, arguments) + } + + // Clear module cache and require the module + delete require.cache[require.resolve('../../../../src/bootstrap/_arc-package')] + arcPackage = require('../../../../src/bootstrap/_arc-package') + }) + + afterEach(() => { + // Restore original require + Module.prototype.require = originalRequire + + // Reset state + exists = false + pkg = arcAsDep + process.argv = argv + }) + + it('should load the module', () => { + assert.ok(arcPackage, 'Loaded arcPackage') + }) + + it('should bail when Architect is called from a global install', () => { + process.argv = [ '/usr/local/bin/node', '/usr/local/bin/arc', 'create' ] + let result = arcPackage({}) + assert.ok(!result, 'Invocation from global install should opt out of Arc installation') + + process.argv = [ '/usr/local/bin/node', '/usr/local/bin/arc', 'init' ] + result = arcPackage({}) + assert.ok(!result, 'Invocation from global install should opt out of Arc installation') + }) + + it('should write a package file when none exists', () => { + process.argv = [] + let result = arcPackage({ name, folder }) + assert.ok(result, 'Missing package file found should opt into Arc installation') + assert.equal(destination, join(__dirname, 'package.json'), 'Wrote package.json to specified folder') + assert.equal(JSON.parse(written)['name'], foo, 'package.json uses specified app name') + }) + + it('should determine whether to install Arc based on an existing package.json', () => { + process.argv = [] + exists = true + let result = arcPackage({ name, folder }) + assert.ok(!result, 'Found package file with Arc as dep should opt out of Arc installation') + + pkg = arcAsDevDep + result = arcPackage({ name, folder }) + assert.ok(!result, 'Found package file with Arc as dev dep should opt out of Arc installation') -test(`Package writer determines whether to install Arc based on an existing package.json`, t => { - t.plan(3) - process.argv = [] - exists = true - let result = arcPackage({ name, folder }) - t.notOk(result, 'Found package file with Arc as dep should opt out of Arc installation') - reset() - - pkg = arcAsDevDep - result = arcPackage({ name, folder }) - t.notOk(result, 'Found package file with Arc as dev dep should opt out of Arc installation') - reset() - - pkg = {} - result = arcPackage({ name, folder }) - t.ok(result, 'Found package file with no Arc installed, so opt into Arc installation') - reset() + pkg = {} + result = arcPackage({ name, folder }) + assert.ok(result, 'Found package file with no Arc installed, so opt into Arc installation') + }) }) diff --git a/test/unit/src/write-functions/write-code-test.js b/test/unit/src/write-functions/write-code-test.js index c0aa729..a6643cd 100644 --- a/test/unit/src/write-functions/write-code-test.js +++ b/test/unit/src/write-functions/write-code-test.js @@ -1,18 +1,12 @@ -let { join } = require('path') -let proxyquire = require('proxyquire') +let { describe, it, beforeEach, afterEach } = require('node:test') +let assert = require('node:assert/strict') +let Module = require('module') + let destination let written -let fsStub = { - writeFileSync: (dest, data) => { - destination = dest - written = data - }, -} -let sut = join(process.cwd(), 'src', 'write-functions', 'write-code') -let writeCode = proxyquire(sut, { - fs: fsStub, -}) -let test = require('tape') + +// Store original require +let originalRequire = Module.prototype.require let inventory = { inv: { @@ -21,21 +15,53 @@ let inventory = { }, } -test('Set up env', t => { - t.plan(1) - t.ok(writeCode, 'Loaded writeCode') -}) +describe('write-code', () => { + let writeCode + + beforeEach(() => { + // Reset state + destination = '' + written = '' + + // Mock fs module + Module.prototype.require = function (id) { + if (id === 'fs') { + return { + existsSync: originalRequire.apply(this, [ 'fs' ]).existsSync, + mkdirSync: originalRequire.apply(this, [ 'fs' ]).mkdirSync, + writeFileSync: (dest, data) => { + destination = dest + written = data + }, + } + } + return originalRequire.apply(this, arguments) + } + + // Clear module cache and require the module + delete require.cache[require.resolve('../../../../src/write-functions/write-code')] + writeCode = require('../../../../src/write-functions/write-code') + }) + + afterEach(() => { + // Restore original require + Module.prototype.require = originalRequire + }) + + it('should load the module', () => { + assert.ok(writeCode, 'Loaded writeCode') + }) -test('Should write template body if no body provided via argument', t => { - t.plan(2) - writeCode({ - handlerFile: 'src/http/get-catchall/index.js', - config: { - runtime: 'nodejs14.x', - }, - handlerModuleSystem: 'cjs', - pragma: 'http', - }, inventory) - t.equal(destination, 'src/http/get-catchall/index.js', 'Correct file location to be written to') - t.match(written, /async function http/, 'Correct argument-provided content written') + it('should write template body if no body provided via argument', async () => { + await writeCode({ + handlerFile: 'src/http/get-catchall/index.js', + config: { + runtime: 'nodejs14.x', + }, + handlerModuleSystem: 'cjs', + pragma: 'http', + }, inventory) + assert.equal(destination, 'src/http/get-catchall/index.js', 'Correct file location to be written to') + assert.match(written, /async function http/, 'Correct argument-provided content written') + }) }) From 7d3950c7b524721f53d6911ac600dc3167c200af Mon Sep 17 00:00:00 2001 From: Brian LeRoux Date: Fri, 28 Nov 2025 10:14:36 -0800 Subject: [PATCH 02/12] fix: remove usage of fs-extra --- package.json | 3 +-- test/integration/cli-test.js | 30 +++++++++++++++++++++++------- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 3f39d9f..620bae6 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,6 @@ }, "devDependencies": { "@architect/eslint-config": "~3.0.0", - "eslint": "~9.36.0", - "fs-extra": "~11.3.2" + "eslint": "~9.36.0" } } diff --git a/test/integration/cli-test.js b/test/integration/cli-test.js index fab7002..413a892 100644 --- a/test/integration/cli-test.js +++ b/test/integration/cli-test.js @@ -2,21 +2,31 @@ let { describe, it, before, after } = require('node:test') let assert = require('node:assert/strict') let cli = require('../../src/cli') let { join } = require('path') -let fs = require('fs-extra') -let { readFileSync, existsSync } = require('fs') +let { readFileSync, existsSync, rmSync, mkdirSync } = require('fs') let tmp = join(__dirname, '..', 'tmp') let origCwd = process.cwd() let argv = process.argv let args = s => process.argv = [ 'fake-env', 'fake-file', ...s.split(' ') ] +// Helper to empty a directory (replaces fs-extra's emptyDirSync) +function emptyDirSync (dir) { + if (existsSync(dir)) { + rmSync(dir, { recursive: true, force: true }) + } + mkdirSync(dir, { recursive: true }) +} + describe('CLI Integration Tests', () => { before(async () => { - fs.emptyDirSync(tmp) + emptyDirSync(tmp) process.chdir(tmp) }) it('should build the basic templated node runtime project', async () => { - fs.emptyDirSync(tmp) + // Change back to original dir before emptying tmp + process.chdir(origCwd) + emptyDirSync(tmp) + process.chdir(tmp) args('--no-install --runtime node.js') await cli() assert.ok(existsSync(join(tmp, 'src', 'http', 'get-index', 'index.mjs')), 'src/http/get-index/index.mjs created') @@ -24,7 +34,9 @@ describe('CLI Integration Tests', () => { }) it('should build the basic templated deno runtime project', async () => { - fs.emptyDirSync(tmp) + process.chdir(origCwd) + emptyDirSync(tmp) + process.chdir(tmp) args('--no-install --runtime deno') await cli() assert.ok(existsSync(join(tmp, 'src', 'http', 'get-index', 'mod.ts')), 'src/http/get-index/mod.ts created') @@ -32,7 +44,9 @@ describe('CLI Integration Tests', () => { }) it('should build the basic templated python runtime project', async () => { - fs.emptyDirSync(tmp) + process.chdir(origCwd) + emptyDirSync(tmp) + process.chdir(tmp) args('--no-install --runtime python') await cli() assert.ok(existsSync(join(tmp, 'src', 'http', 'get-index', 'lambda.py')), 'src/http/get-index/lambda.py created') @@ -40,7 +54,9 @@ describe('CLI Integration Tests', () => { }) it('should build the basic templated ruby runtime project', async () => { - fs.emptyDirSync(tmp) + process.chdir(origCwd) + emptyDirSync(tmp) + process.chdir(tmp) args('--no-install --runtime ruby') await cli() assert.ok(existsSync(join(tmp, 'src', 'http', 'get-index', 'lambda.rb')), 'src/http/get-index/lambda.rb created') From 4638b94a600086cfaeab9df1a7444258db7fe685 Mon Sep 17 00:00:00 2001 From: Brian LeRoux Date: Fri, 28 Nov 2025 10:17:33 -0800 Subject: [PATCH 03/12] fix: failing tests due to chdir confusing the test runner --- test/integration/cli-test.js | 76 ++++++++++++++++++++++-------------- 1 file changed, 46 insertions(+), 30 deletions(-) diff --git a/test/integration/cli-test.js b/test/integration/cli-test.js index 413a892..b663501 100644 --- a/test/integration/cli-test.js +++ b/test/integration/cli-test.js @@ -1,9 +1,9 @@ -let { describe, it, before, after } = require('node:test') +let { describe, it, before, after, beforeEach } = require('node:test') let assert = require('node:assert/strict') let cli = require('../../src/cli') -let { join } = require('path') +let { join, resolve } = require('path') let { readFileSync, existsSync, rmSync, mkdirSync } = require('fs') -let tmp = join(__dirname, '..', 'tmp') +let tmp = resolve(__dirname, '..', 'tmp') let origCwd = process.cwd() let argv = process.argv let args = s => process.argv = [ 'fake-env', 'fake-file', ...s.split(' ') ] @@ -17,50 +17,66 @@ function emptyDirSync (dir) { } describe('CLI Integration Tests', () => { - before(async () => { + before(() => { + // Ensure tmp directory exists emptyDirSync(tmp) - process.chdir(tmp) }) - it('should build the basic templated node runtime project', async () => { - // Change back to original dir before emptying tmp - process.chdir(origCwd) + beforeEach(() => { + // Clean tmp directory before each test but stay in original directory emptyDirSync(tmp) + }) + + it('should build the basic templated node runtime project', async () => { process.chdir(tmp) - args('--no-install --runtime node.js') - await cli() - assert.ok(existsSync(join(tmp, 'src', 'http', 'get-index', 'index.mjs')), 'src/http/get-index/index.mjs created') - assert.ok(readFileSync(join(tmp, 'app.arc'), 'utf-8').match(/runtime node/), '"runtime node" present somewhere in manifest') + try { + args('--no-install --runtime node.js') + await cli() + assert.ok(existsSync(join(tmp, 'src', 'http', 'get-index', 'index.mjs')), 'src/http/get-index/index.mjs created') + assert.ok(readFileSync(join(tmp, 'app.arc'), 'utf-8').match(/runtime node/), '"runtime node" present somewhere in manifest') + } + finally { + process.chdir(origCwd) + } }) it('should build the basic templated deno runtime project', async () => { - process.chdir(origCwd) - emptyDirSync(tmp) process.chdir(tmp) - args('--no-install --runtime deno') - await cli() - assert.ok(existsSync(join(tmp, 'src', 'http', 'get-index', 'mod.ts')), 'src/http/get-index/mod.ts created') - assert.ok(readFileSync(join(tmp, 'app.arc'), 'utf-8').match(/runtime deno/), '"runtime deno" present somewhere in manifest') + try { + args('--no-install --runtime deno') + await cli() + assert.ok(existsSync(join(tmp, 'src', 'http', 'get-index', 'mod.ts')), 'src/http/get-index/mod.ts created') + assert.ok(readFileSync(join(tmp, 'app.arc'), 'utf-8').match(/runtime deno/), '"runtime deno" present somewhere in manifest') + } + finally { + process.chdir(origCwd) + } }) it('should build the basic templated python runtime project', async () => { - process.chdir(origCwd) - emptyDirSync(tmp) process.chdir(tmp) - args('--no-install --runtime python') - await cli() - assert.ok(existsSync(join(tmp, 'src', 'http', 'get-index', 'lambda.py')), 'src/http/get-index/lambda.py created') - assert.ok(readFileSync(join(tmp, 'app.arc'), 'utf-8').match(/runtime python/), '"runtime python" present somewhere in manifest') + try { + args('--no-install --runtime python') + await cli() + assert.ok(existsSync(join(tmp, 'src', 'http', 'get-index', 'lambda.py')), 'src/http/get-index/lambda.py created') + assert.ok(readFileSync(join(tmp, 'app.arc'), 'utf-8').match(/runtime python/), '"runtime python" present somewhere in manifest') + } + finally { + process.chdir(origCwd) + } }) it('should build the basic templated ruby runtime project', async () => { - process.chdir(origCwd) - emptyDirSync(tmp) process.chdir(tmp) - args('--no-install --runtime ruby') - await cli() - assert.ok(existsSync(join(tmp, 'src', 'http', 'get-index', 'lambda.rb')), 'src/http/get-index/lambda.rb created') - assert.ok(readFileSync(join(tmp, 'app.arc'), 'utf-8').match(/runtime ruby/), '"runtime ruby" present somewhere in manifest') + try { + args('--no-install --runtime ruby') + await cli() + assert.ok(existsSync(join(tmp, 'src', 'http', 'get-index', 'lambda.rb')), 'src/http/get-index/lambda.rb created') + assert.ok(readFileSync(join(tmp, 'app.arc'), 'utf-8').match(/runtime ruby/), '"runtime ruby" present somewhere in manifest') + } + finally { + process.chdir(origCwd) + } }) after(() => { From c907e705772692fdde98fe544f2bcd76b799e332 Mon Sep 17 00:00:00 2001 From: Brian LeRoux Date: Fri, 28 Nov 2025 10:20:59 -0800 Subject: [PATCH 04/12] fix: failing tests hopefully haha --- test/integration/cli-test.js | 60 ++++++++++-------------------------- 1 file changed, 17 insertions(+), 43 deletions(-) diff --git a/test/integration/cli-test.js b/test/integration/cli-test.js index b663501..6f989bd 100644 --- a/test/integration/cli-test.js +++ b/test/integration/cli-test.js @@ -4,7 +4,6 @@ let cli = require('../../src/cli') let { join, resolve } = require('path') let { readFileSync, existsSync, rmSync, mkdirSync } = require('fs') let tmp = resolve(__dirname, '..', 'tmp') -let origCwd = process.cwd() let argv = process.argv let args = s => process.argv = [ 'fake-env', 'fake-file', ...s.split(' ') ] @@ -23,64 +22,39 @@ describe('CLI Integration Tests', () => { }) beforeEach(() => { - // Clean tmp directory before each test but stay in original directory + // Clean tmp directory before each test emptyDirSync(tmp) }) it('should build the basic templated node runtime project', async () => { - process.chdir(tmp) - try { - args('--no-install --runtime node.js') - await cli() - assert.ok(existsSync(join(tmp, 'src', 'http', 'get-index', 'index.mjs')), 'src/http/get-index/index.mjs created') - assert.ok(readFileSync(join(tmp, 'app.arc'), 'utf-8').match(/runtime node/), '"runtime node" present somewhere in manifest') - } - finally { - process.chdir(origCwd) - } + args(`--no-install --runtime node.js ${tmp}`) + await cli() + assert.ok(existsSync(join(tmp, 'src', 'http', 'get-index', 'index.mjs')), 'src/http/get-index/index.mjs created') + assert.ok(readFileSync(join(tmp, 'app.arc'), 'utf-8').match(/runtime node/), '"runtime node" present somewhere in manifest') }) it('should build the basic templated deno runtime project', async () => { - process.chdir(tmp) - try { - args('--no-install --runtime deno') - await cli() - assert.ok(existsSync(join(tmp, 'src', 'http', 'get-index', 'mod.ts')), 'src/http/get-index/mod.ts created') - assert.ok(readFileSync(join(tmp, 'app.arc'), 'utf-8').match(/runtime deno/), '"runtime deno" present somewhere in manifest') - } - finally { - process.chdir(origCwd) - } + args(`--no-install --runtime deno ${tmp}`) + await cli() + assert.ok(existsSync(join(tmp, 'src', 'http', 'get-index', 'mod.ts')), 'src/http/get-index/mod.ts created') + assert.ok(readFileSync(join(tmp, 'app.arc'), 'utf-8').match(/runtime deno/), '"runtime deno" present somewhere in manifest') }) it('should build the basic templated python runtime project', async () => { - process.chdir(tmp) - try { - args('--no-install --runtime python') - await cli() - assert.ok(existsSync(join(tmp, 'src', 'http', 'get-index', 'lambda.py')), 'src/http/get-index/lambda.py created') - assert.ok(readFileSync(join(tmp, 'app.arc'), 'utf-8').match(/runtime python/), '"runtime python" present somewhere in manifest') - } - finally { - process.chdir(origCwd) - } + args(`--no-install --runtime python ${tmp}`) + await cli() + assert.ok(existsSync(join(tmp, 'src', 'http', 'get-index', 'lambda.py')), 'src/http/get-index/lambda.py created') + assert.ok(readFileSync(join(tmp, 'app.arc'), 'utf-8').match(/runtime python/), '"runtime python" present somewhere in manifest') }) it('should build the basic templated ruby runtime project', async () => { - process.chdir(tmp) - try { - args('--no-install --runtime ruby') - await cli() - assert.ok(existsSync(join(tmp, 'src', 'http', 'get-index', 'lambda.rb')), 'src/http/get-index/lambda.rb created') - assert.ok(readFileSync(join(tmp, 'app.arc'), 'utf-8').match(/runtime ruby/), '"runtime ruby" present somewhere in manifest') - } - finally { - process.chdir(origCwd) - } + args(`--no-install --runtime ruby ${tmp}`) + await cli() + assert.ok(existsSync(join(tmp, 'src', 'http', 'get-index', 'lambda.rb')), 'src/http/get-index/lambda.rb created') + assert.ok(readFileSync(join(tmp, 'app.arc'), 'utf-8').match(/runtime ruby/), '"runtime ruby" present somewhere in manifest') }) after(() => { process.argv = argv - process.chdir(origCwd) }) }) From 2cbacf6fd683101aa2ffe5f7cee8a2fcb460a822 Mon Sep 17 00:00:00 2001 From: Brian LeRoux Date: Fri, 28 Nov 2025 10:23:36 -0800 Subject: [PATCH 05/12] fix: failing tests maybe --- test/integration/cli-test.js | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/test/integration/cli-test.js b/test/integration/cli-test.js index 6f989bd..cfe63a7 100644 --- a/test/integration/cli-test.js +++ b/test/integration/cli-test.js @@ -1,11 +1,9 @@ -let { describe, it, before, after, beforeEach } = require('node:test') +let { describe, it, before, beforeEach, afterEach } = require('node:test') let assert = require('node:assert/strict') let cli = require('../../src/cli') let { join, resolve } = require('path') let { readFileSync, existsSync, rmSync, mkdirSync } = require('fs') let tmp = resolve(__dirname, '..', 'tmp') -let argv = process.argv -let args = s => process.argv = [ 'fake-env', 'fake-file', ...s.split(' ') ] // Helper to empty a directory (replaces fs-extra's emptyDirSync) function emptyDirSync (dir) { @@ -16,9 +14,13 @@ function emptyDirSync (dir) { } describe('CLI Integration Tests', () => { + let originalArgv + before(() => { // Ensure tmp directory exists emptyDirSync(tmp) + // Save original argv + originalArgv = process.argv }) beforeEach(() => { @@ -26,35 +28,36 @@ describe('CLI Integration Tests', () => { emptyDirSync(tmp) }) + afterEach(() => { + // Restore argv after each test + process.argv = originalArgv + }) + it('should build the basic templated node runtime project', async () => { - args(`--no-install --runtime node.js ${tmp}`) + process.argv = [ 'node', 'test', '--no-install', '--runtime', 'node.js', tmp ] await cli() assert.ok(existsSync(join(tmp, 'src', 'http', 'get-index', 'index.mjs')), 'src/http/get-index/index.mjs created') assert.ok(readFileSync(join(tmp, 'app.arc'), 'utf-8').match(/runtime node/), '"runtime node" present somewhere in manifest') }) it('should build the basic templated deno runtime project', async () => { - args(`--no-install --runtime deno ${tmp}`) + process.argv = [ 'node', 'test', '--no-install', '--runtime', 'deno', tmp ] await cli() assert.ok(existsSync(join(tmp, 'src', 'http', 'get-index', 'mod.ts')), 'src/http/get-index/mod.ts created') assert.ok(readFileSync(join(tmp, 'app.arc'), 'utf-8').match(/runtime deno/), '"runtime deno" present somewhere in manifest') }) it('should build the basic templated python runtime project', async () => { - args(`--no-install --runtime python ${tmp}`) + process.argv = [ 'node', 'test', '--no-install', '--runtime', 'python', tmp ] await cli() assert.ok(existsSync(join(tmp, 'src', 'http', 'get-index', 'lambda.py')), 'src/http/get-index/lambda.py created') assert.ok(readFileSync(join(tmp, 'app.arc'), 'utf-8').match(/runtime python/), '"runtime python" present somewhere in manifest') }) it('should build the basic templated ruby runtime project', async () => { - args(`--no-install --runtime ruby ${tmp}`) + process.argv = [ 'node', 'test', '--no-install', '--runtime', 'ruby', tmp ] await cli() assert.ok(existsSync(join(tmp, 'src', 'http', 'get-index', 'lambda.rb')), 'src/http/get-index/lambda.rb created') assert.ok(readFileSync(join(tmp, 'app.arc'), 'utf-8').match(/runtime ruby/), '"runtime ruby" present somewhere in manifest') }) - - after(() => { - process.argv = argv - }) }) From 819c7375a5da7ce11a9fbcbd70aadb3f8579f188 Mon Sep 17 00:00:00 2001 From: Brian LeRoux Date: Fri, 28 Nov 2025 10:34:17 -0800 Subject: [PATCH 06/12] fix: maybe --- test/integration/cli-test.js | 46 +++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/test/integration/cli-test.js b/test/integration/cli-test.js index cfe63a7..b5d932f 100644 --- a/test/integration/cli-test.js +++ b/test/integration/cli-test.js @@ -1,8 +1,9 @@ -let { describe, it, before, beforeEach, afterEach } = require('node:test') +let { describe, it, before, beforeEach } = require('node:test') let assert = require('node:assert/strict') -let cli = require('../../src/cli') +let create = require('../../src/index') let { join, resolve } = require('path') let { readFileSync, existsSync, rmSync, mkdirSync } = require('fs') +let { updater } = require('@architect/utils') let tmp = resolve(__dirname, '..', 'tmp') // Helper to empty a directory (replaces fs-extra's emptyDirSync) @@ -14,13 +15,9 @@ function emptyDirSync (dir) { } describe('CLI Integration Tests', () => { - let originalArgv - before(() => { // Ensure tmp directory exists emptyDirSync(tmp) - // Save original argv - originalArgv = process.argv }) beforeEach(() => { @@ -28,35 +25,46 @@ describe('CLI Integration Tests', () => { emptyDirSync(tmp) }) - afterEach(() => { - // Restore argv after each test - process.argv = originalArgv - }) - it('should build the basic templated node runtime project', async () => { - process.argv = [ 'node', 'test', '--no-install', '--runtime', 'node.js', tmp ] - await cli() + await create({ + folder: tmp, + install: false, + runtime: 'node.js', + update: updater('Create'), + }) assert.ok(existsSync(join(tmp, 'src', 'http', 'get-index', 'index.mjs')), 'src/http/get-index/index.mjs created') assert.ok(readFileSync(join(tmp, 'app.arc'), 'utf-8').match(/runtime node/), '"runtime node" present somewhere in manifest') }) it('should build the basic templated deno runtime project', async () => { - process.argv = [ 'node', 'test', '--no-install', '--runtime', 'deno', tmp ] - await cli() + await create({ + folder: tmp, + install: false, + runtime: 'deno', + update: updater('Create'), + }) assert.ok(existsSync(join(tmp, 'src', 'http', 'get-index', 'mod.ts')), 'src/http/get-index/mod.ts created') assert.ok(readFileSync(join(tmp, 'app.arc'), 'utf-8').match(/runtime deno/), '"runtime deno" present somewhere in manifest') }) it('should build the basic templated python runtime project', async () => { - process.argv = [ 'node', 'test', '--no-install', '--runtime', 'python', tmp ] - await cli() + await create({ + folder: tmp, + install: false, + runtime: 'python', + update: updater('Create'), + }) assert.ok(existsSync(join(tmp, 'src', 'http', 'get-index', 'lambda.py')), 'src/http/get-index/lambda.py created') assert.ok(readFileSync(join(tmp, 'app.arc'), 'utf-8').match(/runtime python/), '"runtime python" present somewhere in manifest') }) it('should build the basic templated ruby runtime project', async () => { - process.argv = [ 'node', 'test', '--no-install', '--runtime', 'ruby', tmp ] - await cli() + await create({ + folder: tmp, + install: false, + runtime: 'ruby', + update: updater('Create'), + }) assert.ok(existsSync(join(tmp, 'src', 'http', 'get-index', 'lambda.rb')), 'src/http/get-index/lambda.rb created') assert.ok(readFileSync(join(tmp, 'app.arc'), 'utf-8').match(/runtime ruby/), '"runtime ruby" present somewhere in manifest') }) From 75950e91b5650d034e0bda1b39fd1056da593915 Mon Sep 17 00:00:00 2001 From: Brian LeRoux Date: Fri, 28 Nov 2025 10:50:51 -0800 Subject: [PATCH 07/12] idk --- package.json | 4 ++-- test/integration/cli-test.js | 12 ++++++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 620bae6..244df73 100644 --- a/package.json +++ b/package.json @@ -14,8 +14,8 @@ "test": "npm run lint && npm run test:integration && npm run coverage", "test:nolint": "npm run test:integration && npm run coverage", "test:unit": "node --test 'test/unit/**/*-test.js'", - "test:integration": "node --test 'test/integration/**/*-test.js'", - "coverage": "node --test --experimental-test-coverage 'test/unit/**/*-test.js' 'test/integration/**/*-test.js'", + "test:integration": "node --test test/integration/cli-test.js", + "coverage": "node --test --experimental-test-coverage 'test/unit/**/*-test.js' test/integration/cli-test.js", "lint": "eslint . --fix", "rc": "npm version prerelease --preid RC" }, diff --git a/test/integration/cli-test.js b/test/integration/cli-test.js index b5d932f..25f7a9e 100644 --- a/test/integration/cli-test.js +++ b/test/integration/cli-test.js @@ -26,44 +26,48 @@ describe('CLI Integration Tests', () => { }) it('should build the basic templated node runtime project', async () => { + let update = updater('Create') await create({ folder: tmp, install: false, runtime: 'node.js', - update: updater('Create'), + update, }) assert.ok(existsSync(join(tmp, 'src', 'http', 'get-index', 'index.mjs')), 'src/http/get-index/index.mjs created') assert.ok(readFileSync(join(tmp, 'app.arc'), 'utf-8').match(/runtime node/), '"runtime node" present somewhere in manifest') }) it('should build the basic templated deno runtime project', async () => { + let update = updater('Create') await create({ folder: tmp, install: false, runtime: 'deno', - update: updater('Create'), + update, }) assert.ok(existsSync(join(tmp, 'src', 'http', 'get-index', 'mod.ts')), 'src/http/get-index/mod.ts created') assert.ok(readFileSync(join(tmp, 'app.arc'), 'utf-8').match(/runtime deno/), '"runtime deno" present somewhere in manifest') }) it('should build the basic templated python runtime project', async () => { + let update = updater('Create') await create({ folder: tmp, install: false, runtime: 'python', - update: updater('Create'), + update, }) assert.ok(existsSync(join(tmp, 'src', 'http', 'get-index', 'lambda.py')), 'src/http/get-index/lambda.py created') assert.ok(readFileSync(join(tmp, 'app.arc'), 'utf-8').match(/runtime python/), '"runtime python" present somewhere in manifest') }) it('should build the basic templated ruby runtime project', async () => { + let update = updater('Create') await create({ folder: tmp, install: false, runtime: 'ruby', - update: updater('Create'), + update, }) assert.ok(existsSync(join(tmp, 'src', 'http', 'get-index', 'lambda.rb')), 'src/http/get-index/lambda.rb created') assert.ok(readFileSync(join(tmp, 'app.arc'), 'utf-8').match(/runtime ruby/), '"runtime ruby" present somewhere in manifest') From c3bec1b688983e2dba2ea9228a1abba2987c6023 Mon Sep 17 00:00:00 2001 From: Brian LeRoux Date: Fri, 28 Nov 2025 10:54:07 -0800 Subject: [PATCH 08/12] wtfbbq --- .github/workflows/build.yml | 1 + package.json | 4 +- test/integration/run.js | 84 +++++++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 test/integration/run.js diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bb666ec..8e0476a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -51,6 +51,7 @@ jobs: run: npm test env: CI: true + NODE_OPTIONS: --no-warnings - name: Notify uses: sarisia/actions-status-discord@v1 diff --git a/package.json b/package.json index 244df73..0430998 100644 --- a/package.json +++ b/package.json @@ -14,8 +14,8 @@ "test": "npm run lint && npm run test:integration && npm run coverage", "test:nolint": "npm run test:integration && npm run coverage", "test:unit": "node --test 'test/unit/**/*-test.js'", - "test:integration": "node --test test/integration/cli-test.js", - "coverage": "node --test --experimental-test-coverage 'test/unit/**/*-test.js' test/integration/cli-test.js", + "test:integration": "node test/integration/run.js", + "coverage": "node --test --experimental-test-coverage 'test/unit/**/*-test.js'", "lint": "eslint . --fix", "rc": "npm version prerelease --preid RC" }, diff --git a/test/integration/run.js b/test/integration/run.js new file mode 100644 index 0000000..3557718 --- /dev/null +++ b/test/integration/run.js @@ -0,0 +1,84 @@ +#!/usr/bin/env node +// Simple test runner that avoids Node.js test runner serialization issues +let create = require('../../src/index') +let { join, resolve } = require('path') +let { readFileSync, existsSync, rmSync, mkdirSync } = require('fs') +let { updater } = require('@architect/utils') + +let tmp = resolve(__dirname, '..', 'tmp') +let passed = 0 +let failed = 0 + +function emptyDirSync (dir) { + if (existsSync(dir)) { + rmSync(dir, { recursive: true, force: true }) + } + mkdirSync(dir, { recursive: true }) +} + +async function test (name, fn) { + try { + emptyDirSync(tmp) + await fn() + console.log(`✓ ${name}`) + passed++ + } + catch (err) { + console.error(`✗ ${name}`) + console.error(err) + failed++ + } +} + +async function main () { + console.log('Running CLI Integration Tests...\n') + + await test('should build the basic templated node runtime project', async () => { + let update = updater('Create') + await create({ folder: tmp, install: false, runtime: 'node.js', update }) + if (!existsSync(join(tmp, 'src', 'http', 'get-index', 'index.mjs'))) { + throw new Error('index.mjs not created') + } + if (!readFileSync(join(tmp, 'app.arc'), 'utf-8').match(/runtime node/)) { + throw new Error('runtime node not in manifest') + } + }) + + await test('should build the basic templated deno runtime project', async () => { + let update = updater('Create') + await create({ folder: tmp, install: false, runtime: 'deno', update }) + if (!existsSync(join(tmp, 'src', 'http', 'get-index', 'mod.ts'))) { + throw new Error('mod.ts not created') + } + if (!readFileSync(join(tmp, 'app.arc'), 'utf-8').match(/runtime deno/)) { + throw new Error('runtime deno not in manifest') + } + }) + + await test('should build the basic templated python runtime project', async () => { + let update = updater('Create') + await create({ folder: tmp, install: false, runtime: 'python', update }) + if (!existsSync(join(tmp, 'src', 'http', 'get-index', 'lambda.py'))) { + throw new Error('lambda.py not created') + } + if (!readFileSync(join(tmp, 'app.arc'), 'utf-8').match(/runtime python/)) { + throw new Error('runtime python not in manifest') + } + }) + + await test('should build the basic templated ruby runtime project', async () => { + let update = updater('Create') + await create({ folder: tmp, install: false, runtime: 'ruby', update }) + if (!existsSync(join(tmp, 'src', 'http', 'get-index', 'lambda.rb'))) { + throw new Error('lambda.rb not created') + } + if (!readFileSync(join(tmp, 'app.arc'), 'utf-8').match(/runtime ruby/)) { + throw new Error('runtime ruby not in manifest') + } + }) + + console.log(`\n${passed} passed, ${failed} failed`) + process.exit(failed > 0 ? 1 : 0) +} + +main() From 5fc3edde3a3c34c2d9ffa794868fdfa468729cf9 Mon Sep 17 00:00:00 2001 From: Brian LeRoux Date: Fri, 28 Nov 2025 11:13:49 -0800 Subject: [PATCH 09/12] fix: remove old workflow code path --- .github/workflows/build.yml | 7 ------- package.json | 2 +- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8e0476a..f516684 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -40,14 +40,7 @@ jobs: - name: Install run: npm install - - name: Test (Node.js <= 16.x) - 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 diff --git a/package.json b/package.json index 0430998..f7fc6bf 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,6 @@ }, "devDependencies": { "@architect/eslint-config": "~3.0.0", - "eslint": "~9.36.0" + "eslint": "~9.39.1" } } From d572a9c45bc0d47513b3329559cecfd9bb581aaa Mon Sep 17 00:00:00 2001 From: Brian LeRoux Date: Fri, 28 Nov 2025 11:24:06 -0800 Subject: [PATCH 10/12] fix: updates changelog --- changelog.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index 9fedd15..f07ef88 100644 --- a/changelog.md +++ b/changelog.md @@ -2,12 +2,20 @@ --- +## [6.0.1] 2025-11-28 + +### Changed + +- Removed almost all devdeps in favour of node internal test runner/coverage + +--- + ## [6.0.0] 2024-09-24 ### Changed - Updated dependencies -- Updated to >= node 20 +- Updated to >= node 22 --- From 3cd4e961bc3b7f66ca9536fb913d4b4d14df658b Mon Sep 17 00:00:00 2001 From: Brian LeRoux Date: Fri, 28 Nov 2025 11:24:09 -0800 Subject: [PATCH 11/12] 7.0.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f7fc6bf..75536d5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@architect/create", - "version": "7.0.0", + "version": "7.0.1", "description": "Idempotently initialize Architect projects", "main": "src/index.js", "bin": { From c647bd8e273a4ade4ec5a63cf603246299660f26 Mon Sep 17 00:00:00 2001 From: Brian LeRoux Date: Fri, 28 Nov 2025 11:25:25 -0800 Subject: [PATCH 12/12] fix changelog --- changelog.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/changelog.md b/changelog.md index f07ef88..2af78e7 100644 --- a/changelog.md +++ b/changelog.md @@ -2,20 +2,24 @@ --- -## [6.0.1] 2025-11-28 - -### Changed +## [7.0.1] 2025-11-28 - Removed almost all devdeps in favour of node internal test runner/coverage --- +### [7.0.0] 2025-11-27 + +- Updated to >= node 22 + +--- + ## [6.0.0] 2024-09-24 ### Changed - Updated dependencies -- Updated to >= node 22 +- Updated to >= node 20 ---