diff --git a/changelog.md b/changelog.md index df49b15..7a2989f 100644 --- a/changelog.md +++ b/changelog.md @@ -10,6 +10,13 @@ - Takes advantage of Node.js 22's built-in glob support - Reduces external dependencies and improves performance - No functional changes to dependency discovery behavior +- **Test infrastructure modernization**: Migrated from tape to Node.js native test runner + - Removed dependencies: `tape`, `nyc`, `cross-env`, `proxyquire`, `mock-tmp` + - Added dependency: `c8` (for code coverage) + - All tests now use Node.js built-in `node:test` and `node:assert` modules + - Module mocking now uses Node.js native mock functionality instead of proxyquire + - Temporary directory creation now uses native `fs.mkdtempSync()` instead of mock-tmp + - Test scripts no longer require cross-env for environment variable management ### Migration Guide @@ -25,11 +32,22 @@ If you are upgrading from version 5.x: 3. **No code changes required**: The API remains unchanged, all existing code will continue to work +4. **For contributors**: If you're contributing to this project, note the new testing patterns: + - Use `node:test` and `node:assert` instead of tape + - Use native `mock.module()` for mocking instead of proxyquire + - Use `fs.mkdtempSync()` for temporary directories instead of mock-tmp + - Test scripts now use `node --test` directly + - Coverage reports use `c8` instead of `nyc` + ### Changed - Updated `engines.node` in package.json from `>=20` to `>=22` - Migrated from `@architect/utils/glob` to native `fs.globSync` for file pattern matching - Updated CI test matrix to use Node.js 22.x and 24.x +- Migrated all test files from tape to Node.js native test runner +- Updated test scripts to use `node --test` instead of tape +- Replaced nyc with c8 for code coverage reporting +- Removed cross-env from all test scripts (no longer needed with native test runner) --- diff --git a/package.json b/package.json index 28147bd..accff43 100644 --- a/package.json +++ b/package.json @@ -9,10 +9,11 @@ "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 tape 'test/unit/**/*-tests.js'", - "test:integration": "cross-env tape 'test/integration/**/*-tests.js'", - "test:integration:fast": "cross-env tape 'test/integration/symlink/**/*-tests.js' 'test/integration/*-tests.js'", - "coverage": "nyc --reporter=lcov --reporter=text npm run test:unit", + "test:unit": "node --test 'test/unit/**/*-tests.js'", + "test:integration": "node --test --test-concurrency=1 'test/integration/**/*-tests.js'", + "test:integration:fast": "node --test --test-concurrency=1 'test/integration/symlink/**/*-tests.js' 'test/integration/*-tests.js'", + "test:verify-migration": "node scripts/verify-migration.js", + "coverage": "c8 --reporter=lcov --reporter=text node --test 'test/unit/**/*-tests.js'", "lint": "eslint . --fix", "rc": "npm version prerelease --preid RC", "vendor": "cd src/actions/autoinstall/python/py/ && vendoring sync && zip -r9 vendor.zip ./vendor" @@ -42,13 +43,9 @@ }, "devDependencies": { "@architect/eslint-config": "~3.0.0", - "cross-env": "~10.0.0", + "c8": "~10.1.3", "eslint": "~9.36.0", - "mock-tmp": "~0.0.4", - "nyc": "~17.1.0", "pnpm": "~10.17.1", - "proxyquire": "~2.1.3", - "tape": "~5.9.0", "yarn": "~1.22.22" } } diff --git a/readme.md b/readme.md index b7d2707..76b42ee 100644 --- a/readme.md +++ b/readme.md @@ -92,6 +92,88 @@ Note: by default `update` also updates dependencies in shared folders like `src/ Copies shared code (from `src/shared` and `src/views`, or your custom `@shared` + `@views` paths, if any) into all functions. +# Testing + +This project uses Node.js's native test runner (`node:test` module) for all tests. + +## Running Tests + +```bash +# Run all tests (lint + integration + coverage) +npm test + +# Run only unit tests +npm run test:unit + +# Run only integration tests +npm run test:integration + +# Run tests without linting +npm run test:nolint + +# Run coverage report +npm run coverage +``` + +## Test Structure + +- **Unit tests**: Located in `test/unit/` directory +- **Integration tests**: Located in `test/integration/` directory +- All test files use the `-tests.js` suffix + +## Writing Tests + +Tests use Node.js native testing modules: + +```javascript +const { test } = require('node:test') +const assert = require('node:assert') + +test('example test', async (t) => { + const result = someFunction() + assert.strictEqual(result, expectedValue) +}) +``` + +### Mocking + +For module mocking, use Node.js native mock functionality: + +```javascript +const { test, mock } = require('node:test') + +test('test with mocks', async (t) => { + mock.module('./some-module', { + namedExports: { someFunction: () => 'mocked value' } + }) + const module = require('./module-under-test') + // Test with mocked dependency +}) +``` + +### Temporary Directories + +For tests requiring temporary directories, use native `fs` operations: + +```javascript +const { mkdtempSync, rmSync } = require('fs') +const { tmpdir } = require('os') +const { join } = require('path') + +test('test with temp dir', async (t) => { + const tmp = mkdtempSync(join(tmpdir(), 'test-')) + t.after(() => rmSync(tmp, { recursive: true, force: true })) + // Use tmp directory in test +}) +``` + +## Coverage + +Code coverage is collected using `c8` and reports are generated in the `coverage/` directory: +- `coverage/lcov-report/` - HTML coverage report +- `coverage/lcov.info` - LCOV format for CI integration + + [shared]: #hydratesharedoptions-callback [install]: #hydrateinstalloptions-callback [update]: #hydrateupdateoptions-callback diff --git a/test/integration/_shared.js b/test/integration/_shared.js index 92bff1e..e77a56b 100644 --- a/test/integration/_shared.js +++ b/test/integration/_shared.js @@ -148,52 +148,50 @@ let viewsArtifactsDisabled = [ // Test resetters -function reset (t, callback) { +function reset (callback) { process.chdir(join(__dirname, '..')) destroyPath(mockTmp) cp(mockSource, mockTmp, { recursive: true, force: true }, function (err) { - if (err) t.fail(err) - else { - process.chdir(mockTmp) - callback() - } + if (err) throw err + process.chdir(mockTmp) + callback() }) } -function resetAndCopyShared (t, callback) { - reset(t, function () { +function resetAndCopyShared (callback) { + reset(function () { cp('_shared', 'src', { recursive: true, force: true }, function done (err) { - if (err) t.fail(err) - else callback() + if (err) throw err + callback() }) }) } -function resetAndCopySharedAutoinstall (t, callback) { - reset(t, function () { +function resetAndCopySharedAutoinstall (callback) { + reset(function () { cp('_shared-autoinstall', '.', { recursive: true, force: true }, function done (err) { - if (err) t.fail(err) - else callback() + if (err) throw err + callback() }) }) } -function resetAndCopySharedCustom (t, callback) { - reset(t, function () { +function resetAndCopySharedCustom (callback) { + reset(function () { cp('_shared-custom', '.', { recursive: true, force: true }, function done (err) { - if (err) t.fail(err) - else callback() + if (err) throw err + callback() }) }) } -function resetAndCopySharedPlugins (t, callback) { - reset(t, function () { +function resetAndCopySharedPlugins (callback) { + reset(function () { cp('_shared-plugins', 'src', { recursive: true, force: true }, function done (err) { - if (err) t.fail(err) - else callback() + if (err) throw err + callback() }) }) } // Ensure we don't create empty folders with copied files -let checkFolderCreation = t => t.notOk(existsSync(join('src', 'events', 'silence')), `Did not copy and create function folder that should not exist`) +let checkFolderCreation = assert => assert.ok(!existsSync(join('src', 'events', 'silence')), `Did not copy and create function folder that should not exist`) module.exports = { diff --git a/test/integration/default/install-tests.js b/test/integration/default/install-tests.js index ca25d3c..857a364 100644 --- a/test/integration/default/install-tests.js +++ b/test/integration/default/install-tests.js @@ -5,7 +5,8 @@ let { readFileSync, writeFileSync, } = require('fs') -let test = require('tape') +const { test } = require('node:test') +const assert = require('node:assert') let { reset, resetAndCopyShared, @@ -32,86 +33,70 @@ let { let hydrate = require('../../..') process.env.CI = true // Suppresses tape issues with progress indicator -test('Does not exit code 1', t => { - process.on('exit', code => { if (code === 1) t.fail('Exited code 1!') }) - t.end() -}) - -test(`[Default (file copying)] install() hydrates all Functions', shared and views dependencies (autoinstall enabled)`, t => { - let count = - pythonDependencies.length + - rubyDependencies().length + - nodeDependencies.length + - pythonSharedDependencies.length + - pythonViewsDependencies.length + - rubySharedDependencies.length + - rubyViewsDependencies.length + - nodeSharedDependencies.length + - nodeViewsDependencies.length + 7 - t.plan(count) - resetAndCopyShared(t, function () { - hydrate.install({ autoinstall: true }, function (err) { - if (err) t.fail(err) - else { +test(`[Default (file copying)] install() hydrates all Functions', shared and views dependencies (autoinstall enabled)`, async () => { + await new Promise((resolve) => { + resetAndCopyShared(function () { + hydrate.install({ autoinstall: true }, function (err) { + if (err) assert.fail(err) pythonDependencies.forEach(p => { - t.ok(existsSync(p), `python dependency exists at ${p}`) + assert.ok(existsSync(p), `python dependency exists at ${p}`) }) rubyDependencies().forEach(p => { - t.ok(existsSync(p), `ruby dependency exists at ${p}`) + assert.ok(existsSync(p), `ruby dependency exists at ${p}`) }) nodeDependencies.forEach(p => { - t.ok(existsSync(p), `node dependency exists at ${p}`) + assert.ok(existsSync(p), `node dependency exists at ${p}`) }) pythonSharedDependencies.forEach(p => { - t.ok(existsSync(p), `python shared dependency exists at ${p}`) + assert.ok(existsSync(p), `python shared dependency exists at ${p}`) }) rubySharedDependencies.forEach(p => { - t.ok(existsSync(p), `ruby shared dependency exists at ${p}`) + assert.ok(existsSync(p), `ruby shared dependency exists at ${p}`) }) nodeSharedDependencies.forEach(p => { - t.ok(existsSync(p), `node shared dependency exists at ${p}`) + assert.ok(existsSync(p), `node shared dependency exists at ${p}`) }) pythonViewsDependencies.forEach(p => { - t.ok(existsSync(p), `python views dependency exists at ${p}`) + assert.ok(existsSync(p), `python views dependency exists at ${p}`) }) rubyViewsDependencies.forEach(p => { - t.ok(existsSync(p), `ruby views dependency exists at ${p}`) + assert.ok(existsSync(p), `ruby views dependency exists at ${p}`) }) nodeViewsDependencies.forEach(p => { - t.ok(existsSync(p), `node views dependency exists at ${p}`) + assert.ok(existsSync(p), `node views dependency exists at ${p}`) }) // Autoinstall-specific tests let package = join(arcAutoinstall[0], 'node_modules', '_arc-autoinstall', 'package.json') - t.ok(existsSync(package), 'Found autoinstall package.json') + assert.ok(existsSync(package), 'Found autoinstall package.json') let requirements = join(arcAutoinstall[1], 'vendor', '_arc_autoinstall', 'requirements.txt') - t.ok(existsSync(requirements), 'Found autoinstall requirements.txt') + assert.ok(existsSync(requirements), 'Found autoinstall requirements.txt') // Yarn-specific tests let yarnFunction = join(mockTmp, 'src', 'http', 'put-on_your_boots') let yarnIntFile = join(yarnFunction, 'node_modules', '.yarn-integrity') let pkgLockFile = join(yarnFunction, 'package-lock.json') - t.ok(existsSync(yarnIntFile), 'Found yarn integrity file') - t.notOk(existsSync(pkgLockFile), `Did not find package-lock.json (i.e. npm didn't run)`) + assert.ok(existsSync(yarnIntFile), 'Found yarn integrity file') + assert.ok(!existsSync(pkgLockFile), `Did not find package-lock.json (i.e. npm didn't run)`) // pnpm-specific tests let pnpmFunction = join(mockTmp, 'src', 'http', 'options-are_plentiful') let pnpmIntFile = join(pnpmFunction, 'node_modules', '.modules.yaml') pkgLockFile = join(pnpmFunction, 'package-lock.json') - t.ok(existsSync(pnpmIntFile), 'Found pnpm integrity file') - t.notOk(existsSync(pkgLockFile), `Did not find package-lock.json (i.e. npm didn't run)`) - checkFolderCreation(t) - } + assert.ok(existsSync(pnpmIntFile), 'Found pnpm integrity file') + assert.ok(!existsSync(pkgLockFile), `Did not find package-lock.json (i.e. npm didn't run)`) + checkFolderCreation(assert) + resolve() + }) }) }) }) -test(`[Default (file copying)] install() hydrates all Functions', shared and views dependencies (autoinstall enabled, no package files in shared)`, t => { - t.plan(7) - resetAndCopySharedAutoinstall(t, function () { - hydrate.install({ autoinstall: true }, function (err) { - if (err) t.fail(err) - else { +test(`[Default (file copying)] install() hydrates all Functions', shared and views dependencies (autoinstall enabled, no package files in shared)`, async () => { + await new Promise((resolve) => { + resetAndCopySharedAutoinstall(function () { + hydrate.install({ autoinstall: true }, function (err) { + if (err) assert.fail(err) // Autoinstall-specific tests let package = join(arcAutoinstall[0], 'node_modules', '_arc-autoinstall', 'package.json') - t.ok(existsSync(package), 'Found autoinstall package.json') + assert.ok(existsSync(package), 'Found autoinstall package.json') let autoinstall = JSON.parse(readFileSync(package)) let _parsed = [ 'index.js', @@ -123,154 +108,155 @@ test(`[Default (file copying)] install() hydrates all Functions', shared and vie 'run-series': 'latest', 'tiny-json-http': 'latest', } - t.deepEqual(autoinstall._parsed, _parsed, 'Autoinstall walked shared + views') - t.deepEqual(autoinstall.dependencies, dependencies, 'Autoinstall installed shared + views deps') + assert.deepStrictEqual(autoinstall._parsed, _parsed, 'Autoinstall walked shared + views') + assert.deepStrictEqual(autoinstall.dependencies, dependencies, 'Autoinstall installed shared + views deps') // Check to see if files that are supposed to be there are actually there - t.ok(existsSync(nodeDependencies[1]), `scoped install for ${nodeFunctions[0]} installed dependencies in ${nodeDependencies[1]}`) + assert.ok(existsSync(nodeDependencies[1]), `scoped install for ${nodeFunctions[0]} installed dependencies in ${nodeDependencies[1]}`) let path = join(arcHttp[2], 'node_modules') let sharedDep = join(path, 'cpr') let viewsDep = join(path, 'run-series') - t.ok(existsSync(sharedDep), 'Autoinstalled shared dependency') - t.ok(existsSync(viewsDep), 'Autoinstalled views dependency') - checkFolderCreation(t) - } + assert.ok(existsSync(sharedDep), 'Autoinstalled shared dependency') + assert.ok(existsSync(viewsDep), 'Autoinstalled views dependency') + checkFolderCreation(assert) + resolve() + }) }) }) }) -test(`[Default (file copying)] install (specific path / single path) hydrates only Functions found in the specified subpath`, t => { - t.plan(8) - resetAndCopyShared(t, function () { - let basepath = nodeFunctions[0] - hydrate.install({ basepath }, function (err) { - if (err) t.fail(err) - else { +test(`[Default (file copying)] install (specific path / single path) hydrates only Functions found in the specified subpath`, async () => { + await new Promise((resolve) => { + resetAndCopyShared(function () { + let basepath = nodeFunctions[0] + hydrate.install({ basepath }, function (err) { + if (err) assert.fail(err) // Check to see if files that are supposed to be there are actually there - t.ok(existsSync(nodeDependencies[0]), `scoped install for ${nodeFunctions[0]} installed dependencies in ${nodeDependencies[0]}`) - t.notOk(existsSync(pythonDependencies[0]), `scoped install did not install dependencies for unspecified function at ${pythonDependencies[0]}`) + assert.ok(existsSync(nodeDependencies[0]), `scoped install for ${nodeFunctions[0]} installed dependencies in ${nodeDependencies[0]}`) + assert.ok(!existsSync(pythonDependencies[0]), `scoped install did not install dependencies for unspecified function at ${pythonDependencies[0]}`) let arcFileArtifact = arcFileArtifacts.find(p => p.startsWith(arcHttp[0])) let sharedArtifact = sharedArtifacts.find(p => p.startsWith(arcHttp[0])) let viewsArtifact = viewsArtifacts.find(p => p.startsWith(arcHttp[0])) - t.ok(existsSync(nodeSharedDependencies[0]), `node shared dependency exists at ${nodeSharedDependencies[0]}`) - t.ok(existsSync(nodeViewsDependencies[0]), `node views dependency exists at ${nodeViewsDependencies[0]}`) - t.notOk(existsSync(arcFileArtifact), `arc file does not exist at ${arcFileArtifact}`) - t.ok(existsSync(sharedArtifact), `shared file artifact exists at ${sharedArtifact}`) - t.ok(existsSync(viewsArtifact), `shared file artifact exists at ${viewsArtifact}`) - checkFolderCreation(t) - } + assert.ok(existsSync(nodeSharedDependencies[0]), `node shared dependency exists at ${nodeSharedDependencies[0]}`) + assert.ok(existsSync(nodeViewsDependencies[0]), `node views dependency exists at ${nodeViewsDependencies[0]}`) + assert.ok(!existsSync(arcFileArtifact), `arc file does not exist at ${arcFileArtifact}`) + assert.ok(existsSync(sharedArtifact), `shared file artifact exists at ${sharedArtifact}`) + assert.ok(existsSync(viewsArtifact), `shared file artifact exists at ${viewsArtifact}`) + checkFolderCreation(assert) + resolve() + }) }) }) }) -test(`[Default (file copying)] install (specific path / single path) in a manifest-free Node.js function adds missing deps with autoinstall enabled`, t => { - t.plan(7) - resetAndCopyShared(t, function () { - let basepath = nodeFunctions[1] - hydrate.install({ basepath, autoinstall: true }, function (err) { - if (err) t.fail(err) - else { +test(`[Default (file copying)] install (specific path / single path) in a manifest-free Node.js function adds missing deps with autoinstall enabled`, async () => { + await new Promise((resolve) => { + resetAndCopyShared(function () { + let basepath = nodeFunctions[1] + hydrate.install({ basepath, autoinstall: true }, function (err) { + if (err) assert.fail(err) // Check to see if files that are supposed to be there are actually there - t.ok(existsSync(nodeDependencies[1]), `scoped install for ${nodeFunctions[1]} installed dependencies in ${nodeDependencies[1]}`) - t.notOk(existsSync(pythonDependencies[0]), `scoped install did not install dependencies for unspecified function at ${pythonDependencies[0]}`) + assert.ok(existsSync(nodeDependencies[1]), `scoped install for ${nodeFunctions[1]} installed dependencies in ${nodeDependencies[1]}`) + assert.ok(!existsSync(pythonDependencies[0]), `scoped install did not install dependencies for unspecified function at ${pythonDependencies[0]}`) let arcFileArtifact = arcFileArtifacts.find(p => p.startsWith(arcAutoinstall[0])) let sharedArtifact = sharedArtifacts.find(p => p.startsWith(arcAutoinstall[0])) let viewsArtifact = viewsArtifacts.find(p => p.startsWith(arcAutoinstall[0])) - t.ok(existsSync(nodeSharedDependencies[1]), `node shared dependency exists at ${nodeSharedDependencies[1]}`) - t.notOk(existsSync(arcFileArtifact), `arc file does not exist at ${arcFileArtifact}`) - t.ok(existsSync(sharedArtifact), `shared file artifact exists at ${sharedArtifact}`) - t.notOk(existsSync(viewsArtifact), `shared file artifact exists at ${viewsArtifact}`) - checkFolderCreation(t) - } + assert.ok(existsSync(nodeSharedDependencies[1]), `node shared dependency exists at ${nodeSharedDependencies[1]}`) + assert.ok(!existsSync(arcFileArtifact), `arc file does not exist at ${arcFileArtifact}`) + assert.ok(existsSync(sharedArtifact), `shared file artifact exists at ${sharedArtifact}`) + assert.ok(!existsSync(viewsArtifact), `shared file artifact exists at ${viewsArtifact}`) + checkFolderCreation(assert) + resolve() + }) }) }) }) -test(`[Default (file copying)] install (specific path / single path) in a manifest-free Python function adds missing deps with autoinstall enabled`, t => { - t.plan(7) - resetAndCopyShared(t, function () { - let basepath = pythonFunctions[1] - hydrate.install({ basepath, autoinstall: true }, function (err) { - if (err) t.fail(err) - else { +test(`[Default (file copying)] install (specific path / single path) in a manifest-free Python function adds missing deps with autoinstall enabled`, async () => { + await new Promise((resolve) => { + resetAndCopyShared(function () { + let basepath = pythonFunctions[1] + hydrate.install({ basepath, autoinstall: true }, function (err) { + if (err) assert.fail(err) // Check to see if files that are supposed to be there are actually there - t.ok(existsSync(pythonDependencies[1]), `scoped install for ${pythonFunctions[1]} installed dependencies in ${pythonDependencies[1]}`) - t.notOk(existsSync(nodeDependencies[0]), `scoped install did not install dependencies for unspecified function at ${nodeDependencies[0]}`) + assert.ok(existsSync(pythonDependencies[1]), `scoped install for ${pythonFunctions[1]} installed dependencies in ${pythonDependencies[1]}`) + assert.ok(!existsSync(nodeDependencies[0]), `scoped install did not install dependencies for unspecified function at ${nodeDependencies[0]}`) let arcFileArtifact = arcFileArtifacts.find(p => p.startsWith(arcAutoinstall[0])) let sharedArtifact = sharedArtifacts.find(p => p.startsWith(arcAutoinstall[0])) let viewsArtifact = viewsArtifacts.find(p => p.startsWith(arcAutoinstall[0])) - t.ok(existsSync(pythonSharedDependencies[1]), `python shared dependency exists at ${pythonSharedDependencies[1]}`) - t.notOk(existsSync(arcFileArtifact), `arc file does not exist at ${arcFileArtifact}`) - t.ok(existsSync(sharedArtifact), `shared file artifact exists at ${sharedArtifact}`) - t.notOk(existsSync(viewsArtifact), `shared file artifact exists at ${viewsArtifact}`) - checkFolderCreation(t) - } + assert.ok(existsSync(pythonSharedDependencies[1]), `python shared dependency exists at ${pythonSharedDependencies[1]}`) + assert.ok(!existsSync(arcFileArtifact), `arc file does not exist at ${arcFileArtifact}`) + assert.ok(existsSync(sharedArtifact), `shared file artifact exists at ${sharedArtifact}`) + assert.ok(!existsSync(viewsArtifact), `shared file artifact exists at ${viewsArtifact}`) + checkFolderCreation(assert) + resolve() + }) }) }) }) -test(`[Default (file copying)] install (specific path / single path) in a manifest-free Node.js function does not add missing deps with autoinstall disabled`, t => { - t.plan(7) - resetAndCopyShared(t, function () { - let basepath = nodeFunctions[1] - hydrate.install({ basepath, autoinstall: false }, function (err) { - if (err) t.fail(err) - else { +test(`[Default (file copying)] install (specific path / single path) in a manifest-free Node.js function does not add missing deps with autoinstall disabled`, async () => { + await new Promise((resolve) => { + resetAndCopyShared(function () { + let basepath = nodeFunctions[1] + hydrate.install({ basepath, autoinstall: false }, function (err) { + if (err) assert.fail(err) // Check to see if files that are supposed to be there are actually there - t.notOk(existsSync(nodeDependencies[1]), `scoped install for ${nodeFunctions[1]} installed dependencies in ${nodeDependencies[1]}`) - t.notOk(existsSync(pythonDependencies[0]), `scoped install did not install dependencies for unspecified function at ${pythonDependencies[0]}`) + assert.ok(!existsSync(nodeDependencies[1]), `scoped install for ${nodeFunctions[1]} installed dependencies in ${nodeDependencies[1]}`) + assert.ok(!existsSync(pythonDependencies[0]), `scoped install did not install dependencies for unspecified function at ${pythonDependencies[0]}`) let arcFileArtifact = arcFileArtifacts.find(p => p.startsWith(arcAutoinstall[0])) let sharedArtifact = sharedArtifacts.find(p => p.startsWith(arcAutoinstall[0])) let viewsArtifact = viewsArtifacts.find(p => p.startsWith(arcAutoinstall[0])) - t.ok(existsSync(nodeSharedDependencies[1]), `node shared dependency exists at ${nodeSharedDependencies[1]}`) - t.notOk(existsSync(arcFileArtifact), `arc file does not exist at ${arcFileArtifact}`) - t.ok(existsSync(sharedArtifact), `shared file artifact exists at ${sharedArtifact}`) - t.notOk(existsSync(viewsArtifact), `shared file artifact exists at ${viewsArtifact}`) - checkFolderCreation(t) - } + assert.ok(existsSync(nodeSharedDependencies[1]), `node shared dependency exists at ${nodeSharedDependencies[1]}`) + assert.ok(!existsSync(arcFileArtifact), `arc file does not exist at ${arcFileArtifact}`) + assert.ok(existsSync(sharedArtifact), `shared file artifact exists at ${sharedArtifact}`) + assert.ok(!existsSync(viewsArtifact), `shared file artifact exists at ${viewsArtifact}`) + checkFolderCreation(assert) + resolve() + }) }) }) }) -test(`[Default (file copying)] install (specific path / single path) in a manifest-free Python function does not add missing deps with autoinstall disabled`, t => { - t.plan(7) - resetAndCopyShared(t, function () { - let basepath = pythonFunctions[1] - hydrate.install({ basepath, autoinstall: false }, function (err) { - if (err) t.fail(err) - else { +test(`[Default (file copying)] install (specific path / single path) in a manifest-free Python function does not add missing deps with autoinstall disabled`, async () => { + await new Promise((resolve) => { + resetAndCopyShared(function () { + let basepath = pythonFunctions[1] + hydrate.install({ basepath, autoinstall: false }, function (err) { + if (err) assert.fail(err) // Check to see if files that are supposed to be there are actually there - t.notOk(existsSync(pythonDependencies[1]), `scoped install for ${pythonFunctions[1]} installed dependencies in ${pythonDependencies[1]}`) - t.notOk(existsSync(nodeDependencies[0]), `scoped install did not install dependencies for unspecified function at ${nodeDependencies[0]}`) + assert.ok(!existsSync(pythonDependencies[1]), `scoped install for ${pythonFunctions[1]} installed dependencies in ${pythonDependencies[1]}`) + assert.ok(!existsSync(nodeDependencies[0]), `scoped install did not install dependencies for unspecified function at ${nodeDependencies[0]}`) let arcFileArtifact = arcFileArtifacts.find(p => p.startsWith(arcAutoinstall[0])) let sharedArtifact = sharedArtifacts.find(p => p.startsWith(arcAutoinstall[0])) let viewsArtifact = viewsArtifacts.find(p => p.startsWith(arcAutoinstall[0])) - t.ok(existsSync(pythonSharedDependencies[1]), `python shared dependency exists at ${pythonSharedDependencies[1]}`) - t.notOk(existsSync(arcFileArtifact), `arc file does not exist at ${arcFileArtifact}`) - t.ok(existsSync(sharedArtifact), `shared file artifact exists at ${sharedArtifact}`) - t.notOk(existsSync(viewsArtifact), `shared file artifact exists at ${viewsArtifact}`) - checkFolderCreation(t) - } + assert.ok(existsSync(pythonSharedDependencies[1]), `python shared dependency exists at ${pythonSharedDependencies[1]}`) + assert.ok(!existsSync(arcFileArtifact), `arc file does not exist at ${arcFileArtifact}`) + assert.ok(existsSync(sharedArtifact), `shared file artifact exists at ${sharedArtifact}`) + assert.ok(!existsSync(viewsArtifact), `shared file artifact exists at ${viewsArtifact}`) + checkFolderCreation(assert) + resolve() + }) }) }) }) -test(`[Default (file copying)] install() should not recurse into Functions dependencies and hydrate those`, t => { - t.plan(2) - reset(t, function () { - let subdep = join(nodeFunctions[0], 'node_modules', 'poop') - mkdirSync(subdep, { recursive: true }) - writeFileSync(join(subdep, 'package.json'), JSON.stringify({ - name: 'poop', - dependencies: { 'tiny-json-http': '*' }, - }), 'utf-8') - let basepath = nodeFunctions[0] - hydrate.install({ basepath }, function (err) { - if (err) t.fail(err) - else { +test(`[Default (file copying)] install() should not recurse into Functions dependencies and hydrate those`, async () => { + await new Promise((resolve) => { + reset(function () { + let subdep = join(nodeFunctions[0], 'node_modules', 'poop') + mkdirSync(subdep, { recursive: true }) + writeFileSync(join(subdep, 'package.json'), JSON.stringify({ + name: 'poop', + dependencies: { 'tiny-json-http': '*' }, + }), 'utf-8') + let basepath = nodeFunctions[0] + hydrate.install({ basepath }, function (err) { + if (err) assert.fail(err) let submod = join(subdep, 'node_modules') - t.notOk(existsSync(submod), `install did not recurse into node subdependencies at ${submod}`) - checkFolderCreation(t) - } + assert.ok(!existsSync(submod), `install did not recurse into node subdependencies at ${submod}`) + checkFolderCreation(assert) + resolve() + }) }) }) }) diff --git a/test/integration/default/shared-tests.js b/test/integration/default/shared-tests.js index 6fc59a0..acf847a 100644 --- a/test/integration/default/shared-tests.js +++ b/test/integration/default/shared-tests.js @@ -8,7 +8,8 @@ let { renameSync, writeFileSync, } = require('fs') -let test = require('tape') +const { test } = require('node:test') +const assert = require('node:assert') let { resetAndCopyShared, resetAndCopySharedCustom, @@ -26,367 +27,340 @@ let { let hydrate = require('../../..') process.env.CI = true // Suppresses tape issues with progress indicator -test('Does not exit code 1', t => { - process.on('exit', code => { if (code === 1) t.fail('Exited code 1!') }) - t.end() -}) - -test(`[Shared file copying (default paths)] shared() never uses symlinks by default`, t => { - t.plan(2) - resetAndCopyShared(t, function () { - hydrate.shared({}, function (err) { - if (err) t.fail(err) - else { +test(`[Shared file copying (default paths)] shared() never uses symlinks by default`, async () => { + await new Promise((resolve) => { + resetAndCopyShared(function () { + hydrate.shared({}, function (err) { + if (err) assert.fail(err) let path = 'src/http/get-index/node_modules/@architect/shared' let file = path + '/shared.md' let stat = lstatSync(path).isSymbolicLink() - t.notOk(stat, 'shared directory was copied, and is not a symlink') - t.equal(readFileSync(file).toString(), 'It me!', 'Copied file is readable') - } + assert.ok(!stat, 'shared directory was copied, and is not a symlink') + assert.strictEqual(readFileSync(file).toString(), 'It me!', 'Copied file is readable') + resolve() + }) }) }) }) -test(`[Shared file copying (custom paths)] shared() never uses symlinks by default`, t => { - t.plan(2) - resetAndCopySharedCustom(t, function () { - hydrate.shared({}, function (err) { - if (err) t.fail(err) - else { +test(`[Shared file copying (custom paths)] shared() never uses symlinks by default`, async () => { + await new Promise((resolve) => { + resetAndCopySharedCustom(function () { + hydrate.shared({}, function (err) { + if (err) assert.fail(err) let path = 'src/http/get-index/node_modules/@architect/shared' let file = path + '/shared.md' let stat = lstatSync(path).isSymbolicLink() - t.notOk(stat, 'shared directory was copied, and is not a symlink') - t.equal(readFileSync(file).toString(), 'It me!', 'Copied file is readable') - } + assert.ok(!stat, 'shared directory was copied, and is not a symlink') + assert.strictEqual(readFileSync(file).toString(), 'It me!', 'Copied file is readable') + resolve() + }) }) }) }) -test(`[Shared file copying (default paths)] shared() copies shared and views (unless disabled or folder not found; @views not specified)`, t => { - t.plan( - sharedArtifacts.length + - getViewsArtifacts.length + - sharedArtifactsDisabled.length + - viewsArtifactsDisabled.length + 1, - ) - resetAndCopyShared(t, function () { - hydrate.shared({}, function (err) { - if (err) t.fail(err) - else { +test(`[Shared file copying (default paths)] shared() copies shared and views (unless disabled or folder not found; @views not specified)`, async () => { + await new Promise((resolve) => { + resetAndCopyShared(function () { + hydrate.shared({}, function (err) { + if (err) assert.fail(err) // Check to see if files that are supposed to be there are actually there sharedArtifacts.forEach(path => { - t.ok(existsSync(path), `Found shared file in ${path}`) + assert.ok(existsSync(path), `Found shared file in ${path}`) }) sharedArtifactsDisabled.forEach(path => { - t.notOk(existsSync(path), `Did not find shared file in function with @arc shared false ${path}`) + assert.ok(!existsSync(path), `Did not find shared file in function with @arc shared false ${path}`) }) getViewsArtifacts.forEach(path => { if (path.includes('get-')) { - t.ok(existsSync(path), `Found views file in GET function ${path}`) + assert.ok(existsSync(path), `Found views file in GET function ${path}`) } else { - t.notOk(existsSync(path), `Did not find views file in non-GET function ${path}`) + assert.ok(!existsSync(path), `Did not find views file in non-GET function ${path}`) } }) viewsArtifactsDisabled.forEach(path => { - t.notOk(existsSync(path), `Did not find views file in function with @arc views false ${path}`) + assert.ok(!existsSync(path), `Did not find views file in function with @arc views false ${path}`) }) - checkFolderCreation(t) - } + checkFolderCreation(assert) + resolve() + }) }) }) }) -test(`[Shared file copying with plugins (default paths)] shared() copies shared and views, as well as files via plugin`, t => { - t.plan( - sharedArtifacts.length + - getViewsArtifacts.length + - sharedArtifactsDisabled.length + - viewsArtifactsDisabled.length + - pluginArtifacts.length + 1, - ) - resetAndCopySharedPlugins(t, function () { - cp(join('src', 'app.plugins'), join('.', 'app.arc'), { recursive: true, force: true }, - function (err) { - if (err) t.fail(err) - else { +test(`[Shared file copying with plugins (default paths)] shared() copies shared and views, as well as files via plugin`, async () => { + await new Promise((resolve) => { + resetAndCopySharedPlugins(function () { + cp(join('src', 'app.plugins'), join('.', 'app.arc'), { recursive: true, force: true }, + function (err) { + if (err) assert.fail(err) hydrate.shared({}, function (err) { - if (err) t.fail(err) - else { + if (err) assert.fail(err) // Check to see if files that are supposed to be there are actually there - sharedArtifacts.forEach(path => { - t.ok(existsSync(path), `Found shared file in ${path}`) - }) - sharedArtifactsDisabled.forEach(path => { - t.notOk(existsSync(path), `Did not find shared file in function with @arc shared false ${path}`) - }) - getViewsArtifacts.forEach(path => { - if (path.includes('get-')) { - t.ok(existsSync(path), `Found views file in GET function ${path}`) - } - else { - t.notOk(existsSync(path), `Did not find views file in non-GET function ${path}`) - } - }) - viewsArtifactsDisabled.forEach(path => { - t.notOk(existsSync(path), `Did not find views file in function with @arc views false ${path}`) - }) - pluginArtifacts.forEach(path => { - t.ok(existsSync(path), `Found plugin file in ${path}`) - }) - let normallyShouldNotBePresent = join('src', 'events', 'silence', 'node_modules') - t.ok(existsSync(normallyShouldNotBePresent), 'Silence event folder created just this once!') - } + sharedArtifacts.forEach(path => { + assert.ok(existsSync(path), `Found shared file in ${path}`) + }) + sharedArtifactsDisabled.forEach(path => { + assert.ok(!existsSync(path), `Did not find shared file in function with @arc shared false ${path}`) + }) + getViewsArtifacts.forEach(path => { + if (path.includes('get-')) { + assert.ok(existsSync(path), `Found views file in GET function ${path}`) + } + else { + assert.ok(!existsSync(path), `Did not find views file in non-GET function ${path}`) + } + }) + viewsArtifactsDisabled.forEach(path => { + assert.ok(!existsSync(path), `Did not find views file in function with @arc views false ${path}`) + }) + pluginArtifacts.forEach(path => { + assert.ok(existsSync(path), `Found plugin file in ${path}`) + }) + let normallyShouldNotBePresent = join('src', 'events', 'silence', 'node_modules') + assert.ok(existsSync(normallyShouldNotBePresent), 'Silence event folder created just this once!') + resolve() }) - } - }) + }) + }) }) }) -test(`[Shared file copying (custom paths)] shared() copies shared and views (unless disabled or folder not found; @views not specified)`, t => { - t.plan( - sharedArtifacts.length + - getViewsArtifacts.length + - sharedArtifactsDisabled.length + - viewsArtifactsDisabled.length + 1, - ) - resetAndCopySharedCustom(t, function () { - hydrate.shared({}, function (err) { - if (err) t.fail(err) - else { +test(`[Shared file copying (custom paths)] shared() copies shared and views (unless disabled or folder not found; @views not specified)`, async () => { + await new Promise((resolve) => { + resetAndCopySharedCustom(function () { + hydrate.shared({}, function (err) { + if (err) assert.fail(err) // Check to see if files that are supposed to be there are actually there sharedArtifacts.forEach(path => { - t.ok(existsSync(path), `Found shared file in ${path}`) + assert.ok(existsSync(path), `Found shared file in ${path}`) }) sharedArtifactsDisabled.forEach(path => { - t.notOk(existsSync(path), `Did not find shared file in function with @arc shared false ${path}`) + assert.ok(!existsSync(path), `Did not find shared file in function with @arc shared false ${path}`) }) getViewsArtifacts.forEach(path => { if (path.includes('get-')) { - t.ok(existsSync(path), `Found views file in GET function ${path}`) + assert.ok(existsSync(path), `Found views file in GET function ${path}`) } else { - t.notOk(existsSync(path), `Did not find views file in non-GET function ${path}`) + assert.ok(!existsSync(path), `Did not find views file in non-GET function ${path}`) } }) viewsArtifactsDisabled.forEach(path => { - t.notOk(existsSync(path), `Did not find views file in function with @arc views false ${path}`) + assert.ok(!existsSync(path), `Did not find views file in function with @arc views false ${path}`) }) - checkFolderCreation(t) - } + checkFolderCreation(assert) + resolve() + }) }) }) }) -test(`[Shared file copying (default paths)] shared() views to only @views (unless disabled or folder not found)`, t => { - t.plan(viewsArtifacts.length + viewsArtifactsDisabled.length + 1) - resetAndCopyShared(t, function () { - cp(join('src', 'app.arc-views'), join('.', 'app.arc'), { recursive: true, force: true }, function (err) { - if (err) t.fail(err) - else { +test(`[Shared file copying (default paths)] shared() views to only @views (unless disabled or folder not found)`, async () => { + await new Promise((resolve) => { + resetAndCopyShared(function () { + cp(join('src', 'app.arc-views'), join('.', 'app.arc'), { recursive: true, force: true }, function (err) { + if (err) assert.fail(err) hydrate.shared({}, function (err) { - if (err) t.fail(err) - else { - // Check to see if files that are supposed to be there are actually there - viewsArtifacts.forEach(path => { - if (path.includes('get-index') || path.includes('post-up-tents')) { - t.ok(existsSync(path), `Found views file in GET function ${path}`) - } - else { - t.notOk(existsSync(path), `Did not find views file in non-GET function ${path}`) - } - }) - viewsArtifactsDisabled.forEach(path => { - t.notOk(existsSync(path), `Did not find views file in function with @arc views false ${path}`) - }) - checkFolderCreation(t) - } + if (err) assert.fail(err) + // Check to see if files that are supposed to be there are actually there + viewsArtifacts.forEach(path => { + if (path.includes('get-index') || path.includes('post-up-tents')) { + assert.ok(existsSync(path), `Found views file in GET function ${path}`) + } + else { + assert.ok(!existsSync(path), `Did not find views file in non-GET function ${path}`) + } + }) + viewsArtifactsDisabled.forEach(path => { + assert.ok(!existsSync(path), `Did not find views file in function with @arc views false ${path}`) + }) + checkFolderCreation(assert) + resolve() }) - } + }) }) }) }) -test(`[Shared file copying (custom paths)] shared() views to only @views (unless disabled or folder not found)`, t => { - t.plan(viewsArtifacts.length + viewsArtifactsDisabled.length + 1) - resetAndCopySharedCustom(t, function () { - cp(join('_shared-custom', 'app.arc-views'), join('.', 'app.arc'), { recursive: true, force: true }, function (err) { - if (err) t.fail(err) - else { +test(`[Shared file copying (custom paths)] shared() views to only @views (unless disabled or folder not found)`, async () => { + await new Promise((resolve) => { + resetAndCopySharedCustom(function () { + cp(join('_shared-custom', 'app.arc-views'), join('.', 'app.arc'), { recursive: true, force: true }, function (err) { + if (err) assert.fail(err) hydrate.shared({}, function (err) { - if (err) t.fail(err) - else { - // Check to see if files that are supposed to be there are actually there - viewsArtifacts.forEach(path => { - if (path.includes('get-index') || path.includes('post-up-tents')) { - t.ok(existsSync(path), `Found views file in GET function ${path}`) - } - else { - t.notOk(existsSync(path), `Did not find views file in non-GET function ${path}`) - } - }) - viewsArtifactsDisabled.forEach(path => { - t.notOk(existsSync(path), `Did not find views file in function with @arc views false ${path}`) - }) - checkFolderCreation(t) - } + if (err) assert.fail(err) + // Check to see if files that are supposed to be there are actually there + viewsArtifacts.forEach(path => { + if (path.includes('get-index') || path.includes('post-up-tents')) { + assert.ok(existsSync(path), `Found views file in GET function ${path}`) + } + else { + assert.ok(!existsSync(path), `Did not find views file in non-GET function ${path}`) + } + }) + viewsArtifactsDisabled.forEach(path => { + assert.ok(!existsSync(path), `Did not find views file in function with @arc views false ${path}`) + }) + checkFolderCreation(assert) + resolve() }) - } + }) }) }) }) -test(`[Shared file copying (default paths)] shared() copies static.json but not app.arc (Arc v6+)`, t => { - t.plan(arcFileArtifacts.length + staticArtifacts.length + 1) - resetAndCopyShared(t, function () { - hydrate.shared({}, function (err) { - if (err) t.fail(err) - else { +test(`[Shared file copying (default paths)] shared() copies static.json but not app.arc (Arc v6+)`, async () => { + await new Promise((resolve) => { + resetAndCopyShared(function () { + hydrate.shared({}, function (err) { + if (err) assert.fail(err) // Check to see if files that are supposed to be there are actually there arcFileArtifacts.forEach(path => { - t.notOk(existsSync(path), `Did not find app.arc file in ${path}`) + assert.ok(!existsSync(path), `Did not find app.arc file in ${path}`) }) staticArtifacts.forEach(path => { - t.ok(existsSync(path), `Found static.json file in ${path}`) + assert.ok(existsSync(path), `Found static.json file in ${path}`) }) - checkFolderCreation(t) - } + checkFolderCreation(assert) + resolve() + }) }) }) }) -test(`[Shared file copying (custom paths)] shared() copies static.json but not app.arc (Arc v6+)`, t => { - t.plan(arcFileArtifacts.length + staticArtifacts.length + 1) - resetAndCopySharedCustom(t, function () { - hydrate.shared({}, function (err) { - if (err) t.fail(err) - else { +test(`[Shared file copying (custom paths)] shared() copies static.json but not app.arc (Arc v6+)`, async () => { + await new Promise((resolve) => { + resetAndCopySharedCustom(function () { + hydrate.shared({}, function (err) { + if (err) assert.fail(err) // Check to see if files that are supposed to be there are actually there arcFileArtifacts.forEach(path => { - t.notOk(existsSync(path), `Did not find app.arc file in ${path}`) + assert.ok(!existsSync(path), `Did not find app.arc file in ${path}`) }) staticArtifacts.forEach(path => { - t.ok(existsSync(path), `Found static.json file in ${path}`) + assert.ok(existsSync(path), `Found static.json file in ${path}`) }) - checkFolderCreation(t) - } + checkFolderCreation(assert) + resolve() + }) }) }) }) -test(`[Shared file copying (default paths)] shared() copies static.json with @static folder configured`, t => { - t.plan(staticArtifacts.length + 3) - resetAndCopyShared(t, function () { - // Rewrite app.arc to include @static folder directive - let arcFile = join(process.cwd(), 'app.arc') - let arc = readFileSync(arcFile).toString() - arc += '@static\nfolder foo' - writeFileSync(arcFile, arc) - t.pass(`Added '@static folder foo' to app.arc`) - // Move public/ to foo/ - renameSync(join(process.cwd(), 'public'), join(process.cwd(), 'foo')) - t.ok(existsSync(join(process.cwd(), 'foo', 'static.json')), 'public/static.json moved into foo/static.json') - hydrate.shared({}, function (err) { - if (err) t.fail(err) - else { +test(`[Shared file copying (default paths)] shared() copies static.json with @static folder configured`, async () => { + await new Promise((resolve) => { + resetAndCopyShared(function () { + // Rewrite app.arc to include @static folder directive + let arcFile = join(process.cwd(), 'app.arc') + let arc = readFileSync(arcFile).toString() + arc += '@static\nfolder foo' + writeFileSync(arcFile, arc) + assert.ok(true, `Added '@static folder foo' to app.arc`) + // Move public/ to foo/ + renameSync(join(process.cwd(), 'public'), join(process.cwd(), 'foo')) + assert.ok(existsSync(join(process.cwd(), 'foo', 'static.json')), 'public/static.json moved into foo/static.json') + hydrate.shared({}, function (err) { + if (err) assert.fail(err) // Check to see if files that are supposed to be there are actually there staticArtifacts.forEach(path => { - t.ok(existsSync(path), `Found static.json file in ${path}`) + assert.ok(existsSync(path), `Found static.json file in ${path}`) }) - checkFolderCreation(t) - } + checkFolderCreation(assert) + resolve() + }) }) }) }) -test(`[Shared file copying (custom paths)] shared() copies static.json with @static folder configured`, t => { - t.plan(staticArtifacts.length + 3) - resetAndCopySharedCustom(t, function () { - // Rewrite app.arc to include @static folder directive - let arcFile = join(process.cwd(), 'app.arc') - let arc = readFileSync(arcFile).toString() - arc += '@static\nfolder foo' - writeFileSync(arcFile, arc) - t.pass(`Added '@static folder foo' to app.arc`) - // Move public/ to foo/ - renameSync(join(process.cwd(), 'public'), join(process.cwd(), 'foo')) - t.ok(existsSync(join(process.cwd(), 'foo', 'static.json')), 'public/static.json moved into foo/static.json') - hydrate.shared({}, function (err) { - if (err) t.fail(err) - else { +test(`[Shared file copying (custom paths)] shared() copies static.json with @static folder configured`, async () => { + await new Promise((resolve) => { + resetAndCopySharedCustom(function () { + // Rewrite app.arc to include @static folder directive + let arcFile = join(process.cwd(), 'app.arc') + let arc = readFileSync(arcFile).toString() + arc += '@static\nfolder foo' + writeFileSync(arcFile, arc) + assert.ok(true, `Added '@static folder foo' to app.arc`) + // Move public/ to foo/ + renameSync(join(process.cwd(), 'public'), join(process.cwd(), 'foo')) + assert.ok(existsSync(join(process.cwd(), 'foo', 'static.json')), 'public/static.json moved into foo/static.json') + hydrate.shared({}, function (err) { + if (err) assert.fail(err) // Check to see if files that are supposed to be there are actually there staticArtifacts.forEach(path => { - t.ok(existsSync(path), `Found static.json file in ${path}`) + assert.ok(existsSync(path), `Found static.json file in ${path}`) }) - checkFolderCreation(t) - } + checkFolderCreation(assert) + resolve() + }) }) }) }) -test(`[Shared file copying (default paths)] shared() should remove files in functions that do not exist in shared and views`, t => { - t.plan(sharedArtifacts.length + getViewsArtifacts.length + 1) - resetAndCopyShared(t, function () { - let sharedStragglers = sharedArtifacts.map((p) => { - let dir = dirname(p) - mkdirSync(dir, { recursive: true }) - let file = join(dir, 'straggler.json') - writeFileSync(file, '{surprise:true}') - return file - }) - let viewsStragglers = getViewsArtifacts.map((p) => { - let dir = dirname(p) - mkdirSync(dir, { recursive: true }) - let file = join(dir, 'straggler.json') - writeFileSync(file, '{surprise:true}') - return file - }) - hydrate.shared({}, function (err) { - if (err) t.fail(err) - else { +test(`[Shared file copying (default paths)] shared() should remove files in functions that do not exist in shared and views`, async () => { + await new Promise((resolve) => { + resetAndCopyShared(function () { + let sharedStragglers = sharedArtifacts.map((p) => { + let dir = dirname(p) + mkdirSync(dir, { recursive: true }) + let file = join(dir, 'straggler.json') + writeFileSync(file, '{surprise:true}') + return file + }) + let viewsStragglers = getViewsArtifacts.map((p) => { + let dir = dirname(p) + mkdirSync(dir, { recursive: true }) + let file = join(dir, 'straggler.json') + writeFileSync(file, '{surprise:true}') + return file + }) + hydrate.shared({}, function (err) { + if (err) assert.fail(err) // Check to see if files that are supposed to be there are actually there sharedStragglers.forEach(path => { - t.notOk(existsSync(path), `shared straggler file removed from ${path}`) + assert.ok(!existsSync(path), `shared straggler file removed from ${path}`) }) viewsStragglers.forEach(path => { - t.notOk(existsSync(path), `views straggler file removed from ${path}`) + assert.ok(!existsSync(path), `views straggler file removed from ${path}`) }) - checkFolderCreation(t) - } + checkFolderCreation(assert) + resolve() + }) }) }) }) -test(`[Shared file copying (custom paths)] shared() should remove files in functions that do not exist in shared and views`, t => { - t.plan(sharedArtifacts.length + getViewsArtifacts.length + 1) - resetAndCopySharedCustom(t, function () { - let sharedStragglers = sharedArtifacts.map((p) => { - let dir = dirname(p) - mkdirSync(dir, { recursive: true }) - let file = join(dir, 'straggler.json') - writeFileSync(file, '{surprise:true}') - return file - }) - let viewsStragglers = getViewsArtifacts.map((p) => { - let dir = dirname(p) - mkdirSync(dir, { recursive: true }) - let file = join(dir, 'straggler.json') - writeFileSync(file, '{surprise:true}') - return file - }) - hydrate.shared({}, function (err) { - if (err) t.fail(err) - else { +test(`[Shared file copying (custom paths)] shared() should remove files in functions that do not exist in shared and views`, async () => { + await new Promise((resolve) => { + resetAndCopySharedCustom(function () { + let sharedStragglers = sharedArtifacts.map((p) => { + let dir = dirname(p) + mkdirSync(dir, { recursive: true }) + let file = join(dir, 'straggler.json') + writeFileSync(file, '{surprise:true}') + return file + }) + let viewsStragglers = getViewsArtifacts.map((p) => { + let dir = dirname(p) + mkdirSync(dir, { recursive: true }) + let file = join(dir, 'straggler.json') + writeFileSync(file, '{surprise:true}') + return file + }) + hydrate.shared({}, function (err) { + if (err) assert.fail(err) // Check to see if files that are supposed to be there are actually there sharedStragglers.forEach(path => { - t.notOk(existsSync(path), `shared straggler file removed from ${path}`) + assert.ok(!existsSync(path), `shared straggler file removed from ${path}`) }) viewsStragglers.forEach(path => { - t.notOk(existsSync(path), `views straggler file removed from ${path}`) + assert.ok(!existsSync(path), `views straggler file removed from ${path}`) }) - checkFolderCreation(t) - } + checkFolderCreation(assert) + resolve() + }) }) }) }) diff --git a/test/integration/default/update-tests.js b/test/integration/default/update-tests.js index 6e79ef5..f600ff1 100644 --- a/test/integration/default/update-tests.js +++ b/test/integration/default/update-tests.js @@ -1,6 +1,7 @@ +const { test } = require('node:test') +const assert = require('node:assert') let { join } = require('path') let { readFileSync } = require('fs') -let test = require('tape') let { reset, checkFolderCreation, @@ -11,34 +12,29 @@ let { let hydrate = require('../../..') process.env.CI = true // Suppresses tape issues with progress indicator -test('Does not exit code 1', t => { - process.on('exit', code => { if (code === 1) t.fail('Exited code 1!') }) - t.end() -}) - -test(`[Default (file copying)] update() bumps installed dependencies to newer versions`, t => { - t.plan(4) - reset(t, function () { - // TODO: pip requires manual locking (via two requirements.txt files) so - // we dont test update w/ python - hydrate.update(undefined, function (err) { - if (err) t.fail(err) - else { +test(`[Default (file copying)] update() bumps installed dependencies to newer versions`, async () => { + await new Promise((resolve) => { + reset(function () { + // TODO: pip requires manual locking (via two requirements.txt files) so + // we dont test update w/ python + hydrate.update(undefined, function (err) { + if (err) assert.fail(err) let pkgLock = JSON.parse(readFileSync(join(mockTmp, nodeFunctions[0], 'package-lock.json'))) let newVersion = [ 2, 3 ].includes(pkgLock.lockfileVersion) ? pkgLock.packages['node_modules/tiny-json-http'].version : pkgLock.dependencies['tiny-json-http'].version - t.notEqual(newVersion, '7.0.2', `get-index tiny-json-http bumped to ${newVersion} from 7.0.2`) + assert.notStrictEqual(newVersion, '7.0.2', `get-index tiny-json-http bumped to ${newVersion} from 7.0.2`) let yarnLock = readFileSync(join(mockTmp, nodeFunctions[2], 'yarn.lock'), 'utf-8') let newYarn = yarnLock.split('\n').filter(t => t.includes(' version "'))[0].split(' version "')[1].replace('"', '') - t.notEqual(newYarn, '7.0.2', `put-on_your_boots tiny-json-http bumped to ${newVersion} from 7.0.2`) + assert.notStrictEqual(newYarn, '7.0.2', `put-on_your_boots tiny-json-http bumped to ${newVersion} from 7.0.2`) let gemfileLock = readFileSync(join(mockTmp, rubyFunctions[0], 'Gemfile.lock'), 'utf-8') let newGem = gemfileLock.split('\n').filter(t => t.includes('a (0'))[0].split('(')[1].split(')')[0] - t.notEqual(newGem, '0.2.1', `delete-badness_in_life 'a' gem bumped to ${newGem} from 0.2.1`) - checkFolderCreation(t) - } + assert.notStrictEqual(newGem, '0.2.1', `delete-badness_in_life 'a' gem bumped to ${newGem} from 0.2.1`) + checkFolderCreation(assert) + resolve() + }) }) }) }) diff --git a/test/integration/failure-tests.js b/test/integration/failure-tests.js index 11a7c23..c5301a6 100644 --- a/test/integration/failure-tests.js +++ b/test/integration/failure-tests.js @@ -1,4 +1,5 @@ -let test = require('tape') +const { test } = require('node:test') +const assert = require('node:assert') let { join } = require('path') let { unlinkSync, writeFileSync } = require('fs') let { reset } = require('./_shared') @@ -13,90 +14,102 @@ let { let npmVer = execSync('npm --version').toString() -test('Corrupt package-lock.json fails hydrate.install', t => { - t.plan(1) - reset(t, function () { - // Make a funky package-lock file - let corruptPackage = 'ohayo gozaimasu!' - writeFileSync(join(nodeFunctions[0], 'package-lock.json'), corruptPackage) - let basepath = nodeFunctions[0] - hydrate.install({ basepath }, function done (err) { - if (err) t.pass(`Successfully errored: ${err}`) - else t.fail('Hydration did not fail') +test('Corrupt package-lock.json fails hydrate.install', async () => { + await new Promise((resolve) => { + reset(function () { + // Make a funky package-lock file + let corruptPackage = 'ohayo gozaimasu!' + writeFileSync(join(nodeFunctions[0], 'package-lock.json'), corruptPackage) + let basepath = nodeFunctions[0] + hydrate.install({ basepath }, function done (err) { + if (err) assert.ok(true, `Successfully errored: ${err}`) + else assert.fail('Hydration did not fail') + resolve() + }) }) }) }) -test('Corrupt package-lock.json may or may not fail hydrate.update (depending on npm version)', t => { - t.plan(1) - reset(t, function () { - // Make a funky package-lock file - let corruptPackage = 'ohayo gozaimasu!' - writeFileSync(join(nodeFunctions[0], 'package-lock.json'), corruptPackage) - let basepath = nodeFunctions[0] - hydrate.update({ basepath }, function done (err) { - if (Number(npmVer.split('.')[0]) >= 7) { - if (err) t.fail(err) - else t.pass('Hydration did not fail in npm 7.x') - } - else { - if (err) t.pass(`Successfully errored: ${err}`) - else t.fail('Hydration did not fail') - } +test('Corrupt package-lock.json may or may not fail hydrate.update (depending on npm version)', async () => { + await new Promise((resolve) => { + reset(function () { + // Make a funky package-lock file + let corruptPackage = 'ohayo gozaimasu!' + writeFileSync(join(nodeFunctions[0], 'package-lock.json'), corruptPackage) + let basepath = nodeFunctions[0] + hydrate.update({ basepath }, function done (err) { + if (Number(npmVer.split('.')[0]) >= 7) { + if (err) assert.fail(err) + else assert.ok(true, 'Hydration did not fail in npm 7.x') + } + else { + if (err) assert.ok(true, `Successfully errored: ${err}`) + else assert.fail('Hydration did not fail') + } + resolve() + }) }) }) }) -test('Corrupt Gemfile fails hydrate.install', t => { - t.plan(1) - reset(t, function () { - let corruptPackage = 'ohayo gozaimasu!' - unlinkSync(join(rubyFunctions[0], 'Gemfile.lock')) - writeFileSync(join(rubyFunctions[0], 'Gemfile'), corruptPackage) - let basepath = rubyFunctions[0] - hydrate.install({ basepath }, function done (err) { - if (err) t.pass(`Successfully errored: ${err}`) - else t.fail('Hydration did not fail') +test('Corrupt Gemfile fails hydrate.install', async () => { + await new Promise((resolve) => { + reset(function () { + let corruptPackage = 'ohayo gozaimasu!' + unlinkSync(join(rubyFunctions[0], 'Gemfile.lock')) + writeFileSync(join(rubyFunctions[0], 'Gemfile'), corruptPackage) + let basepath = rubyFunctions[0] + hydrate.install({ basepath }, function done (err) { + if (err) assert.ok(true, `Successfully errored: ${err}`) + else assert.fail('Hydration did not fail') + resolve() + }) }) }) }) -test('Corrupt Gemfile fails hydrate.update', t => { - t.plan(1) - reset(t, function () { - let corruptPackage = 'ohayo gozaimasu!' - unlinkSync(join(rubyFunctions[0], 'Gemfile.lock')) - writeFileSync(join(rubyFunctions[0], 'Gemfile'), corruptPackage) - let basepath = rubyFunctions[0] - hydrate.update({ basepath }, function done (err) { - if (err) t.pass(`Successfully errored: ${err}`) - else t.fail('Hydration did not fail') +test('Corrupt Gemfile fails hydrate.update', async () => { + await new Promise((resolve) => { + reset(function () { + let corruptPackage = 'ohayo gozaimasu!' + unlinkSync(join(rubyFunctions[0], 'Gemfile.lock')) + writeFileSync(join(rubyFunctions[0], 'Gemfile'), corruptPackage) + let basepath = rubyFunctions[0] + hydrate.update({ basepath }, function done (err) { + if (err) assert.ok(true, `Successfully errored: ${err}`) + else assert.fail('Hydration did not fail') + resolve() + }) }) }) }) -test('Corrupt requirements.txt fails hydrate.install', t => { - t.plan(1) - reset(t, function () { - let corruptPackage = 'ohayo gozaimasu!' - writeFileSync(join(pythonFunctions[0], 'requirements.txt'), corruptPackage) - let basepath = pythonFunctions[0] - hydrate.install({ basepath, installing: true }, function done (err) { - if (err) t.pass(`Successfully errored: ${err}`) - else t.fail('Hydration did not fail') +test('Corrupt requirements.txt fails hydrate.install', async () => { + await new Promise((resolve) => { + reset(function () { + let corruptPackage = 'ohayo gozaimasu!' + writeFileSync(join(pythonFunctions[0], 'requirements.txt'), corruptPackage) + let basepath = pythonFunctions[0] + hydrate.install({ basepath, installing: true }, function done (err) { + if (err) assert.ok(true, `Successfully errored: ${err}`) + else assert.fail('Hydration did not fail') + resolve() + }) }) }) }) -test('Corrupt requirements.txt fails hydrate.update', t => { - t.plan(1) - reset(t, function () { - let corruptPackage = 'ohayo gozaimasu!' - writeFileSync(join(pythonFunctions[0], 'requirements.txt'), corruptPackage) - let basepath = pythonFunctions[0] - hydrate.update({ basepath, installing: false }, function done (err) { - if (err) t.pass(`Successfully errored: ${err}`) - else t.fail('Hydration did not fail') +test('Corrupt requirements.txt fails hydrate.update', async () => { + await new Promise((resolve) => { + reset(function () { + let corruptPackage = 'ohayo gozaimasu!' + writeFileSync(join(pythonFunctions[0], 'requirements.txt'), corruptPackage) + let basepath = pythonFunctions[0] + hydrate.update({ basepath, installing: false }, function done (err) { + if (err) assert.ok(true, `Successfully errored: ${err}`) + else assert.fail('Hydration did not fail') + resolve() + }) }) }) }) diff --git a/test/integration/symlink/install-tests.js b/test/integration/symlink/install-tests.js index d2cdf8f..366d57a 100644 --- a/test/integration/symlink/install-tests.js +++ b/test/integration/symlink/install-tests.js @@ -5,7 +5,8 @@ let { readFileSync, writeFileSync, } = require('fs') -let test = require('tape') +const { test } = require('node:test') +const assert = require('node:assert') let { reset, resetAndCopyShared, @@ -33,89 +34,73 @@ let hydrate = require('../../..') process.env.CI = true // Suppresses tape issues with progress indicator let symlink = true -test('Does not exit code 1', t => { - process.on('exit', code => { if (code === 1) t.fail('Exited code 1!') }) - t.end() -}) - // As of late 2020, this test passes GHCI in both windows-latest and windows-2016 // This is strange, bc windows-2016 should be running a pre-Windows-symlink build (10.0.14393 Build 3930) // See: https://blogs.windows.com/windowsdeveloper/2016/12/02/symlinks-windows-10/ -test(`[Symlinking] install() with symlink hydrates all Functions', shared and views dependencies (autoinstall enabled)`, t => { - let count = - pythonDependencies.length + - rubyDependencies().length + - nodeDependencies.length + - pythonSharedDependencies.length + - pythonViewsDependencies.length + - rubySharedDependencies.length + - rubyViewsDependencies.length + - nodeSharedDependencies.length + - nodeViewsDependencies.length + 7 - t.plan(count) - resetAndCopyShared(t, function () { - hydrate.install({ symlink, autoinstall: true }, function (err) { - if (err) t.fail(err) - else { +test(`[Symlinking] install() with symlink hydrates all Functions', shared and views dependencies (autoinstall enabled)`, async () => { + await new Promise((resolve) => { + resetAndCopyShared(function () { + hydrate.install({ symlink, autoinstall: true }, function (err) { + if (err) assert.fail(err) pythonDependencies.forEach(p => { - t.ok(existsSync(p), `python dependency exists at ${p}`) + assert.ok(existsSync(p), `python dependency exists at ${p}`) }) rubyDependencies().forEach(p => { - t.ok(existsSync(p), `ruby dependency exists at ${p}`) + assert.ok(existsSync(p), `ruby dependency exists at ${p}`) }) nodeDependencies.forEach(p => { - t.ok(existsSync(p), `node dependency exists at ${p}`) + assert.ok(existsSync(p), `node dependency exists at ${p}`) }) pythonSharedDependencies.forEach(p => { - t.ok(existsSync(p), `python shared dependency exists at ${p}`) + assert.ok(existsSync(p), `python shared dependency exists at ${p}`) }) rubySharedDependencies.forEach(p => { - t.ok(existsSync(p), `ruby shared dependency exists at ${p}`) + assert.ok(existsSync(p), `ruby shared dependency exists at ${p}`) }) nodeSharedDependencies.forEach(p => { - t.ok(existsSync(p), `node shared dependency exists at ${p}`) + assert.ok(existsSync(p), `node shared dependency exists at ${p}`) }) pythonViewsDependencies.forEach(p => { - t.ok(existsSync(p), `python views dependency exists at ${p}`) + assert.ok(existsSync(p), `python views dependency exists at ${p}`) }) rubyViewsDependencies.forEach(p => { - t.ok(existsSync(p), `ruby views dependency exists at ${p}`) + assert.ok(existsSync(p), `ruby views dependency exists at ${p}`) }) nodeViewsDependencies.forEach(p => { - t.ok(existsSync(p), `node views dependency exists at ${p}`) + assert.ok(existsSync(p), `node views dependency exists at ${p}`) }) // Autoinstall-specific tests let package = join(arcAutoinstall[0], 'node_modules', '_arc-autoinstall', 'package.json') - t.ok(existsSync(package), 'Found autoinstall package.json') + assert.ok(existsSync(package), 'Found autoinstall package.json') let requirements = join(arcAutoinstall[1], 'vendor', '_arc_autoinstall', 'requirements.txt') - t.ok(existsSync(requirements), 'Found autoinstall requirements.txt') + assert.ok(existsSync(requirements), 'Found autoinstall requirements.txt') // Yarn-specific tests let yarnFunction = join(mockTmp, 'src', 'http', 'put-on_your_boots') let yarnIntFile = join(yarnFunction, 'node_modules', '.yarn-integrity') let pkgLockFile = join(yarnFunction, 'package-lock.json') - t.ok(existsSync(yarnIntFile), 'Found yarn integrity file') - t.notOk(existsSync(pkgLockFile), `Did not find package-lock.json (i.e. npm didn't run)`) + assert.ok(existsSync(yarnIntFile), 'Found yarn integrity file') + assert.ok(!existsSync(pkgLockFile), `Did not find package-lock.json (i.e. npm didn't run)`) // pnpm-specific tests let pnpmFunction = join(mockTmp, 'src', 'http', 'options-are_plentiful') let pnpmIntFile = join(pnpmFunction, 'node_modules', '.modules.yaml') pkgLockFile = join(pnpmFunction, 'package-lock.json') - t.ok(existsSync(pnpmIntFile), 'Found pnpm integrity file') - t.notOk(existsSync(pkgLockFile), `Did not find package-lock.json (i.e. npm didn't run)`) - checkFolderCreation(t) - } + assert.ok(existsSync(pnpmIntFile), 'Found pnpm integrity file') + assert.ok(!existsSync(pkgLockFile), `Did not find package-lock.json (i.e. npm didn't run)`) + checkFolderCreation(assert) + resolve() + }) }) }) }) -test(`[Symlinking] install() hydrates all Functions', shared and views dependencies (autoinstall enabled, no package files in shared)`, t => { - t.plan(7) - resetAndCopySharedAutoinstall(t, function () { - hydrate.install({ symlink, autoinstall: true }, function (err) { - if (err) t.fail(err) - else { +test(`[Symlinking] install() hydrates all Functions', shared and views dependencies (autoinstall enabled, no package files in shared)`, async () => { + await new Promise((resolve) => { + resetAndCopySharedAutoinstall(function () { + hydrate.install({ symlink, autoinstall: true }, function (err) { + if (err) assert.fail(err) // Autoinstall-specific tests let package = join(arcAutoinstall[0], 'node_modules', '_arc-autoinstall', 'package.json') - t.ok(existsSync(package), 'Found autoinstall package.json') + assert.ok(existsSync(package), 'Found autoinstall package.json') let autoinstall = JSON.parse(readFileSync(package)) let _parsed = [ 'index.js', @@ -127,154 +112,155 @@ test(`[Symlinking] install() hydrates all Functions', shared and views dependenc 'run-series': 'latest', 'tiny-json-http': 'latest', } - t.deepEqual(autoinstall._parsed, _parsed, 'Autoinstall walked shared + views') - t.deepEqual(autoinstall.dependencies, dependencies, 'Autoinstall installed shared + views deps') + assert.deepStrictEqual(autoinstall._parsed, _parsed, 'Autoinstall walked shared + views') + assert.deepStrictEqual(autoinstall.dependencies, dependencies, 'Autoinstall installed shared + views deps') // Check to see if files that are supposed to be there are actually there - t.ok(existsSync(nodeDependencies[1]), `scoped install for ${nodeFunctions[0]} installed dependencies in ${nodeDependencies[1]}`) + assert.ok(existsSync(nodeDependencies[1]), `scoped install for ${nodeFunctions[0]} installed dependencies in ${nodeDependencies[1]}`) let path = join(arcHttp[2], 'node_modules') let sharedDep = join(path, 'cpr') let viewsDep = join(path, 'run-series') - t.ok(existsSync(sharedDep), 'Autoinstalled shared dependency') - t.ok(existsSync(viewsDep), 'Autoinstalled views dependency') - checkFolderCreation(t) - } + assert.ok(existsSync(sharedDep), 'Autoinstalled shared dependency') + assert.ok(existsSync(viewsDep), 'Autoinstalled views dependency') + checkFolderCreation(assert) + resolve() + }) }) }) }) -test(`[Symlinking] install (specific path / single path) hydrates only Functions found in the specified subpath`, t => { - t.plan(8) - resetAndCopyShared(t, function () { - let basepath = nodeFunctions[0] - hydrate.install({ basepath, symlink }, function (err) { - if (err) t.fail(err) - else { +test(`[Symlinking] install (specific path / single path) hydrates only Functions found in the specified subpath`, async () => { + await new Promise((resolve) => { + resetAndCopyShared(function () { + let basepath = nodeFunctions[0] + hydrate.install({ basepath, symlink }, function (err) { + if (err) assert.fail(err) // Check to see if files that are supposed to be there are actually there - t.ok(existsSync(nodeDependencies[0]), `scoped install for ${nodeFunctions[0]} installed dependencies in ${nodeDependencies[0]}`) - t.notOk(existsSync(pythonDependencies[0]), `scoped install did not install dependencies for unspecified function at ${pythonDependencies[0]}`) + assert.ok(existsSync(nodeDependencies[0]), `scoped install for ${nodeFunctions[0]} installed dependencies in ${nodeDependencies[0]}`) + assert.ok(!existsSync(pythonDependencies[0]), `scoped install did not install dependencies for unspecified function at ${pythonDependencies[0]}`) let arcFileArtifact = arcFileArtifacts.find(p => p.startsWith(arcHttp[0])) let sharedArtifact = sharedArtifacts.find(p => p.startsWith(arcHttp[0])) let viewsArtifact = viewsArtifacts.find(p => p.startsWith(arcHttp[0])) - t.ok(existsSync(nodeSharedDependencies[0]), `node shared dependency exists at ${nodeSharedDependencies[0]}`) - t.ok(existsSync(nodeViewsDependencies[0]), `node views dependency exists at ${nodeViewsDependencies[0]}`) - t.notOk(existsSync(arcFileArtifact), `arc file does not exist at ${arcFileArtifact}`) - t.ok(existsSync(sharedArtifact), `shared file artifact exists at ${sharedArtifact}`) - t.ok(existsSync(viewsArtifact), `shared file artifact exists at ${viewsArtifact}`) - checkFolderCreation(t) - } + assert.ok(existsSync(nodeSharedDependencies[0]), `node shared dependency exists at ${nodeSharedDependencies[0]}`) + assert.ok(existsSync(nodeViewsDependencies[0]), `node views dependency exists at ${nodeViewsDependencies[0]}`) + assert.ok(!existsSync(arcFileArtifact), `arc file does not exist at ${arcFileArtifact}`) + assert.ok(existsSync(sharedArtifact), `shared file artifact exists at ${sharedArtifact}`) + assert.ok(existsSync(viewsArtifact), `shared file artifact exists at ${viewsArtifact}`) + checkFolderCreation(assert) + resolve() + }) }) }) }) -test(`[Symlinking] install (specific path / single path) in a manifest-free Node.js function adds missing deps with autoinstall enabled`, t => { - t.plan(7) - resetAndCopyShared(t, function () { - let basepath = nodeFunctions[1] - hydrate.install({ basepath, symlink, autoinstall: true }, function (err) { - if (err) t.fail(err) - else { +test(`[Symlinking] install (specific path / single path) in a manifest-free Node.js function adds missing deps with autoinstall enabled`, async () => { + await new Promise((resolve) => { + resetAndCopyShared(function () { + let basepath = nodeFunctions[1] + hydrate.install({ basepath, symlink, autoinstall: true }, function (err) { + if (err) assert.fail(err) // Check to see if files that are supposed to be there are actually there - t.ok(existsSync(nodeDependencies[1]), `scoped install for ${nodeFunctions[1]} installed dependencies in ${nodeDependencies[1]}`) - t.notOk(existsSync(pythonDependencies[0]), `scoped install did not install dependencies for unspecified function at ${pythonDependencies[0]}`) + assert.ok(existsSync(nodeDependencies[1]), `scoped install for ${nodeFunctions[1]} installed dependencies in ${nodeDependencies[1]}`) + assert.ok(!existsSync(pythonDependencies[0]), `scoped install did not install dependencies for unspecified function at ${pythonDependencies[0]}`) let arcFileArtifact = arcFileArtifacts.find(p => p.startsWith(arcAutoinstall[0])) let sharedArtifact = sharedArtifacts.find(p => p.startsWith(arcAutoinstall[0])) let viewsArtifact = viewsArtifacts.find(p => p.startsWith(arcAutoinstall[0])) - t.ok(existsSync(nodeSharedDependencies[1]), `node shared dependency exists at ${nodeSharedDependencies[1]}`) - t.notOk(existsSync(arcFileArtifact), `arc file does not exist at ${arcFileArtifact}`) - t.ok(existsSync(sharedArtifact), `shared file artifact exists at ${sharedArtifact}`) - t.notOk(existsSync(viewsArtifact), `shared file artifact exists at ${viewsArtifact}`) - checkFolderCreation(t) - } + assert.ok(existsSync(nodeSharedDependencies[1]), `node shared dependency exists at ${nodeSharedDependencies[1]}`) + assert.ok(!existsSync(arcFileArtifact), `arc file does not exist at ${arcFileArtifact}`) + assert.ok(existsSync(sharedArtifact), `shared file artifact exists at ${sharedArtifact}`) + assert.ok(!existsSync(viewsArtifact), `shared file artifact exists at ${viewsArtifact}`) + checkFolderCreation(assert) + resolve() + }) }) }) }) -test(`[Default (file copying)] install (specific path / single path) in a manifest-free Python function adds missing deps with autoinstall enabled`, t => { - t.plan(7) - resetAndCopyShared(t, function () { - let basepath = pythonFunctions[1] - hydrate.install({ basepath, symlink, autoinstall: true }, function (err) { - if (err) t.fail(err) - else { +test(`[Default (file copying)] install (specific path / single path) in a manifest-free Python function adds missing deps with autoinstall enabled`, async () => { + await new Promise((resolve) => { + resetAndCopyShared(function () { + let basepath = pythonFunctions[1] + hydrate.install({ basepath, symlink, autoinstall: true }, function (err) { + if (err) assert.fail(err) // Check to see if files that are supposed to be there are actually there - t.ok(existsSync(pythonDependencies[1]), `scoped install for ${pythonFunctions[1]} installed dependencies in ${pythonDependencies[1]}`) - t.notOk(existsSync(nodeDependencies[0]), `scoped install did not install dependencies for unspecified function at ${nodeDependencies[0]}`) + assert.ok(existsSync(pythonDependencies[1]), `scoped install for ${pythonFunctions[1]} installed dependencies in ${pythonDependencies[1]}`) + assert.ok(!existsSync(nodeDependencies[0]), `scoped install did not install dependencies for unspecified function at ${nodeDependencies[0]}`) let arcFileArtifact = arcFileArtifacts.find(p => p.startsWith(arcAutoinstall[0])) let sharedArtifact = sharedArtifacts.find(p => p.startsWith(arcAutoinstall[0])) let viewsArtifact = viewsArtifacts.find(p => p.startsWith(arcAutoinstall[0])) - t.ok(existsSync(pythonSharedDependencies[1]), `python shared dependency exists at ${pythonSharedDependencies[1]}`) - t.notOk(existsSync(arcFileArtifact), `arc file does not exist at ${arcFileArtifact}`) - t.ok(existsSync(sharedArtifact), `shared file artifact exists at ${sharedArtifact}`) - t.notOk(existsSync(viewsArtifact), `shared file artifact exists at ${viewsArtifact}`) - checkFolderCreation(t) - } + assert.ok(existsSync(pythonSharedDependencies[1]), `python shared dependency exists at ${pythonSharedDependencies[1]}`) + assert.ok(!existsSync(arcFileArtifact), `arc file does not exist at ${arcFileArtifact}`) + assert.ok(existsSync(sharedArtifact), `shared file artifact exists at ${sharedArtifact}`) + assert.ok(!existsSync(viewsArtifact), `shared file artifact exists at ${viewsArtifact}`) + checkFolderCreation(assert) + resolve() + }) }) }) }) -test(`[Default (file copying)] install (specific path / single path) in a manifest-free Python function does not add missing deps with autoinstall disabled`, t => { - t.plan(7) - resetAndCopyShared(t, function () { - let basepath = pythonFunctions[1] - hydrate.install({ basepath, autoinstall: false }, function (err) { - if (err) t.fail(err) - else { +test(`[Default (file copying)] install (specific path / single path) in a manifest-free Python function does not add missing deps with autoinstall disabled`, async () => { + await new Promise((resolve) => { + resetAndCopyShared(function () { + let basepath = pythonFunctions[1] + hydrate.install({ basepath, autoinstall: false }, function (err) { + if (err) assert.fail(err) // Check to see if files that are supposed to be there are actually there - t.notOk(existsSync(pythonDependencies[1]), `scoped install for ${pythonFunctions[1]} installed dependencies in ${pythonDependencies[1]}`) - t.notOk(existsSync(nodeDependencies[0]), `scoped install did not install dependencies for unspecified function at ${nodeDependencies[0]}`) + assert.ok(!existsSync(pythonDependencies[1]), `scoped install for ${pythonFunctions[1]} installed dependencies in ${pythonDependencies[1]}`) + assert.ok(!existsSync(nodeDependencies[0]), `scoped install did not install dependencies for unspecified function at ${nodeDependencies[0]}`) let arcFileArtifact = arcFileArtifacts.find(p => p.startsWith(arcAutoinstall[0])) let sharedArtifact = sharedArtifacts.find(p => p.startsWith(arcAutoinstall[0])) let viewsArtifact = viewsArtifacts.find(p => p.startsWith(arcAutoinstall[0])) - t.ok(existsSync(pythonSharedDependencies[1]), `python shared dependency exists at ${pythonSharedDependencies[1]}`) - t.notOk(existsSync(arcFileArtifact), `arc file does not exist at ${arcFileArtifact}`) - t.ok(existsSync(sharedArtifact), `shared file artifact exists at ${sharedArtifact}`) - t.notOk(existsSync(viewsArtifact), `shared file artifact exists at ${viewsArtifact}`) - checkFolderCreation(t) - } + assert.ok(existsSync(pythonSharedDependencies[1]), `python shared dependency exists at ${pythonSharedDependencies[1]}`) + assert.ok(!existsSync(arcFileArtifact), `arc file does not exist at ${arcFileArtifact}`) + assert.ok(existsSync(sharedArtifact), `shared file artifact exists at ${sharedArtifact}`) + assert.ok(!existsSync(viewsArtifact), `shared file artifact exists at ${viewsArtifact}`) + checkFolderCreation(assert) + resolve() + }) }) }) }) -test(`[Symlinking] install (specific path / single path) in a manifest-free Node.js function does not add missing deps with autoinstall disabled`, t => { - t.plan(7) - resetAndCopyShared(t, function () { - let basepath = nodeFunctions[1] - hydrate.install({ basepath, symlink, autoinstall: false }, function (err) { - if (err) t.fail(err) - else { +test(`[Symlinking] install (specific path / single path) in a manifest-free Node.js function does not add missing deps with autoinstall disabled`, async () => { + await new Promise((resolve) => { + resetAndCopyShared(function () { + let basepath = nodeFunctions[1] + hydrate.install({ basepath, symlink, autoinstall: false }, function (err) { + if (err) assert.fail(err) // Check to see if files that are supposed to be there are actually there - t.notOk(existsSync(nodeDependencies[1]), `scoped install for ${nodeFunctions[1]} installed dependencies in ${nodeDependencies[1]}`) - t.notOk(existsSync(pythonDependencies[0]), `scoped install did not install dependencies for unspecified function at ${pythonDependencies[0]}`) + assert.ok(!existsSync(nodeDependencies[1]), `scoped install for ${nodeFunctions[1]} installed dependencies in ${nodeDependencies[1]}`) + assert.ok(!existsSync(pythonDependencies[0]), `scoped install did not install dependencies for unspecified function at ${pythonDependencies[0]}`) let arcFileArtifact = arcFileArtifacts.find(p => p.startsWith(arcAutoinstall[0])) let sharedArtifact = sharedArtifacts.find(p => p.startsWith(arcAutoinstall[0])) let viewsArtifact = viewsArtifacts.find(p => p.startsWith(arcAutoinstall[0])) - t.ok(existsSync(nodeSharedDependencies[1]), `node shared dependency exists at ${nodeSharedDependencies[1]}`) - t.notOk(existsSync(arcFileArtifact), `arc file does not exist at ${arcFileArtifact}`) - t.ok(existsSync(sharedArtifact), `shared file artifact exists at ${sharedArtifact}`) - t.notOk(existsSync(viewsArtifact), `shared file artifact exists at ${viewsArtifact}`) - checkFolderCreation(t) - } + assert.ok(existsSync(nodeSharedDependencies[1]), `node shared dependency exists at ${nodeSharedDependencies[1]}`) + assert.ok(!existsSync(arcFileArtifact), `arc file does not exist at ${arcFileArtifact}`) + assert.ok(existsSync(sharedArtifact), `shared file artifact exists at ${sharedArtifact}`) + assert.ok(!existsSync(viewsArtifact), `shared file artifact exists at ${viewsArtifact}`) + checkFolderCreation(assert) + resolve() + }) }) }) }) -test(`[Symlinking] install() should not recurse into Functions dependencies and hydrate those`, t => { - t.plan(2) - reset(t, function () { - let subdep = join(nodeFunctions[0], 'node_modules', 'poop') - mkdirSync(subdep, { recursive: true }) - writeFileSync(join(subdep, 'package.json'), JSON.stringify({ - name: 'poop', - dependencies: { 'tiny-json-http': '*' }, - }), 'utf-8') - let basepath = nodeFunctions[0] - hydrate.install({ basepath, symlink }, function (err) { - if (err) t.fail(err) - else { +test(`[Symlinking] install() should not recurse into Functions dependencies and hydrate those`, async () => { + await new Promise((resolve) => { + reset(function () { + let subdep = join(nodeFunctions[0], 'node_modules', 'poop') + mkdirSync(subdep, { recursive: true }) + writeFileSync(join(subdep, 'package.json'), JSON.stringify({ + name: 'poop', + dependencies: { 'tiny-json-http': '*' }, + }), 'utf-8') + let basepath = nodeFunctions[0] + hydrate.install({ basepath, symlink }, function (err) { + if (err) assert.fail(err) let submod = join(subdep, 'node_modules') - t.notOk(existsSync(submod), `install did not recurse into node subdependencies at ${submod}`) - checkFolderCreation(t) - } + assert.ok(!existsSync(submod), `install did not recurse into node subdependencies at ${submod}`) + checkFolderCreation(assert) + resolve() + }) }) }) }) diff --git a/test/integration/symlink/shared-tests.js b/test/integration/symlink/shared-tests.js index da0abee..cf8f628 100644 --- a/test/integration/symlink/shared-tests.js +++ b/test/integration/symlink/shared-tests.js @@ -8,7 +8,8 @@ let { renameSync, writeFileSync, } = require('fs') -let test = require('tape') +const { test } = require('node:test') +const assert = require('node:assert') let { resetAndCopyShared, resetAndCopySharedCustom, @@ -27,370 +28,343 @@ let hydrate = require('../../..') process.env.CI = true // Suppresses tape issues with progress indicator let symlink = true -test('Does not exit code 1', t => { - process.on('exit', code => { if (code === 1) t.fail('Exited code 1!') }) - t.end() -}) - // As of late 2020, this test passes GHCI in both windows-latest and windows-2016 // This is strange, bc windows-2016 should be running a pre-Windows-symlink build (10.0.14393 Build 3930) // See: https://blogs.windows.com/windowsdeveloper/2016/12/02/symlinks-windows-10/ -test(`[Shared file symlinking (default paths)] shared() never uses symlinks by default`, t => { - t.plan(2) - resetAndCopyShared(t, function () { - hydrate.shared({ symlink }, function (err) { - if (err) t.fail(err) - else { +test(`[Shared file symlinking (default paths)] shared() never uses symlinks by default`, async () => { + await new Promise((resolve) => { + resetAndCopyShared(function () { + hydrate.shared({ symlink }, function (err) { + if (err) assert.fail(err) let path = 'src/http/get-index/node_modules/@architect/shared' let file = path + '/shared.md' let stat = lstatSync(path).isSymbolicLink() - t.ok(stat, 'shared directory is a symlink') - t.equal(readFileSync(file).toString(), 'It me!', 'Symlinked file is readable') - } + assert.ok(stat, 'shared directory is a symlink') + assert.strictEqual(readFileSync(file).toString(), 'It me!', 'Symlinked file is readable') + resolve() + }) }) }) }) -test(`[Shared file symlinking (custom paths)] shared() never uses symlinks by default`, t => { - t.plan(2) - resetAndCopySharedCustom(t, function () { - hydrate.shared({ symlink }, function (err) { - if (err) t.fail(err) - else { +test(`[Shared file symlinking (custom paths)] shared() never uses symlinks by default`, async () => { + await new Promise((resolve) => { + resetAndCopySharedCustom(function () { + hydrate.shared({ symlink }, function (err) { + if (err) assert.fail(err) let path = 'src/http/get-index/node_modules/@architect/shared' let file = path + '/shared.md' let stat = lstatSync(path).isSymbolicLink() - t.ok(stat, 'shared directory is a symlink') - t.equal(readFileSync(file).toString(), 'It me!', 'Symlinked file is readable') - } + assert.ok(stat, 'shared directory is a symlink') + assert.strictEqual(readFileSync(file).toString(), 'It me!', 'Symlinked file is readable') + resolve() + }) }) }) }) -test(`[Shared file symlinking (default paths)] shared() copies shared and views (unless disabled or folder not found; @views not specified)`, t => { - t.plan( - sharedArtifacts.length + - getViewsArtifacts.length + - sharedArtifactsDisabled.length + - viewsArtifactsDisabled.length + 1, - ) - resetAndCopyShared(t, function () { - hydrate.shared({ symlink }, function (err) { - if (err) t.fail(err) - else { +test(`[Shared file symlinking (default paths)] shared() copies shared and views (unless disabled or folder not found; @views not specified)`, async () => { + await new Promise((resolve) => { + resetAndCopyShared(function () { + hydrate.shared({ symlink }, function (err) { + if (err) assert.fail(err) // Check to see if files that are supposed to be there are actually there sharedArtifacts.forEach(path => { - t.ok(existsSync(path), `Found shared file in ${path}`) + assert.ok(existsSync(path), `Found shared file in ${path}`) }) sharedArtifactsDisabled.forEach(path => { - t.notOk(existsSync(path), `Did not find shared file in function with @arc shared false ${path}`) + assert.ok(!existsSync(path), `Did not find shared file in function with @arc shared false ${path}`) }) getViewsArtifacts.forEach(path => { if (path.includes('get-')) { - t.ok(existsSync(path), `Found views file in GET function ${path}`) + assert.ok(existsSync(path), `Found views file in GET function ${path}`) } else { - t.notOk(existsSync(path), `Did not find views file in non-GET function ${path}`) + assert.ok(!existsSync(path), `Did not find views file in non-GET function ${path}`) } }) viewsArtifactsDisabled.forEach(path => { - t.notOk(existsSync(path), `Did not find views file in function with @arc views false ${path}`) + assert.ok(!existsSync(path), `Did not find views file in function with @arc views false ${path}`) }) - checkFolderCreation(t) - } + checkFolderCreation(assert) + resolve() + }) }) }) }) -test(`[Shared file symlinking with plugins (default paths)] shared() copies shared and views, as well as files via plugin`, t => { - t.plan( - sharedArtifacts.length + - getViewsArtifacts.length + - sharedArtifactsDisabled.length + - viewsArtifactsDisabled.length + - pluginArtifacts.length + 1, - ) - resetAndCopySharedPlugins(t, function () { - cp(join('src', 'app.plugins'), join('.', 'app.arc'), { recursive: true, force: true }, - function (err) { - if (err) t.fail(err) - else { +test(`[Shared file symlinking with plugins (default paths)] shared() copies shared and views, as well as files via plugin`, async () => { + await new Promise((resolve) => { + resetAndCopySharedPlugins(function () { + cp(join('src', 'app.plugins'), join('.', 'app.arc'), { recursive: true, force: true }, + function (err) { + if (err) assert.fail(err) hydrate.shared({}, function (err) { - if (err) t.fail(err) - else { + if (err) assert.fail(err) // Check to see if files that are supposed to be there are actually there - sharedArtifacts.forEach(path => { - t.ok(existsSync(path), `Found shared file in ${path}`) - }) - sharedArtifactsDisabled.forEach(path => { - t.notOk(existsSync(path), `Did not find shared file in function with @arc shared false ${path}`) - }) - getViewsArtifacts.forEach(path => { - if (path.includes('get-')) { - t.ok(existsSync(path), `Found views file in GET function ${path}`) - } - else { - t.notOk(existsSync(path), `Did not find views file in non-GET function ${path}`) - } - }) - viewsArtifactsDisabled.forEach(path => { - t.notOk(existsSync(path), `Did not find views file in function with @arc views false ${path}`) - }) - pluginArtifacts.forEach(path => { - t.ok(existsSync(path), `Found plugin file in ${path}`) - }) - let normallyShouldNotBePresent = join('src', 'events', 'silence', 'node_modules') - t.ok(existsSync(normallyShouldNotBePresent), 'Silence event folder created just this once!') - } + sharedArtifacts.forEach(path => { + assert.ok(existsSync(path), `Found shared file in ${path}`) + }) + sharedArtifactsDisabled.forEach(path => { + assert.ok(!existsSync(path), `Did not find shared file in function with @arc shared false ${path}`) + }) + getViewsArtifacts.forEach(path => { + if (path.includes('get-')) { + assert.ok(existsSync(path), `Found views file in GET function ${path}`) + } + else { + assert.ok(!existsSync(path), `Did not find views file in non-GET function ${path}`) + } + }) + viewsArtifactsDisabled.forEach(path => { + assert.ok(!existsSync(path), `Did not find views file in function with @arc views false ${path}`) + }) + pluginArtifacts.forEach(path => { + assert.ok(existsSync(path), `Found plugin file in ${path}`) + }) + let normallyShouldNotBePresent = join('src', 'events', 'silence', 'node_modules') + assert.ok(existsSync(normallyShouldNotBePresent), 'Silence event folder created just this once!') + resolve() }) - } - }) + }) + }) }) }) -test(`[Shared file symlinking (custom paths)] shared() copies shared and views (unless disabled or folder not found; @views not specified)`, t => { - t.plan( - sharedArtifacts.length + - getViewsArtifacts.length + - sharedArtifactsDisabled.length + - viewsArtifactsDisabled.length + 1, - ) - resetAndCopySharedCustom(t, function () { - hydrate.shared({ symlink }, function (err) { - if (err) t.fail(err) - else { +test(`[Shared file symlinking (custom paths)] shared() copies shared and views (unless disabled or folder not found; @views not specified)`, async () => { + await new Promise((resolve) => { + resetAndCopySharedCustom(function () { + hydrate.shared({ symlink }, function (err) { + if (err) assert.fail(err) // Check to see if files that are supposed to be there are actually there sharedArtifacts.forEach(path => { - t.ok(existsSync(path), `Found shared file in ${path}`) + assert.ok(existsSync(path), `Found shared file in ${path}`) }) sharedArtifactsDisabled.forEach(path => { - t.notOk(existsSync(path), `Did not find shared file in function with @arc shared false ${path}`) + assert.ok(!existsSync(path), `Did not find shared file in function with @arc shared false ${path}`) }) getViewsArtifacts.forEach(path => { if (path.includes('get-')) { - t.ok(existsSync(path), `Found views file in GET function ${path}`) + assert.ok(existsSync(path), `Found views file in GET function ${path}`) } else { - t.notOk(existsSync(path), `Did not find views file in non-GET function ${path}`) + assert.ok(!existsSync(path), `Did not find views file in non-GET function ${path}`) } }) viewsArtifactsDisabled.forEach(path => { - t.notOk(existsSync(path), `Did not find views file in function with @arc views false ${path}`) + assert.ok(!existsSync(path), `Did not find views file in function with @arc views false ${path}`) }) - checkFolderCreation(t) - } + checkFolderCreation(assert) + resolve() + }) }) }) }) -test(`[Shared file symlinking (default paths)] shared() views to only @views (unless disabled or folder not found)`, t => { - t.plan(viewsArtifacts.length + viewsArtifactsDisabled.length + 1) - resetAndCopyShared(t, function () { - cp(join('src', 'app.arc-views'), join('.', 'app.arc'), { recursive: true, force: true }, function (err) { - if (err) t.fail(err) - else { +test(`[Shared file symlinking (default paths)] shared() views to only @views (unless disabled or folder not found)`, async () => { + await new Promise((resolve) => { + resetAndCopyShared(function () { + cp(join('src', 'app.arc-views'), join('.', 'app.arc'), { recursive: true, force: true }, function (err) { + if (err) assert.fail(err) hydrate.shared({ symlink }, function (err) { - if (err) t.fail(err) - else { - // Check to see if files that are supposed to be there are actually there - viewsArtifacts.forEach(path => { - if (path.includes('get-index') || path.includes('post-up-tents')) { - t.ok(existsSync(path), `Found views file in GET function ${path}`) - } - else { - t.notOk(existsSync(path), `Did not find views file in non-GET function ${path}`) - } - }) - viewsArtifactsDisabled.forEach(path => { - t.notOk(existsSync(path), `Did not find views file in function with @arc views false ${path}`) - }) - checkFolderCreation(t) - } + if (err) assert.fail(err) + // Check to see if files that are supposed to be there are actually there + viewsArtifacts.forEach(path => { + if (path.includes('get-index') || path.includes('post-up-tents')) { + assert.ok(existsSync(path), `Found views file in GET function ${path}`) + } + else { + assert.ok(!existsSync(path), `Did not find views file in non-GET function ${path}`) + } + }) + viewsArtifactsDisabled.forEach(path => { + assert.ok(!existsSync(path), `Did not find views file in function with @arc views false ${path}`) + }) + checkFolderCreation(assert) + resolve() }) - } + }) }) }) }) -test(`[Shared file symlinking (custom paths)] shared() views to only @views (unless disabled or folder not found)`, t => { - t.plan(viewsArtifacts.length + viewsArtifactsDisabled.length + 1) - resetAndCopySharedCustom(t, function () { - cp(join('_shared-custom', 'app.arc-views'), join('.', 'app.arc'), { recursive: true, force: true }, function (err) { - if (err) t.fail(err) - else { +test(`[Shared file symlinking (custom paths)] shared() views to only @views (unless disabled or folder not found)`, async () => { + await new Promise((resolve) => { + resetAndCopySharedCustom(function () { + cp(join('_shared-custom', 'app.arc-views'), join('.', 'app.arc'), { recursive: true, force: true }, function (err) { + if (err) assert.fail(err) hydrate.shared({ symlink }, function (err) { - if (err) t.fail(err) - else { - // Check to see if files that are supposed to be there are actually there - viewsArtifacts.forEach(path => { - if (path.includes('get-index') || path.includes('post-up-tents')) { - t.ok(existsSync(path), `Found views file in GET function ${path}`) - } - else { - t.notOk(existsSync(path), `Did not find views file in non-GET function ${path}`) - } - }) - viewsArtifactsDisabled.forEach(path => { - t.notOk(existsSync(path), `Did not find views file in function with @arc views false ${path}`) - }) - checkFolderCreation(t) - } + if (err) assert.fail(err) + // Check to see if files that are supposed to be there are actually there + viewsArtifacts.forEach(path => { + if (path.includes('get-index') || path.includes('post-up-tents')) { + assert.ok(existsSync(path), `Found views file in GET function ${path}`) + } + else { + assert.ok(!existsSync(path), `Did not find views file in non-GET function ${path}`) + } + }) + viewsArtifactsDisabled.forEach(path => { + assert.ok(!existsSync(path), `Did not find views file in function with @arc views false ${path}`) + }) + checkFolderCreation(assert) + resolve() }) - } + }) }) }) }) -test(`[Shared file symlinking (default paths)] shared() copies static.json but not app.arc (Arc v6+)`, t => { - t.plan(arcFileArtifacts.length + staticArtifacts.length + 1) - resetAndCopyShared(t, function () { - hydrate.shared({ symlink }, function (err) { - if (err) t.fail(err) - else { +test(`[Shared file symlinking (default paths)] shared() copies static.json but not app.arc (Arc v6+)`, async () => { + await new Promise((resolve) => { + resetAndCopyShared(function () { + hydrate.shared({ symlink }, function (err) { + if (err) assert.fail(err) // Check to see if files that are supposed to be there are actually there arcFileArtifacts.forEach(path => { - t.notOk(existsSync(path), `Did not find app.arc file in ${path}`) + assert.ok(!existsSync(path), `Did not find app.arc file in ${path}`) }) staticArtifacts.forEach(path => { - t.ok(existsSync(path), `Found static.json file in ${path}`) + assert.ok(existsSync(path), `Found static.json file in ${path}`) }) - checkFolderCreation(t) - } + checkFolderCreation(assert) + resolve() + }) }) }) }) -test(`[Shared file symlinking (custom paths)] shared() copies static.json but not app.arc (Arc v6+)`, t => { - t.plan(arcFileArtifacts.length + staticArtifacts.length + 1) - resetAndCopySharedCustom(t, function () { - hydrate.shared({ symlink }, function (err) { - if (err) t.fail(err) - else { +test(`[Shared file symlinking (custom paths)] shared() copies static.json but not app.arc (Arc v6+)`, async () => { + await new Promise((resolve) => { + resetAndCopySharedCustom(function () { + hydrate.shared({ symlink }, function (err) { + if (err) assert.fail(err) // Check to see if files that are supposed to be there are actually there arcFileArtifacts.forEach(path => { - t.notOk(existsSync(path), `Did not find app.arc file in ${path}`) + assert.ok(!existsSync(path), `Did not find app.arc file in ${path}`) }) staticArtifacts.forEach(path => { - t.ok(existsSync(path), `Found static.json file in ${path}`) + assert.ok(existsSync(path), `Found static.json file in ${path}`) }) - checkFolderCreation(t) - } + checkFolderCreation(assert) + resolve() + }) }) }) }) -test(`[Shared file symlinking (default paths)] shared() copies static.json with @static folder configured`, t => { - t.plan(staticArtifacts.length + 3) - resetAndCopyShared(t, function () { - // Rewrite app.arc to include @static folder directive - let arcFile = join(process.cwd(), 'app.arc') - let arc = readFileSync(arcFile).toString() - arc += '@static\nfolder foo' - writeFileSync(arcFile, arc) - t.pass(`Added '@static folder foo' to app.arc`) - // Move public/ to foo/ - renameSync(join(process.cwd(), 'public'), join(process.cwd(), 'foo')) - t.ok(existsSync(join(process.cwd(), 'foo', 'static.json')), 'public/static.json moved into foo/static.json') - hydrate.shared({ symlink }, function (err) { - if (err) t.fail(err) - else { +test(`[Shared file symlinking (default paths)] shared() copies static.json with @static folder configured`, async () => { + await new Promise((resolve) => { + resetAndCopyShared(function () { + // Rewrite app.arc to include @static folder directive + let arcFile = join(process.cwd(), 'app.arc') + let arc = readFileSync(arcFile).toString() + arc += '@static\nfolder foo' + writeFileSync(arcFile, arc) + assert.ok(true, `Added '@static folder foo' to app.arc`) + // Move public/ to foo/ + renameSync(join(process.cwd(), 'public'), join(process.cwd(), 'foo')) + assert.ok(existsSync(join(process.cwd(), 'foo', 'static.json')), 'public/static.json moved into foo/static.json') + hydrate.shared({ symlink }, function (err) { + if (err) assert.fail(err) // Check to see if files that are supposed to be there are actually there staticArtifacts.forEach(path => { - t.ok(existsSync(path), `Found static.json file in ${path}`) + assert.ok(existsSync(path), `Found static.json file in ${path}`) }) - checkFolderCreation(t) - } + checkFolderCreation(assert) + resolve() + }) }) }) }) -test(`[Shared file symlinking (custom paths)] shared() copies static.json with @static folder configured`, t => { - t.plan(staticArtifacts.length + 3) - resetAndCopySharedCustom(t, function () { - // Rewrite app.arc to include @static folder directive - let arcFile = join(process.cwd(), 'app.arc') - let arc = readFileSync(arcFile).toString() - arc += '@static\nfolder foo' - writeFileSync(arcFile, arc) - t.pass(`Added '@static folder foo' to app.arc`) - // Move public/ to foo/ - renameSync(join(process.cwd(), 'public'), join(process.cwd(), 'foo')) - t.ok(existsSync(join(process.cwd(), 'foo', 'static.json')), 'public/static.json moved into foo/static.json') - hydrate.shared({ symlink }, function (err) { - if (err) t.fail(err) - else { +test(`[Shared file symlinking (custom paths)] shared() copies static.json with @static folder configured`, async () => { + await new Promise((resolve) => { + resetAndCopySharedCustom(function () { + // Rewrite app.arc to include @static folder directive + let arcFile = join(process.cwd(), 'app.arc') + let arc = readFileSync(arcFile).toString() + arc += '@static\nfolder foo' + writeFileSync(arcFile, arc) + assert.ok(true, `Added '@static folder foo' to app.arc`) + // Move public/ to foo/ + renameSync(join(process.cwd(), 'public'), join(process.cwd(), 'foo')) + assert.ok(existsSync(join(process.cwd(), 'foo', 'static.json')), 'public/static.json moved into foo/static.json') + hydrate.shared({ symlink }, function (err) { + if (err) assert.fail(err) // Check to see if files that are supposed to be there are actually there staticArtifacts.forEach(path => { - t.ok(existsSync(path), `Found static.json file in ${path}`) + assert.ok(existsSync(path), `Found static.json file in ${path}`) }) - checkFolderCreation(t) - } + checkFolderCreation(assert) + resolve() + }) }) }) }) -test(`[Shared file symlinking (default paths)] shared() should remove files in functions that do not exist in shared and views`, t => { - t.plan(sharedArtifacts.length + getViewsArtifacts.length + 1) - resetAndCopyShared(t, function () { - let sharedStragglers = sharedArtifacts.map((p) => { - let dir = dirname(p) - mkdirSync(dir, { recursive: true }) - let file = join(dir, 'straggler.json') - writeFileSync(file, '{surprise:true}') - return file - }) - let viewsStragglers = getViewsArtifacts.map((p) => { - let dir = dirname(p) - mkdirSync(dir, { recursive: true }) - let file = join(dir, 'straggler.json') - writeFileSync(file, '{surprise:true}') - return file - }) - hydrate.shared({ symlink }, function (err) { - if (err) t.fail(err) - else { +test(`[Shared file symlinking (default paths)] shared() should remove files in functions that do not exist in shared and views`, async () => { + await new Promise((resolve) => { + resetAndCopyShared(function () { + let sharedStragglers = sharedArtifacts.map((p) => { + let dir = dirname(p) + mkdirSync(dir, { recursive: true }) + let file = join(dir, 'straggler.json') + writeFileSync(file, '{surprise:true}') + return file + }) + let viewsStragglers = getViewsArtifacts.map((p) => { + let dir = dirname(p) + mkdirSync(dir, { recursive: true }) + let file = join(dir, 'straggler.json') + writeFileSync(file, '{surprise:true}') + return file + }) + hydrate.shared({ symlink }, function (err) { + if (err) assert.fail(err) // Check to see if files that are supposed to be there are actually there sharedStragglers.forEach(path => { - t.notOk(existsSync(path), `shared straggler file removed from ${path}`) + assert.ok(!existsSync(path), `shared straggler file removed from ${path}`) }) viewsStragglers.forEach(path => { - t.notOk(existsSync(path), `views straggler file removed from ${path}`) + assert.ok(!existsSync(path), `views straggler file removed from ${path}`) }) - checkFolderCreation(t) - } + checkFolderCreation(assert) + resolve() + }) }) }) }) -test(`[Shared file symlinking (custom paths)] shared() should remove files in functions that do not exist in shared and views`, t => { - t.plan(sharedArtifacts.length + getViewsArtifacts.length + 1) - resetAndCopySharedCustom(t, function () { - let sharedStragglers = sharedArtifacts.map((p) => { - let dir = dirname(p) - mkdirSync(dir, { recursive: true }) - let file = join(dir, 'straggler.json') - writeFileSync(file, '{surprise:true}') - return file - }) - let viewsStragglers = getViewsArtifacts.map((p) => { - let dir = dirname(p) - mkdirSync(dir, { recursive: true }) - let file = join(dir, 'straggler.json') - writeFileSync(file, '{surprise:true}') - return file - }) - hydrate.shared({ symlink }, function (err) { - if (err) t.fail(err) - else { +test(`[Shared file symlinking (custom paths)] shared() should remove files in functions that do not exist in shared and views`, async () => { + await new Promise((resolve) => { + resetAndCopySharedCustom(function () { + let sharedStragglers = sharedArtifacts.map((p) => { + let dir = dirname(p) + mkdirSync(dir, { recursive: true }) + let file = join(dir, 'straggler.json') + writeFileSync(file, '{surprise:true}') + return file + }) + let viewsStragglers = getViewsArtifacts.map((p) => { + let dir = dirname(p) + mkdirSync(dir, { recursive: true }) + let file = join(dir, 'straggler.json') + writeFileSync(file, '{surprise:true}') + return file + }) + hydrate.shared({ symlink }, function (err) { + if (err) assert.fail(err) // Check to see if files that are supposed to be there are actually there sharedStragglers.forEach(path => { - t.notOk(existsSync(path), `shared straggler file removed from ${path}`) + assert.ok(!existsSync(path), `shared straggler file removed from ${path}`) }) viewsStragglers.forEach(path => { - t.notOk(existsSync(path), `views straggler file removed from ${path}`) + assert.ok(!existsSync(path), `views straggler file removed from ${path}`) }) - checkFolderCreation(t) - } + checkFolderCreation(assert) + resolve() + }) }) }) }) diff --git a/test/integration/symlink/update-tests.js b/test/integration/symlink/update-tests.js index 00e3cd4..6041790 100644 --- a/test/integration/symlink/update-tests.js +++ b/test/integration/symlink/update-tests.js @@ -1,8 +1,9 @@ +const { test } = require('node:test') +const assert = require('node:assert') let { join } = require('path') let { readFileSync, } = require('fs') -let test = require('tape') let { reset, checkFolderCreation, @@ -14,37 +15,32 @@ let hydrate = require('../../..') process.env.CI = true // Suppresses tape issues with progress indicator let symlink = true -test('Does not exit code 1', t => { - process.on('exit', code => { if (code === 1) t.fail('Exited code 1!') }) - t.end() -}) - // As of late 2020, this test passes GHCI in both windows-latest and windows-2016 // This is strange, bc windows-2016 should be running a pre-Windows-symlink build (10.0.14393 Build 3930) // See: https://blogs.windows.com/windowsdeveloper/2016/12/02/symlinks-windows-10/ -test(`[Symlinking] update() bumps installed dependencies to newer versions`, t => { - t.plan(4) - reset(t, function () { - // TODO: pip requires manual locking (via two requirements.txt files) so - // we dont test update w/ python - hydrate.update({ symlink }, function (err) { - if (err) t.fail(err) - else { +test(`[Symlinking] update() bumps installed dependencies to newer versions`, async () => { + await new Promise((resolve) => { + reset(function () { + // TODO: pip requires manual locking (via two requirements.txt files) so + // we dont test update w/ python + hydrate.update({ symlink }, function (err) { + if (err) assert.fail(err) let pkgLock = JSON.parse(readFileSync(join(mockTmp, nodeFunctions[0], 'package-lock.json'))) let newVersion = [ 2, 3 ].includes(pkgLock.lockfileVersion) ? pkgLock.packages['node_modules/tiny-json-http'].version : pkgLock.dependencies['tiny-json-http'].version - t.notEqual(newVersion, '7.0.2', `get-index tiny-json-http bumped to ${newVersion} from 7.0.2`) + assert.notStrictEqual(newVersion, '7.0.2', `get-index tiny-json-http bumped to ${newVersion} from 7.0.2`) let yarnLock = readFileSync(join(mockTmp, nodeFunctions[2], 'yarn.lock'), 'utf-8') let newYarn = yarnLock.split('\n').filter(t => t.includes(' version "'))[0].split(' version "')[1].replace('"', '') - t.notEqual(newYarn, '7.0.2', `put-on_your_boots tiny-json-http bumped to ${newVersion} from 7.0.2`) + assert.notStrictEqual(newYarn, '7.0.2', `put-on_your_boots tiny-json-http bumped to ${newVersion} from 7.0.2`) let gemfileLock = readFileSync(join(mockTmp, rubyFunctions[0], 'Gemfile.lock'), 'utf-8') let newGem = gemfileLock.split('\n').filter(t => t.includes('a (0'))[0].split('(')[1].split(')')[0] - t.notEqual(newGem, '0.2.1', `delete-badness_in_life 'a' gem bumped to ${newGem} from 0.2.1`) - checkFolderCreation(t) - } + assert.notStrictEqual(newGem, '0.2.1', `delete-badness_in_life 'a' gem bumped to ${newGem} from 0.2.1`) + checkFolderCreation(assert) + resolve() + }) }) }) }) diff --git a/test/unit/index-tests.js b/test/unit/index-tests.js index 8809e8f..7400a94 100644 --- a/test/unit/index-tests.js +++ b/test/unit/index-tests.js @@ -1,5 +1,7 @@ -let test = require('tape') -let proxyquire = require('proxyquire') +const { test } = require('node:test') +const assert = require('node:assert') +const Module = require('module') + let called = [] function caller (type, callback) { called.push(type) @@ -10,60 +12,78 @@ let run = (installing, params, callback) => { else caller('update', callback) } let shared = (p, callback) => caller('shared', callback) -let hydrate = proxyquire('../../', { - './hydrate': run, - './shared': shared, -}) -process.env.CI = true // Suppresses tape issues with progress indicator + +// Mock modules using Module._load override +const originalLoad = Module._load +Module._load = function (request, parent) { + if (request === './hydrate' && parent && parent.filename && parent.filename.endsWith('index.js')) { + return run + } + if (request === './shared' && parent && parent.filename && parent.filename.endsWith('index.js')) { + return shared + } + return originalLoad.apply(this, arguments) +} + +const hydrate = require('../../') + +// Restore original Module._load +Module._load = originalLoad + +process.env.CI = true // Suppresses issues with progress indicator function reset () { called = [] } -test('Set up env', t => { - t.plan(1) - t.ok(hydrate, 'Hydrate module is present') +test('Set up env', async () => { + assert.ok(hydrate, 'Hydrate module is present') }) -test('Main hydration methods are present', t => { - t.plan(3) - t.ok(hydrate.install, 'install method is present') - t.ok(hydrate.update, 'update method is present') - t.ok(hydrate.shared, 'shared method is present') +test('Main hydration methods are present', async () => { + assert.ok(hydrate.install, 'install method is present') + assert.ok(hydrate.update, 'update method is present') + assert.ok(hydrate.shared, 'shared method is present') }) -test(`hydrate.install invokes install`, t => { - t.plan(2) - hydrate.install({}, function done (err) { - if (err) t.fail(err) - else { - t.equal(called.length, 1, 'Invoked one method') - t.equal(called[0], 'install', 'Invoked install') - } +test('hydrate.install invokes install', async () => { + await new Promise((resolve) => { + hydrate.install({}, function done (err) { + if (err) assert.fail(err) + else { + assert.strictEqual(called.length, 1, 'Invoked one method') + assert.strictEqual(called[0], 'install', 'Invoked install') + } + reset() + resolve() + }) }) - reset() }) -test(`hydrate.update invokes update`, t => { - t.plan(2) - hydrate.update({}, function done (err) { - if (err) t.fail(err) - else { - t.equal(called.length, 1, 'Invoked one method') - t.equal(called[0], 'update', 'Invoked update') - } +test('hydrate.update invokes update', async () => { + await new Promise((resolve) => { + hydrate.update({}, function done (err) { + if (err) assert.fail(err) + else { + assert.strictEqual(called.length, 1, 'Invoked one method') + assert.strictEqual(called[0], 'update', 'Invoked update') + } + reset() + resolve() + }) }) - reset() }) -test(`hydrate.shared invokes shared`, t => { - t.plan(2) - hydrate.shared({}, function done (err) { - if (err) t.fail(err) - else { - t.equal(called.length, 1, 'Invoked one method') - t.equal(called[0], 'shared', 'Invoked shared') - } +test('hydrate.shared invokes shared', async () => { + await new Promise((resolve) => { + hydrate.shared({}, function done (err) { + if (err) assert.fail(err) + else { + assert.strictEqual(called.length, 1, 'Invoked one method') + assert.strictEqual(called[0], 'shared', 'Invoked shared') + } + reset() + resolve() + }) }) - reset() }) diff --git a/test/unit/src/_printer-tests.js b/test/unit/src/_printer-tests.js index d657ecb..fe58d40 100644 --- a/test/unit/src/_printer-tests.js +++ b/test/unit/src/_printer-tests.js @@ -1,14 +1,13 @@ -let test = require('tape') -let print = require('../../../src/_printer') -let { updater } = require('@architect/utils') +const { test } = require('node:test') +const assert = require('node:assert') +const print = require('../../../src/_printer') +const { updater } = require('@architect/utils') -test('Set up env', t => { - t.plan(1) - t.ok(print, 'Printer loaded') +test('Set up env', async () => { + assert.ok(print, 'Printer loaded') }) -test('Error on missing params', t => { - t.plan(3) +test('Error on missing params', async () => { let name = 'Testing err' let startMsg = 'Start test' let stdout = 'some info\nmore info' @@ -16,23 +15,35 @@ test('Error on missing params', t => { let done = 'Finish test' let update = updater(name) let start = update.start(startMsg) - print({ stdout, start, done, update }, (err, result) => { - if (err) t.pass(err) - if (result) t.fail('Got unexpected result') + + await new Promise((resolve) => { + print({ stdout, start, done, update }, (err, result) => { + if (err) assert.ok(true, err) + if (result) assert.fail('Got unexpected result') + resolve() + }) }) - print({ stdout, cmd, start, done }, (err, result) => { - if (err) t.pass(err) - if (result) t.fail('Got unexpected result') + + await new Promise((resolve) => { + print({ stdout, cmd, start, done }, (err, result) => { + if (err) assert.ok(true, err) + if (result) assert.fail('Got unexpected result') + resolve() + }) }) - print({ stdout, cmd, update }, (err, result) => { - if (err) t.pass(err) - if (result) t.fail('Got unexpected result') + + await new Promise((resolve) => { + print({ stdout, cmd, update }, (err, result) => { + if (err) assert.ok(true, err) + if (result) assert.fail('Got unexpected result') + resolve() + }) }) + update.cancel() }) -test('Basic stdout', t => { - t.plan(6) +test('Basic stdout', async () => { // Messages let name = 'Testing stdout' let startMsg = 'Start test' @@ -42,22 +53,24 @@ test('Basic stdout', t => { let update = updater(name) let start = update.start(startMsg) - print({ stdout, cmd, start, done, update }, err => { - if (err) t.fail(err) - else { - let got = update.get() - update.reset() - t.match(got, new RegExp(name), `Contents include: ${name}`) - t.match(got, new RegExp(startMsg), `Contents include: ${startMsg}`) - stdout.split('\n').forEach(o => t.match(got, new RegExp(o), `Contents include: ${o}`)) - t.match(got, new RegExp(cmd), `Contents include: ${cmd}`) - t.match(got, new RegExp(done), `Contents include: ${done}`) - } + await new Promise((resolve) => { + print({ stdout, cmd, start, done, update }, err => { + if (err) assert.fail(err) + else { + let got = update.get() + update.reset() + assert.match(got, new RegExp(name), `Contents include: ${name}`) + assert.match(got, new RegExp(startMsg), `Contents include: ${startMsg}`) + stdout.split('\n').forEach(o => assert.match(got, new RegExp(o), `Contents include: ${o}`)) + assert.match(got, new RegExp(cmd), `Contents include: ${cmd}`) + assert.match(got, new RegExp(done), `Contents include: ${done}`) + } + resolve() + }) }) }) -test('Basic stderr', t => { - t.plan(6) +test('Basic stderr', async () => { // Messages let name = 'Testing stderr' let startMsg = 'Start test' @@ -67,22 +80,24 @@ test('Basic stderr', t => { let update = updater(name) let start = update.start(startMsg) - print({ stderr, cmd, start, done, update }, err => { - if (err) t.fail(err) - else { - let got = update.get() - update.reset() - t.match(got, new RegExp(name), `Contents include: ${name}`) - t.match(got, new RegExp(startMsg), `Contents include: ${startMsg}`) - stderr.split('\n').forEach(o => t.match(got, new RegExp(o), `Contents include: ${o}`)) - t.match(got, new RegExp(cmd), `Contents include: ${cmd}`) - t.match(got, new RegExp(done), `Contents include: ${done}`) - } + await new Promise((resolve) => { + print({ stderr, cmd, start, done, update }, err => { + if (err) assert.fail(err) + else { + let got = update.get() + update.reset() + assert.match(got, new RegExp(name), `Contents include: ${name}`) + assert.match(got, new RegExp(startMsg), `Contents include: ${startMsg}`) + stderr.split('\n').forEach(o => assert.match(got, new RegExp(o), `Contents include: ${o}`)) + assert.match(got, new RegExp(cmd), `Contents include: ${cmd}`) + assert.match(got, new RegExp(done), `Contents include: ${done}`) + } + resolve() + }) }) }) -test('Basic err (with some stdout)', t => { - t.plan(6) +test('Basic err (with some stdout)', async () => { // Messages let name = 'Testing err' let startMsg = 'Start test asdfasdfasfs' @@ -94,16 +109,19 @@ test('Basic err (with some stdout)', t => { let update = updater(name) let start = update.start(startMsg) - print({ stdout, err, cmd, start, done, update }, err => { - if (!err) t.fail('No error present') - else { - let got = update.get() - update.reset() - t.match(got, new RegExp(name), `Contents include: ${name}`) - t.match(got, new RegExp(startMsg), `Contents include: ${startMsg}`) - errLine.split('\n').forEach(o => t.match(got, new RegExp(o), `Contents include: ${o}`)) - t.match(got, new RegExp(cmd), `Contents include: ${cmd}`) - t.match(got, new RegExp(done), `Contents do not include: ${done}`) - } + await new Promise((resolve) => { + print({ stdout, err, cmd, start, done, update }, err => { + if (!err) assert.fail('No error present') + else { + let got = update.get() + update.reset() + assert.match(got, new RegExp(name), `Contents include: ${name}`) + assert.match(got, new RegExp(startMsg), `Contents include: ${startMsg}`) + errLine.split('\n').forEach(o => assert.match(got, new RegExp(o), `Contents include: ${o}`)) + assert.match(got, new RegExp(cmd), `Contents include: ${cmd}`) + assert.match(got, new RegExp(done), `Contents do not include: ${done}`) + } + resolve() + }) }) }) diff --git a/test/unit/src/actions/autoinstall/get-lambda-deps-tests.js b/test/unit/src/actions/autoinstall/get-lambda-deps-tests.js index 7be1497..fed8c42 100644 --- a/test/unit/src/actions/autoinstall/get-lambda-deps-tests.js +++ b/test/unit/src/actions/autoinstall/get-lambda-deps-tests.js @@ -1,20 +1,19 @@ -let { join } = require('path') -let test = require('tape') -let sut = join(process.cwd(), 'src', 'actions', 'autoinstall', 'node', 'get-lambda-deps') -let getLambdaDeps = require(sut) -let mock = join(process.cwd(), 'test', 'mocks') -let { updater } = require('@architect/utils') -let update = updater('Hydrate') -let jsFiles = 9 -let correct = [ '@a/package', '@b/package', 'c', 'd', 'e', 'f', 'g', 'h' ] +const { join } = require('path') +const { test } = require('node:test') +const assert = require('node:assert') +const sut = join(process.cwd(), 'src', 'actions', 'autoinstall', 'node', 'get-lambda-deps') +const getLambdaDeps = require(sut) +const mock = join(process.cwd(), 'test', 'mocks') +const { updater } = require('@architect/utils') +const update = updater('Hydrate') +const jsFiles = 9 +const correct = [ '@a/package', '@b/package', 'c', 'd', 'e', 'f', 'g', 'h' ] -test('Set up env', t => { - t.plan(1) - t.ok(getLambdaDeps, 'Dependency getter module is present') +test('Set up env', async () => { + assert.ok(getLambdaDeps, 'Dependency getter module is present') }) -test(`Walk CommonJS deps`, t => { - t.plan(6) +test('Walk CommonJS deps', async () => { let stdout = process.stdout.write let data = '' process.stdout.write = write => { @@ -24,16 +23,15 @@ test(`Walk CommonJS deps`, t => { let { deps, failures, files, awsSdkV2, awsSdkV3 } = getLambdaDeps({ dir: join(mock, 'deps-cjs'), update, inventory }) process.stdout.write = stdout - t.deepEqual(deps.sort(), correct, `Got correct deps`) - t.notOk(failures.length, 'Got no failures') - t.equal(files.length, jsFiles, `Walked ${jsFiles} js files`) - t.match(data, /'something'/, 'Warned about dynamic require') - t.ok(awsSdkV2, 'Found AWS SDK v2') - t.ok(awsSdkV3, 'Found AWS SDK v3') + assert.deepStrictEqual(deps.sort(), correct, 'Got correct deps') + assert.ok(!failures.length, 'Got no failures') + assert.strictEqual(files.length, jsFiles, `Walked ${jsFiles} js files`) + assert.match(data, /'something'/, 'Warned about dynamic require') + assert.ok(awsSdkV2, 'Found AWS SDK v2') + assert.ok(awsSdkV3, 'Found AWS SDK v3') }) -test(`Walk ESM deps`, t => { - t.plan(6) +test('Walk ESM deps', async () => { let stdout = process.stdout.write let data = '' process.stdout.write = write => { @@ -43,23 +41,22 @@ test(`Walk ESM deps`, t => { let { deps, failures, files, awsSdkV2, awsSdkV3 } = getLambdaDeps({ dir: join(mock, 'deps-esm'), update, inventory }) process.stdout.write = stdout - t.deepEqual(deps.sort(), correct, `Got correct deps`) - t.notOk(failures.length, 'Got no failures') - t.equal(files.length, jsFiles, `Walked ${jsFiles} js files`) - t.match(data, /'something'/, 'Warned about dynamic require') - t.ok(awsSdkV2, 'Found AWS SDK v2') - t.ok(awsSdkV3, 'Found AWS SDK v3') + assert.deepStrictEqual(deps.sort(), correct, 'Got correct deps') + assert.ok(!failures.length, 'Got no failures') + assert.strictEqual(files.length, jsFiles, `Walked ${jsFiles} js files`) + assert.match(data, /'something'/, 'Warned about dynamic require') + assert.ok(awsSdkV2, 'Found AWS SDK v2') + assert.ok(awsSdkV3, 'Found AWS SDK v3') }) -test(`Module systems can kind of mix (sometimes) but not really`, t => { - t.plan(4) +test('Module systems can kind of mix (sometimes) but not really', async () => { let inventory = { inv: { _project: {} } } let dir = join(mock, 'deps-mixed') let { deps, files, awsSdkV2, awsSdkV3 } = getLambdaDeps({ dir, update, inventory }) // TODO such mixed ensure checks are only happening in ESM, not CJS; use Arc 10's `lambda.handlerModuleSystem` - t.deepEqual(deps.sort(), [ 'a', 'b' ], `Got correct deps`) - t.equal(files.length, 1, 'Walked 1 js file') - t.notOk(awsSdkV2, 'Did not find AWS SDK v2') - t.notOk(awsSdkV3, 'Did not find AWS SDK v3') + assert.deepStrictEqual(deps.sort(), [ 'a', 'b' ], 'Got correct deps') + assert.strictEqual(files.length, 1, 'Walked 1 js file') + assert.ok(!awsSdkV2, 'Did not find AWS SDK v2') + assert.ok(!awsSdkV3, 'Did not find AWS SDK v3') }) diff --git a/test/unit/src/actions/autoinstall/get-root-deps-tests.js b/test/unit/src/actions/autoinstall/get-root-deps-tests.js index e03dcfa..1427742 100644 --- a/test/unit/src/actions/autoinstall/get-root-deps-tests.js +++ b/test/unit/src/actions/autoinstall/get-root-deps-tests.js @@ -1,8 +1,10 @@ -let { join } = require('path') -let test = require('tape') -let mockTmp = require('mock-tmp') -let sut = join(process.cwd(), 'src', 'actions', 'autoinstall', 'node', 'get-root-deps') -let getRootDeps = require(sut) +const { join } = require('path') +const { mkdtempSync, rmSync, writeFileSync } = require('fs') +const { tmpdir } = require('os') +const { test } = require('node:test') +const assert = require('node:assert') +const sut = join(process.cwd(), 'src', 'actions', 'autoinstall', 'node', 'get-root-deps') +const getRootDeps = require(sut) function pkgify (deps, devDeps, lock) { let tmpl = { name: 'app' } @@ -15,23 +17,25 @@ function pkgify (deps, devDeps, lock) { let cwd let inventory = () => ({ inv: { _project: { cwd } } }) let run = fs => { - cwd = mockTmp(fs) + cwd = mkdtempSync(join(tmpdir(), 'test-')) + // Write files to temp directory + for (let [ filename, content ] of Object.entries(fs)) { + writeFileSync(join(cwd, filename), content) + } let result = getRootDeps(inventory()) - mockTmp.reset() + rmSync(cwd, { recursive: true, force: true }) return result } -test('Set up env', t => { - t.plan(1) - t.ok(getRootDeps, 'Dependency getter module is present') +test('Set up env', async () => { + assert.ok(getRootDeps, 'Dependency getter module is present') }) -test('package.json', t => { - t.plan(4) +test('package.json', async () => { let result result = run({ ok: 'hi' }) - t.deepEqual(result, {}, 'Got back empty object with no package.json present') + assert.deepStrictEqual(result, {}, 'Got back empty object with no package.json present') console.log(result) let deps = { @@ -39,7 +43,7 @@ test('package.json', t => { bar: '2.0.0', } result = run({ 'package.json': pkgify(deps) }) - t.deepEqual(result, deps, 'Got back dependencies (only)') + assert.deepStrictEqual(result, deps, 'Got back dependencies (only)') console.log(result) let devDeps = { @@ -47,16 +51,15 @@ test('package.json', t => { bar: '4.0.0', } result = run({ 'package.json': pkgify(null, devDeps) }) - t.deepEqual(result, devDeps, 'Got back devDependencies (only)') + assert.deepStrictEqual(result, devDeps, 'Got back devDependencies (only)') console.log(result) result = run({ 'package.json': pkgify(deps, devDeps) }) - t.deepEqual(result, deps, 'Dependencies won over devDependencies') + assert.deepStrictEqual(result, deps, 'Dependencies won over devDependencies') console.log(result) }) -test('package.json + package-lock.json', t => { - t.plan(4) +test('package.json + package-lock.json', async () => { let deps let lockDeps let correct @@ -79,18 +82,16 @@ test('package.json + package-lock.json', t => { foo: '1.2.3', bar: '2.3.4', } - t.deepEqual(result, correct, 'Got back specific dep versions from lockfile (lockfileVersion 1)') + assert.deepStrictEqual(result, correct, 'Got back specific dep versions from lockfile (lockfileVersion 1)') console.log(result) - mockTmp.reset() // v2 result = run({ 'package.json': pkgify(deps), 'package-lock.json': pkgify(lockDeps, null, 2), }) - t.deepEqual(result, correct, 'Got back specific dep versions from lockfile (lockfileVersion 2)') + assert.deepStrictEqual(result, correct, 'Got back specific dep versions from lockfile (lockfileVersion 2)') console.log(result) - mockTmp.reset() // v1 deps = { @@ -110,17 +111,14 @@ test('package.json + package-lock.json', t => { bar: '2.3.4', baz: '3.4.5', } - t.deepEqual(result, correct, 'Merged dep versions from package + lockfile (lockfileVersion 1)') + assert.deepStrictEqual(result, correct, 'Merged dep versions from package + lockfile (lockfileVersion 1)') console.log(result) - mockTmp.reset() // v2 result = run({ 'package.json': pkgify(deps), 'package-lock.json': pkgify(lockDeps, null, 2), }) - t.deepEqual(result, correct, 'Merged dep versions from package + lockfile (lockfileVersion 2)') + assert.deepStrictEqual(result, correct, 'Merged dep versions from package + lockfile (lockfileVersion 2)') console.log(result) - - mockTmp.reset() }) diff --git a/test/unit/src/actions/install-update-tests.js b/test/unit/src/actions/install-update-tests.js index ea357e2..5a67e7f 100644 --- a/test/unit/src/actions/install-update-tests.js +++ b/test/unit/src/actions/install-update-tests.js @@ -1,43 +1,39 @@ -/** -let test = require('tape') - -// Mock the child_process module to avoid actual command execution -let mockChildProcess = { - exec: (cmd, opts, callback) => { - // Mock successful execution - callback(null, 'mock success', '') - }, -} - -// Mock the _printer module -let mockPrinter = (params, callback) => { - callback() -} - -// Mock the lib module -let mockLib = { - destroyPath: () => {}, -} - -// Override requires for the install-update module -let Module = require('module') -let originalRequire = Module.prototype.require - -Module.prototype.require = function (id) { - if (id === 'child_process') return mockChildProcess - if (id === '../_printer') return mockPrinter - if (id === '../lib') return mockLib - return originalRequire.apply(this, arguments) -} - -let installUpdate = require('../../../../src/actions/install-update') +const { test } = require('node:test') +const assert = require('node:assert') +const Module = require('module') + +test('install-update handles absolute paths correctly', async () => { + // Mock modules using Module._load override + const originalLoad = Module._load + Module._load = function (request) { + if (request === 'child_process') { + return { + exec: (cmd, opts, callback) => { + callback(null, 'mock success', '') + }, + } + } + if (request === '../_printer') { + return (params, callback) => { + callback() + } + } + if (request === '../lib') { + return { + destroyPath: () => {}, + } + } + return originalLoad.apply(this, arguments) + } -// Restore original require -Module.prototype.require = originalRequire + // Clear require cache for install-update module + const modulePath = require.resolve('../../../../src/actions/install-update') + delete require.cache[modulePath] + const installUpdate = require('../../../../src/actions/install-update') -test('install-update handles absolute paths correctly', t => { - t.plan(1) + // Restore original Module._load + Module._load = originalLoad // Mock inventory with project cwd and lambdasBySrcDir let mockInventory = { @@ -78,13 +74,46 @@ test('install-update handles absolute paths correctly', t => { } // The test should complete without throwing an error - installUpdate(params, (err) => { - t.notOk(err, 'install-update completes successfully with absolute path') + await new Promise((resolve) => { + installUpdate(params, (err) => { + assert.ok(!err, 'install-update completes successfully with absolute path') + resolve() + }) }) }) -test('install-update handles relative paths correctly', t => { - t.plan(1) +test('install-update handles relative paths correctly', async () => { + // Mock modules using Module._load override + const originalLoad = Module._load + Module._load = function (request) { + if (request === 'child_process') { + return { + exec: (cmd, opts, callback) => { + callback(null, 'mock success', '') + }, + } + } + if (request === '../_printer') { + return (params, callback) => { + callback() + } + } + if (request === '../lib') { + return { + destroyPath: () => {}, + } + } + return originalLoad.apply(this, arguments) + } + + // Clear require cache for install-update module + const modulePath = require.resolve('../../../../src/actions/install-update') + delete require.cache[modulePath] + + const installUpdate = require('../../../../src/actions/install-update') + + // Restore original Module._load + Module._load = originalLoad // Mock inventory with project cwd and lambdasBySrcDir let mockInventory = { @@ -125,8 +154,10 @@ test('install-update handles relative paths correctly', t => { } // The test should complete without throwing an error - installUpdate(params, (err) => { - t.notOk(err, 'install-update completes successfully with relative path') + await new Promise((resolve) => { + installUpdate(params, (err) => { + assert.ok(!err, 'install-update completes successfully with relative path') + resolve() + }) }) }) -*/ diff --git a/test/unit/src/shared/get-paths-tests.js b/test/unit/src/shared/get-paths-tests.js index f4ae6e7..6983247 100644 --- a/test/unit/src/shared/get-paths-tests.js +++ b/test/unit/src/shared/get-paths-tests.js @@ -1,13 +1,20 @@ -let test = require('tape') -let mockTmp = require('mock-tmp') -let { join } = require('path') -let getPaths = require('../../../../src/shared/get-paths') -let lambdaPath = join('app', 'src', 'http', 'get-items') +const { test } = require('node:test') +const assert = require('node:assert') +const { mkdtempSync, rmSync, mkdirSync, writeFileSync } = require('fs') +const { tmpdir } = require('os') +const { join } = require('path') +const getPaths = require('../../../../src/shared/get-paths') -test('inventory with a shared path to hydrate and a single node runtime lambda aliased to a single directory should return a path to node modules', t => { - t.plan(3) - let tmp = mockTmp({ [lambdaPath]: 'fake file contents' }) - let path = join(tmp, lambdaPath) +test('inventory with a shared path to hydrate and a single node runtime lambda aliased to a single directory should return a path to node modules', async (t) => { + const lambdaPath = join('app', 'src', 'http', 'get-items') + const tmp = mkdtempSync(join(tmpdir(), 'test-')) + t.after(() => rmSync(tmp, { recursive: true, force: true })) + + const fullLambdaPath = join(tmp, lambdaPath) + mkdirSync(fullLambdaPath, { recursive: true }) + writeFileSync(join(fullLambdaPath, 'index.js'), 'fake file contents') + + let path = fullLambdaPath let inventory = { inv: { lambdasBySrcDir: { @@ -19,17 +26,21 @@ test('inventory with a shared path to hydrate and a single node runtime lambda a }, } let paths = getPaths(inventory) - t.equals(paths.all[path], join(path, 'node_modules', '@architect'), 'node runtime lambda returns node_modules path (all)') - t.notOk(Object.keys(paths.shared).length, 'Did not load any shared paths') - t.notOk(Object.keys(paths.views).length, 'Did not load any views paths') - mockTmp.reset() + assert.strictEqual(paths.all[path], join(path, 'node_modules', '@architect'), 'node runtime lambda returns node_modules path (all)') + assert.ok(!Object.keys(paths.shared).length, 'Did not load any shared paths') + assert.ok(!Object.keys(paths.views).length, 'Did not load any views paths') }) -test('inventory with a shared path to hydrate and a single non-node runtime lambda aliased to a single directory should return a path to vendor', t => { - t.plan(3) - let lambdaPath = join('app', 'src', 'http', 'get-items') - let tmp = mockTmp({ [lambdaPath]: 'fake file contents' }) - let path = join(tmp, lambdaPath) +test('inventory with a shared path to hydrate and a single non-node runtime lambda aliased to a single directory should return a path to vendor', async (t) => { + const lambdaPath = join('app', 'src', 'http', 'get-items') + const tmp = mkdtempSync(join(tmpdir(), 'test-')) + t.after(() => rmSync(tmp, { recursive: true, force: true })) + + const fullLambdaPath = join(tmp, lambdaPath) + mkdirSync(fullLambdaPath, { recursive: true }) + writeFileSync(join(fullLambdaPath, 'index.py'), 'fake file contents') + + let path = fullLambdaPath let inventory = { inv: { shared: { @@ -44,17 +55,21 @@ test('inventory with a shared path to hydrate and a single non-node runtime lamb }, } let paths = getPaths(inventory) - t.equals(paths.all[path], join(path, 'vendor'), 'non-node runtime lambda returns vendor path (all)') - t.equals(paths.shared[path], join(path, 'vendor'), 'non-node runtime lambda returns vendor path (shared)') - t.notOk(Object.keys(paths.views).length, 'Did not load any views paths') - mockTmp.reset() + assert.strictEqual(paths.all[path], join(path, 'vendor'), 'non-node runtime lambda returns vendor path (all)') + assert.strictEqual(paths.shared[path], join(path, 'vendor'), 'non-node runtime lambda returns vendor path (shared)') + assert.ok(!Object.keys(paths.views).length, 'Did not load any views paths') }) -test('inventory with a shared path to hydrate and multiple node runtime lambdas aliased to a single directory should return a single path to node_modules', t => { - t.plan(3) - let lambdaPath = join('app', 'src', 'http', 'get-items') - let tmp = mockTmp({ [lambdaPath]: 'fake file contents' }) - let path = join(tmp, lambdaPath) +test('inventory with a shared path to hydrate and multiple node runtime lambdas aliased to a single directory should return a single path to node_modules', async (t) => { + const lambdaPath = join('app', 'src', 'http', 'get-items') + const tmp = mkdtempSync(join(tmpdir(), 'test-')) + t.after(() => rmSync(tmp, { recursive: true, force: true })) + + const fullLambdaPath = join(tmp, lambdaPath) + mkdirSync(fullLambdaPath, { recursive: true }) + writeFileSync(join(fullLambdaPath, 'index.js'), 'fake file contents') + + let path = fullLambdaPath let inventory = { inv: { views: { @@ -70,8 +85,7 @@ test('inventory with a shared path to hydrate and multiple node runtime lambdas }, } let paths = getPaths(inventory) - t.equals(paths.all[path], join(path, 'node_modules', '@architect'), 'node runtime lambda returns node_modules path (all)') - t.equals(paths.views[path], join(path, 'node_modules', '@architect'), 'node runtime lambda returns node_modules path (views)') - t.notOk(Object.keys(paths.shared).length, 'Did not load any shared paths') - mockTmp.reset() + assert.strictEqual(paths.all[path], join(path, 'node_modules', '@architect'), 'node runtime lambda returns node_modules path (all)') + assert.strictEqual(paths.views[path], join(path, 'node_modules', '@architect'), 'node runtime lambda returns node_modules path (views)') + assert.ok(!Object.keys(paths.shared).length, 'Did not load any shared paths') })