Skip to content
This repository has been archived by the owner on Dec 18, 2021. It is now read-only.

Commit

Permalink
feat(package-manager): determined manager when not provided in results
Browse files Browse the repository at this point in the history
  • Loading branch information
travi committed Apr 18, 2021
1 parent b463db5 commit 76019c9
Show file tree
Hide file tree
Showing 10 changed files with 131 additions and 4 deletions.
14 changes: 13 additions & 1 deletion src/lift-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import any from '@travi/any';
import {assert} from 'chai';
import * as packageLifter from './package';
import * as eslintLifter from './eslint/lift';
import * as packageManagerResolver from './package-manager';
import lift from './lift';

suite('lift', () => {
Expand All @@ -16,7 +17,16 @@ suite('lift', () => {
const dependencies = any.listOf(any.word);
const devDependencies = any.listOf(any.word);
const packageManager = any.word();
const results = {...any.simpleObject(), scripts, tags, eslintConfigs, dependencies, devDependencies, packageManager};
const manager = any.word();
const results = {
...any.simpleObject(),
scripts,
tags,
eslintConfigs,
dependencies,
devDependencies,
packageManager: manager
};
const huskyNextSteps = any.listOf(any.simpleObject);
const huskyLiftResults = {nextSteps: huskyNextSteps};

Expand All @@ -25,9 +35,11 @@ suite('lift', () => {

sandbox.stub(packageLifter, 'default');
sandbox.stub(eslintLifter, 'default');
sandbox.stub(packageManagerResolver, 'default');
sandbox.stub(huskyLifter, 'lift');

huskyLifter.lift.withArgs({projectRoot, packageManager}).resolves(huskyLiftResults);
packageManagerResolver.default.withArgs({projectRoot, packageManager: manager}).resolves(packageManager);
});

teardown(() => sandbox.restore());
Expand Down
4 changes: 3 additions & 1 deletion src/lift.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import deepmerge from 'deepmerge';
import {lift as liftHusky} from '@form8ion/husky';
import liftPackage from './package';
import liftEslint from './eslint';
import resolvePackageManager from './package-manager';

function configIsProvidedForEslint(configs) {
return configs && configs.eslint;
Expand All @@ -11,10 +12,11 @@ function configIsProvidedForEslint(configs) {
export default async function ({
projectRoot,
configs,
results: {scripts, tags, eslintConfigs, dependencies, devDependencies, packageManager}
results: {scripts, tags, eslintConfigs, dependencies, devDependencies, packageManager: manager}
}) {
info('Lifting JavaScript-specific details');

const packageManager = await resolvePackageManager({projectRoot, packageManager: manager});
const huskyResults = await liftHusky({projectRoot, packageManager});

if (configIsProvidedForEslint(configs)) {
Expand Down
47 changes: 47 additions & 0 deletions src/package-manager-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import * as core from '@form8ion/core';
import {packageManagers} from '@form8ion/javascript-core';
import any from '@travi/any';
import {assert} from 'chai';
import sinon from 'sinon';
import derive from './package-manager';

suite('package manager', () => {
let sandbox;
const projectRoot = any.string();

setup(() => {
sandbox = sinon.createSandbox();

sandbox.stub(core, 'fileExists');
});

teardown(() => sandbox.restore());

test('that an already defined manager is returned directly', async () => {
const packageManager = any.word();

assert.equal(await derive({packageManager}), packageManager);
});

test('that `npm` is returned when a package lockfile exists', async () => {
core.fileExists.withArgs(`${projectRoot}/package-lock.json`).resolves(true);

assert.equal(await derive({projectRoot}), packageManagers.NPM);
});

test('that `yarn` is returned when a yarn lockfile exists', async () => {
core.fileExists.withArgs(`${projectRoot}/yarn.lock`).resolves(true);

assert.equal(await derive({projectRoot}), packageManagers.YARN);
});

test('that an error is thrown when no manager is provided and no lockfile is found', async () => {
try {
await derive({projectRoot});

throw new Error('test should have thrown before this point');
} catch (e) {
assert.equal(e.message, 'Package-manager could not be determined');
}
});
});
16 changes: 16 additions & 0 deletions src/package-manager.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import {fileExists} from '@form8ion/core';
import {packageManagers} from '@form8ion/javascript-core';

export default async function ({projectRoot, packageManager}) {
if (packageManager) return packageManager;

if (await fileExists(`${projectRoot}/package-lock.json`)) {
return packageManagers.NPM;
}

if (await fileExists(`${projectRoot}/yarn.lock`)) {
return packageManagers.YARN;
}

throw new Error('Package-manager could not be determined');
}
2 changes: 2 additions & 0 deletions test/integration/features/eslint-configs.feature
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ Feature: ESLint Configs

Scenario: No existing config
Given no existing eslint config file is present
And "npm" is the package manager
And husky is not installed
When the scaffolder results are processed
Then no eslint config file exists

Scenario: existing yaml config
Given an existing eslint config file is present
And "npm" is the package manager
And husky is not installed
When the scaffolder results are processed
Then the yaml eslint config file contains the expected config
26 changes: 26 additions & 0 deletions test/integration/features/husky.feature
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,40 @@ Feature: Husky
Then husky is configured for "npm"
And the v4 config is removed

Scenario: Husky v5 installed, v4 config
Given husky v5 is installed
And "yarn" is the package manager
And husky config is in v4 format
When the scaffolder results are processed
Then husky is configured for "yarn"
And the v4 config is removed

Scenario: Husky v5 installed, v4 config
Given husky v5 is installed
And an "npm" lockfile exists
And husky config is in v4 format
When the scaffolder results are processed
Then husky is configured for "npm"
And the v4 config is removed

Scenario: Husky v5 installed, v4 config
Given husky v5 is installed
And an "yarn" lockfile exists
And husky config is in v4 format
When the scaffolder results are processed
Then husky is configured for "yarn"
And the v4 config is removed

Scenario: Husky v5 installed, v5 config
Given husky v5 is installed
And "npm" is the package manager
And husky config is in v5 format
When the scaffolder results are processed
Then the next-steps do not include a warning about the husky config

Scenario: Husky v4 installed, v4 config
Given husky v4 is installed
And "npm" is the package manager
And husky config is in v4 format
When the scaffolder results are processed
Then the next-steps do not include a warning about the husky config
2 changes: 2 additions & 0 deletions test/integration/features/package-properties.feature
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ Feature: Package Properties

Scenario: Tags results when no existing keywords
Given there are no existing keywords
And "npm" is the package manager
And tags are provided in the results
And husky is not installed
When the scaffolder results are processed
Then keywords from the results exist

Scenario: Tags results when some keywords exist
Given there are existing keywords
And "npm" is the package manager
And tags are provided in the results
And husky is not installed
When the scaffolder results are processed
Expand Down
3 changes: 3 additions & 0 deletions test/integration/features/scripts.feature
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,23 @@ Feature: Scripts

Scenario: No Additional Scripts from Results
Given no additional scripts are included in the results
And "npm" is the package manager
And husky is not installed
When the scaffolder results are processed
Then the existing scripts still exist
And no extra scripts were added

Scenario: Additional Scripts Are Present in Results
Given additional scripts are included in the results
And "npm" is the package manager
And husky is not installed
When the scaffolder results are processed
Then the existing scripts still exist
And the additional scripts exist

Scenario: Duplicate Scripts Are Present in Results
Given additional scripts that duplicate existing scripts are included in the results
And "npm" is the package manager
And husky is not installed
When the scaffolder results are processed
Then the additional scripts exist
13 changes: 12 additions & 1 deletion test/integration/features/step_definitions/common-steps.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import {resolve} from 'path';
import {promises as fs} from 'fs';
import {packageManagers} from '@form8ion/javascript-core';
import stubbedFs from 'mock-fs';
import td from 'testdouble';
import importFresh from 'import-fresh';
import clearModule from 'clear-module';
import any from '@travi/any';
import {After, Before, When} from 'cucumber';
import {After, Before, Given, When} from 'cucumber';

const pathToNodeModules = [__dirname, '../../../../', 'node_modules/'];
const stubbedNodeModules = stubbedFs.load(resolve(...pathToNodeModules));
Expand All @@ -29,6 +30,16 @@ After(function () {
clearModule('@form8ion/javascript-core');
});

Given('an {string} lockfile exists', async function (packageManager) {
if (packageManagers.NPM === packageManager) {
await fs.writeFile(`${process.cwd()}/package-lock.json`, JSON.stringify(any.simpleObject()));
}

if (packageManagers.YARN === packageManager) {
await fs.writeFile(`${process.cwd()}/yarn.lock`, any.string());
}
});

When('the scaffolder results are processed', async function () {
await fs.writeFile(
`${process.cwd()}/package.json`,
Expand Down
8 changes: 7 additions & 1 deletion test/integration/features/step_definitions/husky-steps.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {Given, Then} from 'cucumber';
import any from '@travi/any';
import td from 'testdouble';
import {assert} from 'chai';
import {packageManagers} from '@form8ion/javascript-core';

export async function assertHookContainsScript(hook, script) {
const hookContents = await fs.readFile(`${process.cwd()}/.husky/${hook}`, 'utf-8');
Expand Down Expand Up @@ -66,7 +67,12 @@ Then('the next-steps do not include a warning about the husky config', async fun
});

Then('husky is configured for {string}', async function (packageManager) {
td.verify(this.execa(td.matchers.contains('. ~/.nvm/nvm.sh && nvm use && npm install')), {ignoreExtraArgs: true});
if (packageManagers.NPM === packageManager) {
td.verify(this.execa(td.matchers.contains('. ~/.nvm/nvm.sh && nvm use && npm install')), {ignoreExtraArgs: true});
}
if (packageManagers.YARN === packageManager) {
td.verify(this.execa(td.matchers.contains('. ~/.nvm/nvm.sh && nvm use && yarn add')), {ignoreExtraArgs: true});
}
td.verify(this.execa(td.matchers.contains('husky@latest')), {ignoreExtraArgs: true});
assert.equal(
JSON.parse(await fs.readFile(`${process.cwd()}/package.json`, 'utf-8')).scripts.prepare,
Expand Down

0 comments on commit 76019c9

Please sign in to comment.