'use strict'; const path = require('path'); const fs = require('fs').promises; const assert = require('assert'); const pkgInstall = require('../src/cli/package-install'); describe('Package install lib', () => { /** * Important: * - The tests here have a beforeEach() run prior to each test, it resets * package.json and install/package.json back to identical states. * - Update `source` and `current` for testing. */ describe('updatePackageFile()', () => { let source; let current; const sourcePackagePath = path.resolve(__dirname, '../install/package.json'); const packageFilePath = path.resolve(__dirname, '../package.json'); before(async () => { // Move `install/package.json` and `package.json` out of the way for now await fs.copyFile(sourcePackagePath, path.resolve(__dirname, '../install/package.json.bak')); // safekeeping await fs.copyFile(packageFilePath, path.resolve(__dirname, '../package.json.bak')); // safekeeping }); beforeEach(async () => { await fs.copyFile(path.resolve(__dirname, '../install/package.json.bak'), sourcePackagePath); await fs.copyFile(sourcePackagePath, packageFilePath); // match files for testing source = JSON.parse(await fs.readFile(sourcePackagePath)); current = JSON.parse(await fs.readFile(packageFilePath)); }); it('should remove non-`nodebb-` modules not specified in `install/package.json`', async () => { source.dependencies.dotenv = '16.0.0'; await fs.writeFile(packageFilePath, JSON.stringify(source, null, 4)); delete source.dependencies.dotenv; pkgInstall.updatePackageFile(); // assert it removed the extra package const packageCleaned = JSON.parse(await fs.readFile(packageFilePath, 'utf8')); assert(!packageCleaned.dependencies.dotenv, 'dependency was not removed'); }); it('should merge new root level properties from `install/package.json` into `package.json`', async () => { source.bin = './nodebb'; await fs.writeFile(sourcePackagePath, JSON.stringify(source, null, 4)); pkgInstall.updatePackageFile(); const updated = JSON.parse(await fs.readFile(packageFilePath, 'utf8')); assert.deepStrictEqual(updated, source); }); it('should add new dependencies', async () => { source.dependencies['nodebb-plugin-foobar'] = '1.0.0'; await fs.writeFile(sourcePackagePath, JSON.stringify(source, null, 4)); pkgInstall.updatePackageFile(); const updated = JSON.parse(await fs.readFile(packageFilePath, 'utf8')); assert.deepStrictEqual(updated, source); }); it('should update version on dependencies', async () => { source.dependencies['nodebb-plugin-mentions'] = '1.0.0'; await fs.writeFile(sourcePackagePath, JSON.stringify(source, null, 4)); pkgInstall.updatePackageFile(); const updated = JSON.parse(await fs.readFile(packageFilePath, 'utf8')); assert.deepStrictEqual(updated, source); }); it('should deep merge nested objects', async () => { current.scripts.postinstall = 'echo "I am a silly bean";'; await fs.writeFile(packageFilePath, JSON.stringify(current, null, 4)); source.scripts.preinstall = 'echo "What are you?";'; await fs.writeFile(sourcePackagePath, JSON.stringify(source, null, 4)); source.scripts.postinstall = 'echo "I am a silly bean";'; pkgInstall.updatePackageFile(); const updated = JSON.parse(await fs.readFile(packageFilePath, 'utf8')); assert.deepStrictEqual(updated, source); assert.strictEqual(updated.scripts.postinstall, 'echo "I am a silly bean";'); assert.strictEqual(updated.scripts.preinstall, 'echo "What are you?";'); }); it('should remove extraneous devDependencies', async () => { current.devDependencies.expect = '27.5.1'; await fs.writeFile(packageFilePath, JSON.stringify(current, null, 4)); pkgInstall.updatePackageFile(); const updated = JSON.parse(await fs.readFile(packageFilePath, 'utf8')); assert.strictEqual(updated.devDependencies.hasOwnProperty('expect'), false); }); it('should handle if there is no package.json', async () => { await fs.unlink(packageFilePath); pkgInstall.updatePackageFile(); const updated = JSON.parse(await fs.readFile(packageFilePath, 'utf8')); assert.deepStrictEqual(updated, source); }); after(async () => { // Clean up await fs.rename(path.resolve(__dirname, '../install/package.json.bak'), sourcePackagePath); await fs.rename(path.resolve(__dirname, '../package.json.bak'), packageFilePath); }); }); });