ember-cli
Version:
Command line tool for developing ambitious ember.js apps
174 lines (140 loc) • 4.99 kB
JavaScript
;
const symlinkOrCopySync = require('symlink-or-copy').sync;
const path = require('path');
const fs = require('fs-extra');
// eslint-disable-next-line n/no-unpublished-require
const tmp = require('tmp-promise');
const { execa } = require('execa');
const runCommand = require('./run-command');
const hasGlobalYarn = require('../helpers/has-global-yarn');
let root = path.resolve(__dirname, '..', '..');
const PackageCache = require('../../tests/helpers/package-cache');
const quickTemp = require('quick-temp');
let dirs = {};
let runCommandOptions = {
// Note: We must override the default logOnFailure logging, because we are
// not inside a test.
log() {
return; // no output for initial application build
},
};
function handleResult(result) {
if (result.output) {
console.log(result.output.join('\n'));
}
if (result.errors) {
console.log(result.errors.join('\n'));
}
throw result;
}
function applyCommand(command, name /*, ...flags*/) {
let flags = [].slice.call(arguments, 2, arguments.length);
let binaryPath = path.resolve(path.join(__dirname, '..', '..', 'bin', 'ember'));
let args = [binaryPath, command, name, '--watcher=node', '--skip-git', runCommandOptions];
flags.forEach(function (flag) {
args.splice(2, 0, flag);
});
return runCommand.apply(undefined, args);
}
/**
* @class PrivateTestHelpers
*/
/**
* Use `createTestTargets` in the before hook to do the initial
* setup of a project. This will ensure that we limit the amount of times
* we go to the network to fetch dependencies.
*
* @method createTestTargets
* @param {String} projectName The name of the project. Can be an app or addon.
* @param {Object} options
* @property {String} options.command The command you want to run
* @return {Promise} The result of the running the command
*/
function createTestTargets(projectName, options) {
console.warn(`**********************************************
** DO NOT USE createTestTargets ANY MORE! **
**********************************************
Use createAndInstallTestTargets() which doesn't use a complicated packageCache system
and relies on the pnpm store for caching instead.`);
let outputDir = quickTemp.makeOrReuse(dirs, projectName);
options = options || {};
options.command = options.command || 'new';
return applyCommand(options.command, projectName, '--skip-npm', `--directory=${outputDir}`).catch(handleResult);
}
/**
* Tears down the targeted project download directory
*/
function teardownTestTargets() {
// Remove all tmp directories created in this run.
let dirKeys = Object.keys(dirs);
for (let i = 0; i < dirKeys.length; i++) {
quickTemp.remove(dirs, dirKeys[i]);
}
}
/**
* Creates symbolic links from the dependency temp directories
* to the project that is under test.
*
* @method linkDependencies
* @param {String} projectName The name of the project under test
* @return {String} The path to the hydrated fixture.
*/
function linkDependencies(projectName) {
let sourceFixture = dirs[projectName]; // original fixture for this acceptance test.
let runFixture = quickTemp.makeOrRemake(dirs, `${projectName}-clone`);
fs.copySync(sourceFixture, runFixture);
let nodeManifest = fs.readFileSync(path.join(runFixture, 'package.json'));
let packageCache = new PackageCache(root);
let packager = hasGlobalYarn ? 'yarn' : 'npm';
packageCache.create('node', packager, nodeManifest, [{ name: 'ember-cli', path: root }]);
let nodeModulesPath = path.join(runFixture, 'node_modules');
symlinkOrCopySync(path.join(packageCache.get('node'), 'node_modules'), nodeModulesPath);
process.chdir(runFixture);
return runFixture;
}
/**
* Clean a test run.
*/
function cleanupRun(projectName) {
process.chdir(root);
quickTemp.remove(dirs, `${projectName}-clone`);
}
/**
*
* @param {string} projectName
* @param {string} options.command defaults to new
* @returns {Promise<{ result: string, path: string, cleanup: () => void }>} an object containing command result, path, and a cleanup function;
*/
async function createAndInstallTestTargets(projectName, options) {
let outputDir = await tmp.dir({ unsafeCleanup: true });
let command = options?.command ?? 'new';
let result = await applyCommand(command, projectName, '--skip-npm', `--directory=${outputDir.path}`);
await execa('pnpm', ['install', '--prefer-offline'], {
preferLocal: true,
cwd: outputDir.path,
});
for (let pkg of [
'.',
'packages/blueprint-model',
'packages/blueprint-blueprint',
'packages/app-blueprint',
'packages/addon-blueprint',
]) {
await execa('pnpm', ['link', path.join(__dirname, `../../${pkg}`)], {
preferLocal: true,
cwd: outputDir.path,
});
}
return {
result,
cleanup: outputDir.cleanup,
path: outputDir.path,
};
}
module.exports = {
createAndInstallTestTargets,
createTestTargets,
linkDependencies,
teardownTestTargets,
cleanupRun,
};