From c0248a8beb7e8e42b91f018bb47f1fd9af0db1b4 Mon Sep 17 00:00:00 2001 From: abetomo Date: Sun, 29 Mar 2026 08:51:58 +0900 Subject: [PATCH] fix(tests) v3: combat flakiness Port GH-830 changes to the v3 branch Co-authored-by: Chase --- test/main.js | 65 ++++++++++++++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 30 deletions(-) diff --git a/test/main.js b/test/main.js index e36327f..8172a14 100644 --- a/test/main.js +++ b/test/main.js @@ -95,6 +95,16 @@ const _timeout = function (params) { } } +const forceRemoveSync = (targetPath) => { + if (typeof fs.rmSync === 'function') { + fs.rmSync(targetPath, { recursive: true, force: true }) + return + } + // fs-extra's removeSync always removes recursively and handles non-existent paths gracefully, + // so no options are needed here. This is functionally equivalent to the rmSync call above. + fs.removeSync(targetPath) +} + // It does not completely reproduce the response of the actual API. const lambdaMockSettings = { addPermission: {}, @@ -142,14 +152,10 @@ const lambdaMockSettings = { /* global before, after, beforeEach, afterEach, describe, it */ describe('lib/main', function () { - if (process.platform === 'win32') { - // It seems that it takes very long time for file operation in Windows. - // So set `timeout(300000)` for the whole test. - this.timeout(300000) - } else if (process.platform === 'darwin') { - // It seems that it takes time for file operation in Mac. - // So set `timeout(120000)` for the whole test. - this.timeout(120000) + if (['win32', 'darwin'].includes(process.platform)) { + // It seems that it takes time for file operation in Windows and Mac. + // So set timeout(180000) (sec: 180) for the whole test. + this.timeout(180000) } before(() => { @@ -507,8 +513,8 @@ describe('lib/main', function () { fs.writeFileSync('fuga', '') }) after(() => { - ['fuga', '__unittest'].forEach((path) => { - fs.removeSync(path) + ['fuga', '__unittest'].forEach((targetPath) => { + forceRemoveSync(targetPath) }) }) @@ -589,7 +595,7 @@ describe('lib/main', function () { it('_fileCopy should not include package.json when --prebuiltDirectory is set', () => { const buildDir = '.build_' + Date.now() - after(() => fs.removeSync(buildDir)) + after(() => forceRemoveSync(buildDir)) fs.mkdirSync(buildDir) fs.writeFileSync(path.join(buildDir, 'testa'), '') @@ -623,7 +629,7 @@ describe('lib/main', function () { describe('when package-lock.json does not exist', () => { beforeEach(() => { - fs.removeSync(path.join(codeDirectory, 'package-lock.json')) + forceRemoveSync(path.join(codeDirectory, 'package-lock.json')) }) it('returns false', () => { @@ -746,7 +752,7 @@ describe('lib/main', function () { }) describe('_packageInstall', function () { - _timeout({ this: this, sec: 60 }) // ci should be faster than install + _timeout({ this: this, sec: 180 }) // ci should be faster than install // npm treats files as packages when installing, and so removes them. // Test with `devDependencies` packages that are not installed with the `--production` option. @@ -783,7 +789,7 @@ describe('lib/main', function () { fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson)) // Remove package-lock.json because it does not match the package.json to which optionalDependencies was added. - fs.removeSync(path.join(codeDirectory, 'package-lock.json')) + forceRemoveSync(path.join(codeDirectory, 'package-lock.json')) } const testOptionalDependenciesIsInstalled = async (packageManager) => { @@ -825,7 +831,7 @@ describe('lib/main', function () { describe('when package-lock.json does not exist', () => { beforeEach(() => { - return fs.removeSync(path.join(codeDirectory, 'package-lock.json')) + forceRemoveSync(path.join(codeDirectory, 'package-lock.json')) }) it('should use "npm install"', () => { @@ -878,7 +884,7 @@ describe('lib/main', function () { }) describe('_packageInstall (When codeDirectory contains characters to be escaped)', function () { - _timeout({ this: this, sec: 30 }) // give it time to build the node modules + _timeout({ this: this, sec: 180 }) // give it time to build the node modules beforeEach(() => { // Since '\' can not be included in the file or directory name in Windows @@ -892,7 +898,7 @@ describe('lib/main', function () { }) afterEach(() => { - fs.removeSync(codeDirectory) + forceRemoveSync(codeDirectory) codeDirectory = lambda._codeDirectory() }) @@ -981,7 +987,7 @@ describe('lib/main', function () { }) describe('_zip', function () { - _timeout({ this: this, sec: 60 }) // give it time to zip + _timeout({ this: this, sec: 180 }) // give it time to zip const beforeTask = async (packageManager) => { await lambda._cleanDirectory(codeDirectory) @@ -1051,7 +1057,7 @@ describe('lib/main', function () { describe('_archive', () => { // archive.files's name is a slash delimiter regardless of platform. it('installs and zips with an index.js file and node_modules/dotenv (It is also a test of `_buildAndArchive`)', function () { - _timeout({ this: this, sec: 30 }) // give it time to zip + _timeout({ this: this, sec: 180 }) // give it time to zip return lambda._archive({ ...program, sourceDirectory: sourceDirectoryForTest }).then((data) => { const archive = new Zip(data) @@ -1064,9 +1070,9 @@ describe('lib/main', function () { }) it('packages a prebuilt module without installing (It is also a test of `_archivePrebuilt`)', function () { - _timeout({ this: this, sec: 30 }) // give it time to zip + _timeout({ this: this, sec: 180 }) // give it time to zip const buildDir = '.build_' + Date.now() - after(() => fs.removeSync(buildDir)) + after(() => forceRemoveSync(buildDir)) fs.mkdirSync(buildDir) fs.mkdirSync(path.join(buildDir, 'd')) @@ -1092,11 +1098,11 @@ describe('lib/main', function () { }) it('cleans the temporary directory before running `_archivePrebuilt`', function () { - _timeout({ this: this, sec: 30 }) // give it time to zip + _timeout({ this: this, sec: 180 }) // give it time to zip const buildDir = '.build_' + Date.now() const codeDir = lambda._codeDirectory() const tmpFile = path.join(codeDir, 'deleteme') - after(() => fs.removeSync(buildDir)) + after(() => forceRemoveSync(buildDir)) fs.mkdirSync(codeDir, { recursive: true }) fs.writeFileSync(tmpFile, '...') @@ -1114,7 +1120,7 @@ describe('lib/main', function () { const testZipFile = path.join(os.tmpdir(), 'node-lambda-test.zip') let bufferExpected = null before(function () { - _timeout({ this: this, sec: 30 }) // give it time to zip + _timeout({ this: this, sec: 180 }) // give it time to zip return lambda._zip(program, codeDirectory).then((data) => { bufferExpected = data @@ -1159,7 +1165,7 @@ describe('lib/main', function () { deployZipfile: filePath, sourceDirectory: sourceDirectoryForTest } - _timeout({ this: this, sec: 30 }) // give it time to zip + _timeout({ this: this, sec: 180 }) // give it time to zip return lambda._archive(_program).then((data) => { // same test as "installs and zips with an index.js file and node_modules/dotenv" const archive = new Zip(data) @@ -1671,7 +1677,7 @@ describe('lib/main', function () { describe('Lambda.prototype.deploy()', () => { it('simple test with mock', function () { - _timeout({ this: this, sec: 30 }) // give it time to zip + _timeout({ this: this, sec: 180 }) // give it time to zip return lambda.deploy({ ...program, sourceDirectory: sourceDirectoryForTest }).then((result) => { assert.isUndefined(result) }) @@ -1683,10 +1689,9 @@ describe('lib/main', function () { return lambda._updateTags( lambdaClient, 'arn:aws:lambda:eu-central-1:1234567:function:test', - { tagKey: 'tagValue' }).then((result) => { - assert.deepEqual( - result, {} - ) + { tagKey: 'tagValue' } + ).then((result) => { + assert.deepEqual(result, {}) }) }) })