diff --git a/__mocks__/cpx.js b/__mocks__/cpx.js deleted file mode 100644 index 386ba31819..0000000000 --- a/__mocks__/cpx.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - copySync: jest.fn() -}; diff --git a/__mocks__/make-dir.js b/__mocks__/make-dir.js deleted file mode 100644 index 6ee585673e..0000000000 --- a/__mocks__/make-dir.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = jest.fn(); diff --git a/__mocks__/makef.js b/__mocks__/makef.js deleted file mode 100644 index f7048bba0a..0000000000 --- a/__mocks__/makef.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - createFile: jest.fn() -}; diff --git a/__mocks__/next-on-netlify.js b/__mocks__/next-on-netlify.js deleted file mode 100644 index 6ee585673e..0000000000 --- a/__mocks__/next-on-netlify.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = jest.fn(); diff --git a/index.js b/index.js index 5f093ab507..e81d3628e4 100644 --- a/index.js +++ b/index.js @@ -1,13 +1,18 @@ +const fs = require('fs') const path = require('path') +const util = require('util') + const nextOnNetlify = require('next-on-netlify') const { PHASE_PRODUCTION_BUILD } = require('next/constants') const { default: loadConfig } = require('next/dist/next-server/server/config') -const makef = require('makef') const makeDir = require('make-dir') const pathExists = require('path-exists') const cpx = require('cpx') + const isStaticExportProject = require('./helpers/isStaticExportProject') +const pWriteFile = util.promisify(fs.writeFile) + // * Helpful Plugin Context * // - Between the prebuild and build steps, the project's build command is run // - Between the build and postbuild steps, any functions are bundled @@ -64,7 +69,7 @@ module.exports = { target: 'serverless' } ` - makef.createFile({ 'next.config.js': nextConfig }) + await pWriteFile('next.config.js', nextConfig) console.log(`** Adding next.config.js with target set to 'serverless' **`) } }, diff --git a/package-lock.json b/package-lock.json index fafbf5a80c..7f230d21fb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9365,14 +9365,6 @@ "tmpl": "1.0.x" } }, - "makef": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/makef/-/makef-1.0.0.tgz", - "integrity": "sha512-i5y70loMn59Y7cA3L1tHCJygbONlZaA6GixFrjWNJ2x2BkSFZvgO/9LeWwAMyus7/Y++TIadv8jJsTtpLK0pug==", - "requires": { - "fs-extra": "8.x.x || 9.x.x" - } - }, "map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", @@ -9591,12 +9583,6 @@ "minimist": "^1.2.5" } }, - "mock-fs": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-4.13.0.tgz", - "integrity": "sha512-DD0vOdofJdoaRNtnWcrXe6RQbpHkPPmtqGq14uRX0F8ZKJ5nv89CVTYl/BZdppDxBDaV0hl75htg3abpEWlPZA==", - "dev": true - }, "move-concurrently": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", @@ -13547,6 +13533,24 @@ "setimmediate": "^1.0.4" } }, + "tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dev": true, + "requires": { + "rimraf": "^3.0.0" + } + }, + "tmp-promise": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.2.tgz", + "integrity": "sha512-OyCLAKU1HzBjL6Ev3gxUeraJNlbNingmi8IrHHEsYH8LTmEuhvYfqvhn2F/je+mjf4N58UmZ96OMEy1JanSCpA==", + "dev": true, + "requires": { + "tmp": "^0.2.0" + } + }, "tmpl": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", diff --git a/package.json b/package.json index 4ff7cef1f7..269998345c 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,6 @@ "dependencies": { "cpx": "^1.5.0", "make-dir": "^3.1.0", - "makef": "^1.0.0", "next": "^9.5.3", "next-on-netlify": "^2.6.0", "path-exists": "^4.0.0" @@ -35,10 +34,10 @@ "@netlify/eslint-config-node": "^0.3.0", "husky": "^4.3.0", "jest": "^26.6.1", - "mock-fs": "^4.13.0", "prettier": "^2.1.2", "react": "^17.0.1", - "react-dom": "^17.0.1" + "react-dom": "^17.0.1", + "tmp-promise": "^3.0.2" }, "husky": { "hooks": { @@ -47,7 +46,8 @@ }, "jest": { "testMatch": [ - "**/test/**/*.js" + "**/test/**/*.js", + "!**/test/fixtures/**" ], "verbose": true } diff --git a/test/fixtures/invalid_next_config/next.config.js b/test/fixtures/invalid_next_config/next.config.js new file mode 100644 index 0000000000..f72b6cf52f --- /dev/null +++ b/test/fixtures/invalid_next_config/next.config.js @@ -0,0 +1,3 @@ +module.exports = { + target: 'server', +} diff --git a/test/fixtures/publish_copy_files/out_publish/subdir/dummy.txt b/test/fixtures/publish_copy_files/out_publish/subdir/dummy.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/fixtures/publish_copy_files/publish/subdir/dummy.txt b/test/fixtures/publish_copy_files/publish/subdir/dummy.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/fixtures/publish_copy_files/subdir/dummy.txt b/test/fixtures/publish_copy_files/subdir/dummy.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/index.js b/test/index.js index 944633fdd9..c336c8f9ce 100644 --- a/test/index.js +++ b/test/index.js @@ -1,10 +1,13 @@ const path = require('path') +const process = require('process') + const nextOnNetlify = require('next-on-netlify') -const makef = require('makef') -const makeDir = require('make-dir') -const cpx = require('cpx') -const mockFs = require('mock-fs') -const plugin = require('../index') +const pathExists = require('path-exists') +const { dir: getTmpDir } = require('tmp-promise') + +const plugin = require('..') + +const FIXTURES_DIR = `${__dirname}/fixtures` const utils = { run: { @@ -15,21 +18,41 @@ const utils = { }, } -afterEach(() => { +// Temporary switch cwd +const changeCwd = function (cwd) { + const originalCwd = process.cwd() + process.chdir(cwd) + return process.chdir.bind(process, originalCwd) +} + +// Switch cwd to a fixture directory +const useFixture = function (fixtureName) { + const fixtureDir = `${FIXTURES_DIR}/${fixtureName}` + const restoreCwd = changeCwd(fixtureDir) + return { restoreCwd, fixtureDir } +} + +// In each test, we change cwd to a temporary directory. +// This allows us not to have to mock filesystem operations. +beforeEach(async () => { + const { path, cleanup } = await getTmpDir({ unsafeCleanup: true }) + const restoreCwd = changeCwd(path) + Object.assign(this, { cleanup, restoreCwd }) +}) + +afterEach(async () => { utils.build.failBuild.mockReset() utils.run.command.mockReset() jest.clearAllMocks() jest.resetAllMocks() + + // Cleans up the temporary directory from `getTmpDir()` and do not make it + // the current directory anymore + this.restoreCwd() + await this.cleanup() }) jest.mock('next-on-netlify') -jest.mock('makef') -jest.mock('make-dir') -jest.mock('cpx') - -// See: https://github.com/tschaub/mock-fs/issues/234#issuecomment-377862172 -// for why this log is required -console.log('Initializing tests') const DUMMY_PACKAGE_JSON = { name: 'dummy', version: '1.0.0' } @@ -94,24 +117,18 @@ describe('preBuild()', () => { constants: { FUNCTIONS_SRC: 'out_functions' }, }) - expect(makef.createFile.mock.calls.length).toEqual(1) + expect(await pathExists('next.config.js')).toBeTruthy() }) test(`fail build if the app's next config has an invalid target`, async () => { - mockFs({ - 'next.config.js': { - target: 'nonsense', - }, - }) - + const { restoreCwd } = useFixture('invalid_next_config') await plugin.onPreBuild({ netlifyConfig: {}, packageJson: DUMMY_PACKAGE_JSON, utils, constants: { FUNCTIONS_SRC: 'out_functions' }, }) - - mockFs.restore() + restoreCwd() const acceptableTargets = ['serverless', 'experimental-serverless-trace'] expect(utils.build.failBuild.mock.calls[0][0]).toEqual( @@ -139,17 +156,19 @@ describe('onBuild()', () => { }, }) - expect(makeDir.mock.calls[0][0]).toEqual(PUBLISH_DIR) + expect(await pathExists(PUBLISH_DIR)).toBeTruthy() }) test('calls copySync with correct args', async () => { - const PUBLISH_DIR = 'some/path' + const { restoreCwd, fixtureDir } = useFixture('publish_copy_files') + const PUBLISH_DIR = `${fixtureDir}/publish` await plugin.onBuild({ constants: { PUBLISH_DIR, }, }) + restoreCwd() - expect(cpx.copySync.mock.calls[0][0]).toEqual('out_publish/**/*', PUBLISH_DIR) + expect(await pathExists(`${PUBLISH_DIR}/subdir/dummy.txt`)).toBeTruthy() }) })