From 7f555711104ed4efd69ac112012a86e1a41d8aed Mon Sep 17 00:00:00 2001 From: Lukas Taegert-Atkinson Date: Thu, 30 Dec 2021 07:43:27 +0100 Subject: [PATCH] Stabilize watch tests (#4318) * Use atomic file writes * Use atomic file writes for regular watch tests * Increase timeout --- .../wait-for-bundle-input-object/_config.js | 5 +- .../samples/wait-for-bundle-input/_config.js | 3 +- .../cli/samples/watch/bundle-error/_config.js | 3 +- .../watch-config-early-update/_config.js | 3 +- .../watch/watch-config-error/_config.js | 5 +- .../watch-config-initial-error/_config.js | 3 +- .../watch/watch-config-no-update/_config.js | 3 +- test/utils.js | 11 ++ test/watch/index.js | 105 +++++++++--------- 9 files changed, 80 insertions(+), 61 deletions(-) diff --git a/test/cli/samples/wait-for-bundle-input-object/_config.js b/test/cli/samples/wait-for-bundle-input-object/_config.js index 981f3ba47a9..4bda6e35d5c 100644 --- a/test/cli/samples/wait-for-bundle-input-object/_config.js +++ b/test/cli/samples/wait-for-bundle-input-object/_config.js @@ -1,5 +1,6 @@ const fs = require('fs'); const path = require('path'); +const { atomicWriteFileSync } = require('../../../utils'); let second; let third; @@ -17,9 +18,9 @@ module.exports = { }, abortOnStderr(data) { if (data.includes('waiting for input second')) { - fs.writeFileSync(second, "export default 'second'"); + atomicWriteFileSync(second, "export default 'second'"); } else if (data.includes('waiting for input third')) { - fs.writeFileSync(third, "export default 'third'"); + atomicWriteFileSync(third, "export default 'third'"); } } }; diff --git a/test/cli/samples/wait-for-bundle-input/_config.js b/test/cli/samples/wait-for-bundle-input/_config.js index 045097c443b..64f197395b4 100644 --- a/test/cli/samples/wait-for-bundle-input/_config.js +++ b/test/cli/samples/wait-for-bundle-input/_config.js @@ -1,5 +1,6 @@ const fs = require('fs'); const path = require('path'); +const { atomicWriteFileSync } = require('../../../utils'); let mainFile; @@ -15,7 +16,7 @@ module.exports = { abortOnStderr(data) { if (data.includes('waiting for input main.js')) { // wait longer than one polling interval - setTimeout(() => fs.writeFileSync(mainFile, 'export default 42;'), 600); + setTimeout(() => atomicWriteFileSync(mainFile, 'export default 42;'), 600); } } }; diff --git a/test/cli/samples/watch/bundle-error/_config.js b/test/cli/samples/watch/bundle-error/_config.js index 7b101a1bc14..2f38a2e2407 100644 --- a/test/cli/samples/watch/bundle-error/_config.js +++ b/test/cli/samples/watch/bundle-error/_config.js @@ -1,5 +1,6 @@ const fs = require('fs'); const path = require('path'); +const { atomicWriteFileSync } = require('../../../../utils'); let mainFile; @@ -16,7 +17,7 @@ module.exports = { }, abortOnStderr(data) { if (data.includes('Error: Unexpected token')) { - setTimeout(() => fs.writeFileSync(mainFile, 'export default 42;'), 500); + setTimeout(() => atomicWriteFileSync(mainFile, 'export default 42;'), 500); return false; } if (data.includes('created _actual')) { diff --git a/test/cli/samples/watch/watch-config-early-update/_config.js b/test/cli/samples/watch/watch-config-early-update/_config.js index c13c2690ab6..d7b769c9058 100644 --- a/test/cli/samples/watch/watch-config-early-update/_config.js +++ b/test/cli/samples/watch/watch-config-early-update/_config.js @@ -1,5 +1,6 @@ const fs = require('fs'); const path = require('path'); +const { atomicWriteFileSync } = require('../../../../utils'); let configFile; @@ -34,7 +35,7 @@ module.exports = { }, abortOnStderr(data) { if (data === 'initial\n') { - fs.writeFileSync( + atomicWriteFileSync( configFile, ` console.error('updated'); diff --git a/test/cli/samples/watch/watch-config-error/_config.js b/test/cli/samples/watch/watch-config-error/_config.js index caa161f4052..149901b3e4e 100644 --- a/test/cli/samples/watch/watch-config-error/_config.js +++ b/test/cli/samples/watch/watch-config-error/_config.js @@ -1,5 +1,6 @@ const fs = require('fs'); const path = require('path'); +const { atomicWriteFileSync } = require('../../../../utils'); let configFile; @@ -25,12 +26,12 @@ module.exports = { }, abortOnStderr(data) { if (data.includes(`created _actual${path.sep}main1.js`)) { - fs.writeFileSync(configFile, 'throw new Error("Config contains errors");'); + atomicWriteFileSync(configFile, 'throw new Error("Config contains errors");'); return false; } if (data.includes('Config contains errors')) { setTimeout(() => { - fs.writeFileSync( + atomicWriteFileSync( configFile, 'export default {\n' + '\tinput: "main.js",\n' + diff --git a/test/cli/samples/watch/watch-config-initial-error/_config.js b/test/cli/samples/watch/watch-config-initial-error/_config.js index 9fd2eb4def9..d2ecd6532ec 100644 --- a/test/cli/samples/watch/watch-config-initial-error/_config.js +++ b/test/cli/samples/watch/watch-config-initial-error/_config.js @@ -1,5 +1,6 @@ const fs = require('fs'); const path = require('path'); +const { atomicWriteFileSync } = require('../../../../utils'); let configFile; @@ -16,7 +17,7 @@ module.exports = { async abortOnStderr(data) { if (data.includes('Config contains initial errors')) { await new Promise(resolve => setTimeout(resolve, 100)); - fs.writeFileSync( + atomicWriteFileSync( configFile, 'export default {\n' + '\tinput: "main.js",\n' + diff --git a/test/cli/samples/watch/watch-config-no-update/_config.js b/test/cli/samples/watch/watch-config-no-update/_config.js index 635d77d42d9..7bc29a79ab1 100644 --- a/test/cli/samples/watch/watch-config-no-update/_config.js +++ b/test/cli/samples/watch/watch-config-no-update/_config.js @@ -1,5 +1,6 @@ const fs = require('fs'); const path = require('path'); +const { atomicWriteFileSync } = require('../../../../utils'); let configFile; const configContent = @@ -23,7 +24,7 @@ module.exports = { }, abortOnStderr(data) { if (data.includes('created _actual/main.js')) { - fs.writeFileSync(configFile, configContent); + atomicWriteFileSync(configFile, configContent); return new Promise(resolve => setTimeout(() => resolve(true), 500)); } }, diff --git a/test/utils.js b/test/utils.js index beb2c60d97b..23aecff9d3a 100644 --- a/test/utils.js +++ b/test/utils.js @@ -1,4 +1,5 @@ const assert = require('assert'); +const fs = require('fs'); const path = require('path'); const fixturify = require('fixturify'); const sander = require('sander'); @@ -14,6 +15,7 @@ exports.runTestSuiteWithSamples = runTestSuiteWithSamples; exports.assertDirectoriesAreEqual = assertDirectoriesAreEqual; exports.assertFilesAreEqual = assertFilesAreEqual; exports.assertIncludes = assertIncludes; +exports.atomicWriteFileSync = atomicWriteFileSync; function normaliseError(error) { delete error.stack; @@ -220,3 +222,12 @@ function assertIncludes(actual, expected) { throw err; } } + +// Workaround a race condition in fs.writeFileSync that temporarily creates +// an empty file for a brief moment which may be read by rollup watch - even +// if the content being overwritten is identical. +function atomicWriteFileSync(filePath, contents) { + const stagingPath = filePath + '_'; + fs.writeFileSync(stagingPath, contents); + fs.renameSync(stagingPath, filePath); +} diff --git a/test/watch/index.js b/test/watch/index.js index f7d9124fb52..76a957fb634 100644 --- a/test/watch/index.js +++ b/test/watch/index.js @@ -2,6 +2,7 @@ const assert = require('assert'); const path = require('path'); const sander = require('sander'); const rollup = require('../../dist/rollup'); +const { atomicWriteFileSync } = require('../utils'); const cwd = process.cwd(); @@ -89,7 +90,7 @@ describe('rollup.watch', () => { if (triggerRestart) { triggerRestart = false; return wait(100) - .then(() => sander.writeFileSync('test/_tmp/input/main.js', 'export default 44;')) + .then(() => atomicWriteFileSync('test/_tmp/input/main.js', 'export default 44;')) .then(() => wait(100)) .then(() => code); } @@ -110,7 +111,7 @@ describe('rollup.watch', () => { () => { assert.strictEqual(run('../_tmp/output/bundle.js'), 42); triggerRestart = true; - sander.writeFileSync('test/_tmp/input/main.js', 'export default 43;'); + atomicWriteFileSync('test/_tmp/input/main.js', 'export default 43;'); }, 'START', 'BUNDLE_START', @@ -160,7 +161,7 @@ describe('rollup.watch', () => { 'END', () => { assert.strictEqual(run('../_tmp/output/bundle.js'), 42); - sander.writeFileSync( + atomicWriteFileSync( 'test/_tmp/input/main.js', "import {value} from 'virtual';\nexport default value + 1;" ); @@ -203,7 +204,7 @@ describe('rollup.watch', () => { () => { watchChangeCnt = 0; assert.strictEqual(run('../_tmp/output/bundle.js'), 42); - sander.writeFileSync('test/_tmp/input/main.js', 'export default 43;'); + atomicWriteFileSync('test/_tmp/input/main.js', 'export default 43;'); }, 'START', 'BUNDLE_START', @@ -212,7 +213,7 @@ describe('rollup.watch', () => { () => { assert.strictEqual(run('../_tmp/output/bundle.js'), 43); assert.strictEqual(watchChangeCnt, 1); - sander.writeFileSync('test/_tmp/input/main.js', 'export default 43;'); + atomicWriteFileSync('test/_tmp/input/main.js', 'export default 43;'); }, 'START', 'BUNDLE_START', @@ -221,7 +222,7 @@ describe('rollup.watch', () => { () => { assert.strictEqual(run('../_tmp/output/bundle.js'), 43); assert.strictEqual(watchChangeCnt, 2); - sander.writeFileSync('test/_tmp/input/main.js', 'export default 43;'); + atomicWriteFileSync('test/_tmp/input/main.js', 'export default 43;'); }, 'START', 'BUNDLE_START', @@ -272,7 +273,7 @@ describe('rollup.watch', () => { assert.strictEqual(run('../_tmp/output/bundle.js'), 42); assert.deepStrictEqual(events, []); assert.deepStrictEqual(ids, expectedIds); - sander.writeFileSync(WATCHED_ID, 'first'); + atomicWriteFileSync(WATCHED_ID, 'first'); }, 'START', 'BUNDLE_START', @@ -282,7 +283,7 @@ describe('rollup.watch', () => { assert.strictEqual(run('../_tmp/output/bundle.js'), 42); assert.deepStrictEqual(events, ['create']); assert.deepStrictEqual(ids, expectedIds); - sander.writeFileSync(WATCHED_ID, 'first'); + atomicWriteFileSync(WATCHED_ID, 'first'); }, 'START', 'BUNDLE_START', @@ -320,7 +321,7 @@ describe('rollup.watch', () => { exports: 'auto' }, watch: { - buildDelay: 300, + buildDelay: 600, chokidar: { atomic: false } @@ -345,7 +346,7 @@ describe('rollup.watch', () => { 'END', async () => { assert.strictEqual(lastEvent, null); - sander.writeFileSync(WATCHED_ID, 'another'); + atomicWriteFileSync(WATCHED_ID, 'another'); await wait(100); sander.unlinkSync(WATCHED_ID); }, @@ -356,11 +357,11 @@ describe('rollup.watch', () => { async () => { assert.strictEqual(lastEvent, 'delete'); lastEvent = null; - sander.writeFileSync(WATCHED_ID, '123'); + atomicWriteFileSync(WATCHED_ID, '123'); await wait(100); sander.unlinkSync(WATCHED_ID); // To ensure there is always another change to trigger a rebuild - sander.writeFileSync(MAIN_ID, 'export default 43;'); + atomicWriteFileSync(MAIN_ID, 'export default 43;'); }, 'START', 'BUNDLE_START', @@ -368,9 +369,9 @@ describe('rollup.watch', () => { 'END', async () => { assert.strictEqual(lastEvent, null); - sander.writeFileSync(WATCHED_ID, '123'); + atomicWriteFileSync(WATCHED_ID, '123'); await wait(100); - sander.writeFileSync(WATCHED_ID, 'asd'); + atomicWriteFileSync(WATCHED_ID, 'asd'); }, 'START', 'BUNDLE_START', @@ -459,7 +460,7 @@ describe('rollup.watch', () => { () => { assert.strictEqual(run('../_tmp/output/main1.js'), 21); assert.strictEqual(run('../_tmp/output/main2.js'), 42); - sander.writeFileSync('test/_tmp/input/shared.js', 'export const value = 22;'); + atomicWriteFileSync('test/_tmp/input/shared.js', 'export const value = 22;'); }, 'START', 'BUNDLE_START', @@ -498,7 +499,7 @@ describe('rollup.watch', () => { () => { assert.strictEqual(run('../_tmp/output/_main_1.js'), 21); assert.strictEqual(run('../_tmp/output/subfolder/_main_2.js'), 42); - sander.writeFileSync('test/_tmp/input/shared.js', 'export const value = 22;'); + atomicWriteFileSync('test/_tmp/input/shared.js', 'export const value = 22;'); }, 'START', 'BUNDLE_START', @@ -533,13 +534,13 @@ describe('rollup.watch', () => { 'END', () => { assert.strictEqual(run('../_tmp/output/bundle.js'), 42); - sander.writeFileSync('test/_tmp/input/main.js', 'export nope;'); + atomicWriteFileSync('test/_tmp/input/main.js', 'export nope;'); }, 'START', 'BUNDLE_START', 'ERROR', () => { - sander.writeFileSync('test/_tmp/input/main.js', 'export default 43;'); + atomicWriteFileSync('test/_tmp/input/main.js', 'export default 43;'); }, 'START', 'BUNDLE_START', @@ -572,7 +573,7 @@ describe('rollup.watch', () => { 'ERROR', () => { assert.strictEqual(sander.existsSync('../_tmp/output/bundle.js'), false); - sander.writeFileSync('test/_tmp/input/main.js', 'export default 43;'); + atomicWriteFileSync('test/_tmp/input/main.js', 'export default 43;'); }, 'START', 'BUNDLE_START', @@ -613,7 +614,7 @@ describe('rollup.watch', () => { 'ERROR', () => { assert.strictEqual(sander.existsSync('../_tmp/output/bundle.js'), false); - sander.writeFileSync('test/_tmp/input/main.js', 'export default 43;'); + atomicWriteFileSync('test/_tmp/input/main.js', 'export default 43;'); }, 'START', 'BUNDLE_START', @@ -648,14 +649,14 @@ describe('rollup.watch', () => { () => { assert.strictEqual(run('../_tmp/output/bundle.js'), 42); sander.unlinkSync('test/_tmp/input/main.js'); - sander.writeFileSync('test/_tmp/input/main.js', 'export nope;'); + atomicWriteFileSync('test/_tmp/input/main.js', 'export nope;'); }, 'START', 'BUNDLE_START', 'ERROR', () => { sander.unlinkSync('test/_tmp/input/main.js'); - sander.writeFileSync('test/_tmp/input/main.js', 'export default 43;'); + atomicWriteFileSync('test/_tmp/input/main.js', 'export default 43;'); }, 'START', 'BUNDLE_START', @@ -690,14 +691,14 @@ describe('rollup.watch', () => { () => { assert.strictEqual(run('../_tmp/output/bundle.js'), 43); sander.unlinkSync('test/_tmp/input/dep.js'); - sander.writeFileSync('test/_tmp/input/dep.js', 'export nope;'); + atomicWriteFileSync('test/_tmp/input/dep.js', 'export nope;'); }, 'START', 'BUNDLE_START', 'ERROR', () => { sander.unlinkSync('test/_tmp/input/dep.js'); - sander.writeFileSync('test/_tmp/input/dep.js', 'export const value = 43;'); + atomicWriteFileSync('test/_tmp/input/dep.js', 'export const value = 43;'); }, 'START', 'BUNDLE_START', @@ -735,7 +736,7 @@ describe('rollup.watch', () => { 'START', 'BUNDLE_START', () => { - sander.writeFileSync('test/_tmp/input/main.js', 'export default 44;'); + atomicWriteFileSync('test/_tmp/input/main.js', 'export default 44;'); return wait(400).then(() => assert.deepStrictEqual(events, ['START', 'BUNDLE_START'])); } ]); @@ -767,7 +768,7 @@ describe('rollup.watch', () => { 'START', 'BUNDLE_START', () => { - sander.writeFileSync('test/_tmp/input/main.js', 'export default 44;'); + atomicWriteFileSync('test/_tmp/input/main.js', 'export default 44;'); return wait(400).then(() => assert.deepStrictEqual(events, ['START', 'BUNDLE_START'])); } ]); @@ -795,7 +796,7 @@ describe('rollup.watch', () => { 'END', () => { assert.strictEqual(run('../_tmp/output/bundle.js'), 43); - sander.writeFileSync('test/_tmp/input/main.js', 'export default 42;'); + atomicWriteFileSync('test/_tmp/input/main.js', 'export default 42;'); }, 'START', 'BUNDLE_START', @@ -807,7 +808,7 @@ describe('rollup.watch', () => { watcher.once('event', event => { unexpectedEvent = event; }); - sander.writeFileSync('test/_tmp/input/dep.js', '= invalid'); + atomicWriteFileSync('test/_tmp/input/dep.js', '= invalid'); return wait(400).then(() => assert.strictEqual(unexpectedEvent, false)); } ]); @@ -835,14 +836,14 @@ describe('rollup.watch', () => { 'END', () => { assert.strictEqual(run('../_tmp/output/bundle.js'), 42); - sander.writeFileSync('test/_tmp/input/main.js', `import '../output/bundle.js'`); + atomicWriteFileSync('test/_tmp/input/main.js', `import '../output/bundle.js'`); }, 'START', 'BUNDLE_START', 'ERROR', event => { assert.strictEqual(event.error.message, 'Cannot import the generated bundle'); - sander.writeFileSync('test/_tmp/input/main.js', 'export default 43;'); + atomicWriteFileSync('test/_tmp/input/main.js', 'export default 43;'); }, 'START', 'BUNDLE_START', @@ -882,7 +883,7 @@ describe('rollup.watch', () => { foo: 'foo-1', bar: 'bar-1' }); - sander.writeFileSync('test/_tmp/input/foo.js', `export default 'foo-2';`); + atomicWriteFileSync('test/_tmp/input/foo.js', `export default 'foo-2';`); }, 'START', 'BUNDLE_START', @@ -897,7 +898,7 @@ describe('rollup.watch', () => { watcher.once('event', event => { unexpectedEvent = event; }); - sander.writeFileSync('test/_tmp/input/bar.js', "export default 'bar-2';"); + atomicWriteFileSync('test/_tmp/input/bar.js', "export default 'bar-2';"); return wait(400).then(() => { assert.deepStrictEqual(run('../_tmp/output/bundle.js'), { foo: 'foo-2', @@ -937,7 +938,7 @@ describe('rollup.watch', () => { foo: 'foo-1', bar: 'bar-1' }); - sander.writeFileSync('test/_tmp/input/foo.js', `export default 'foo-2';`); + atomicWriteFileSync('test/_tmp/input/foo.js', `export default 'foo-2';`); }, 'START', 'BUNDLE_START', @@ -952,7 +953,7 @@ describe('rollup.watch', () => { watcher.once('event', event => { unexpectedEvent = event; }); - sander.writeFileSync('test/_tmp/input/bar.js', "export default 'bar-2';"); + atomicWriteFileSync('test/_tmp/input/bar.js', "export default 'bar-2';"); return wait(400).then(() => { assert.deepStrictEqual(run('../_tmp/output/bundle.js'), { foo: 'foo-2', @@ -1000,7 +1001,7 @@ describe('rollup.watch', () => { () => { assert.deepStrictEqual(run('../_tmp/output/bundle1.js'), 42); assert.deepStrictEqual(run('../_tmp/output/bundle2.js'), 43); - sander.writeFileSync('test/_tmp/input/main2.js', 'export default 44'); + atomicWriteFileSync('test/_tmp/input/main2.js', 'export default 44'); }, 'START', 'BUNDLE_START', @@ -1113,7 +1114,7 @@ describe('rollup.watch', () => { 'END', () => { assert.strictEqual(run('../_tmp/output/bundle.js'), 42); - sander.writeFileSync('test/_tmp/input/[foo]/bar.js', `export const bar = 43;`); + atomicWriteFileSync('test/_tmp/input/[foo]/bar.js', `export const bar = 43;`); }, 'START', 'BUNDLE_START', @@ -1155,7 +1156,7 @@ describe('rollup.watch', () => { sander.rimrafSync('test/_tmp/output'); // this should only update the hash of that particular entry point - sander.writeFileSync( + atomicWriteFileSync( 'test/_tmp/input/main-static.js', "import {value} from './shared';\nexport default 2 * value;" ); @@ -1175,7 +1176,7 @@ describe('rollup.watch', () => { staticName = newStaticName; // this should update all hashes - sander.writeFileSync('test/_tmp/input/shared.js', 'export const value = 42;'); + atomicWriteFileSync('test/_tmp/input/shared.js', 'export const value = 42;'); }, 'START', 'BUNDLE_START', @@ -1227,13 +1228,13 @@ describe('rollup.watch', () => { 'END', () => { assert.strictEqual(run('../_tmp/output/bundle.js'), 42); - sander.writeFileSync('test/_tmp/input/main.js', 'export default "broken";'); + atomicWriteFileSync('test/_tmp/input/main.js', 'export default "broken";'); }, 'START', 'BUNDLE_START', 'ERROR', () => { - sander.writeFileSync('test/_tmp/input/main.js', INITIAL_CONTENT); + atomicWriteFileSync('test/_tmp/input/main.js', INITIAL_CONTENT); }, 'START', 'BUNDLE_START', @@ -1277,7 +1278,7 @@ describe('rollup.watch', () => { () => { watchChangeCnt = 0; assert.strictEqual(sander.existsSync('../_tmp/output/bundle.js'), false); - sander.writeFileSync('test/_tmp/input/main.js', 'export default 43;'); + atomicWriteFileSync('test/_tmp/input/main.js', 'export default 43;'); }, 'START', 'BUNDLE_START', @@ -1286,7 +1287,7 @@ describe('rollup.watch', () => { () => { assert.strictEqual(sander.existsSync('../_tmp/output/bundle.js'), false); assert.strictEqual(watchChangeCnt, 1); - sander.writeFileSync('test/_tmp/input/main.js', 'export default 43;'); + atomicWriteFileSync('test/_tmp/input/main.js', 'export default 43;'); }, 'START', 'BUNDLE_START', @@ -1295,7 +1296,7 @@ describe('rollup.watch', () => { () => { assert.strictEqual(sander.existsSync('../_tmp/output/bundle.js'), false); assert.strictEqual(watchChangeCnt, 2); - sander.writeFileSync('test/_tmp/input/main.js', 'export default 43;'); + atomicWriteFileSync('test/_tmp/input/main.js', 'export default 43;'); }, 'START', 'BUNDLE_START', @@ -1332,7 +1333,7 @@ describe('rollup.watch', () => { 'END', () => { assert.strictEqual(run('../_tmp/output/bundle.js'), 42); - sander.writeFileSync('test/_tmp/input/main.js', 'export default 43;'); + atomicWriteFileSync('test/_tmp/input/main.js', 'export default 43;'); startTime = process.hrtime(); }, 'START', @@ -1406,7 +1407,7 @@ describe('rollup.watch', () => { 'END', () => { assert.strictEqual(run('../_tmp/output/bundle.js'), 42); - sander.writeFileSync('test/_tmp/input/main.js', 'export default 43;'); + atomicWriteFileSync('test/_tmp/input/main.js', 'export default 43;'); startTime = process.hrtime(); }, 'START', @@ -1517,7 +1518,7 @@ describe('rollup.watch', () => { 'END', () => { assert.strictEqual(run('../_tmp/output/bundle.js'), 'initial'); - sander.writeFileSync(WATCHED_ID, 'next'); + atomicWriteFileSync(WATCHED_ID, 'next'); }, 'START', 'BUNDLE_START', @@ -1581,7 +1582,7 @@ describe('rollup.watch', () => { () => { assert.strictEqual(run('../_tmp/output/bundle.js'), 'initial'); addWatchFile = false; - sander.writeFileSync(WATCHED_ID, 'next'); + atomicWriteFileSync(WATCHED_ID, 'next'); }, 'START', 'BUNDLE_START', @@ -1589,7 +1590,7 @@ describe('rollup.watch', () => { 'END', () => { assert.strictEqual(run('../_tmp/output/bundle.js'), 'next'); - sander.writeFileSync(WATCHED_ID, 'other'); + atomicWriteFileSync(WATCHED_ID, 'other'); events.length = 0; return wait(400).then(() => assert.deepStrictEqual(events, [])); } @@ -1630,7 +1631,7 @@ describe('rollup.watch', () => { run('../_tmp/output/bundle.js'), `dep1: "export default 'dep2';", dep2: "dep2"` ); - sander.writeFileSync('test/_tmp/input/dep2.js', 'export default "next";'); + atomicWriteFileSync('test/_tmp/input/dep2.js', 'export default "next";'); }, 'START', 'BUNDLE_START', @@ -1715,7 +1716,7 @@ describe('rollup.watch', () => { 'END', () => { assert.strictEqual(run('../_tmp/output/bundle.js'), false); - sander.writeFileSync('test/_tmp/input/dep', ''); + atomicWriteFileSync('test/_tmp/input/dep', ''); }, 'START', 'BUNDLE_START', @@ -1764,7 +1765,7 @@ describe('rollup.watch', () => { 'END', () => { assert.strictEqual(run('../_tmp/output/bundle.js'), false); - sander.writeFileSync('test/_tmp/input/dep', ''); + atomicWriteFileSync('test/_tmp/input/dep', ''); }, 'START', 'BUNDLE_START', @@ -1812,7 +1813,7 @@ describe('rollup.watch', () => { 'END', () => { assert.strictEqual(transformRuns, 1); - sander.writeFileSync('test/_tmp/input/alsoWatched', 'next'); + atomicWriteFileSync('test/_tmp/input/alsoWatched', 'next'); }, 'START', 'BUNDLE_START',