Skip to content

Commit

Permalink
feat(package-properites): definied initial list of properties to sort…
Browse files Browse the repository at this point in the history
… in a package.json
  • Loading branch information
travi committed Aug 17, 2022
1 parent 1d6f8d0 commit 6aaa77c
Show file tree
Hide file tree
Showing 10 changed files with 96 additions and 23 deletions.
11 changes: 11 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@
"make-dir": "^3.1.0",
"mustache": "^4.2.0",
"npm-conf": "^1.1.3",
"sort-object-keys": "^1.1.3",
"touch": "^3.1.0",
"validate-npm-package-name": "^4.0.0"
}
Expand Down
36 changes: 17 additions & 19 deletions src/package/lifter-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {assert} from 'chai';
import any from '@travi/any';

import * as scriptsLifter from './scripts/lifter';
import * as propertySorter from './property-sorter';
import * as dependenciesInstaller from '../dependencies/installer';
import liftPackage from './lifter';

Expand All @@ -15,6 +16,7 @@ suite('package.json lifter', () => {
const pathToPackageJson = `${projectRoot}/package.json`;
const packageJsonContents = {...any.simpleObject(), scripts: any.simpleObject()};
const updatedScripts = any.simpleObject();
const sortedPackageContents = any.simpleObject();

setup(() => {
sandbox = sinon.createSandbox();
Expand All @@ -23,6 +25,7 @@ suite('package.json lifter', () => {
sandbox.stub(jsCore, 'writePackageJson');
sandbox.stub(fs, 'readFile');
sandbox.stub(scriptsLifter, 'default');
sandbox.stub(propertySorter, 'default');
});

teardown(() => sandbox.restore());
Expand All @@ -35,13 +38,11 @@ suite('package.json lifter', () => {
.withArgs(pathToPackageJson, 'utf8')
.resolves(JSON.stringify({...packageJsonContents, scripts: originalScripts}));
scriptsLifter.default.withArgs({existingScripts: originalScripts, scripts}).returns(updatedScripts);
propertySorter.default.withArgs({...packageJsonContents, scripts: updatedScripts}).returns(sortedPackageContents);

await liftPackage({projectRoot, scripts});

assert.calledWith(
jsCore.writePackageJson,
{projectRoot, config: {...packageJsonContents, scripts: updatedScripts}}
);
assert.calledWith(jsCore.writePackageJson, {projectRoot, config: sortedPackageContents});
});
});

Expand All @@ -54,13 +55,13 @@ suite('package.json lifter', () => {
scriptsLifter.default
.withArgs({existingScripts: packageJsonContents.scripts, scripts: undefined})
.returns(updatedScripts);
propertySorter.default
.withArgs({...packageJsonContents, scripts: updatedScripts, keywords: tags})
.returns(sortedPackageContents);

await liftPackage({projectRoot, tags});

assert.calledWith(
jsCore.writePackageJson,
{projectRoot, config: {...packageJsonContents, scripts: updatedScripts, keywords: tags}}
);
assert.calledWith(jsCore.writePackageJson, {projectRoot, config: sortedPackageContents});
});

test('that tags are added as keywords when some keywords already exist', async () => {
Expand All @@ -70,16 +71,13 @@ suite('package.json lifter', () => {
.withArgs(pathToPackageJson, 'utf8')
.resolves(JSON.stringify({...packageJsonContents, scripts: {}, keywords: existingKeywords}));
scriptsLifter.default.withArgs({existingScripts: {}, scripts: undefined}).returns(updatedScripts);
propertySorter.default
.withArgs({...packageJsonContents, scripts: updatedScripts, keywords: [...existingKeywords, ...tags]})
.returns(sortedPackageContents);

await liftPackage({projectRoot, tags});

assert.calledWith(
jsCore.writePackageJson,
{
projectRoot,
config: {...packageJsonContents, scripts: updatedScripts, keywords: [...existingKeywords, ...tags]}
}
);
assert.calledWith(jsCore.writePackageJson, {projectRoot, config: sortedPackageContents});
});

test('that keywords are not modified when some keywords already exist but none are provided', async () => {
Expand All @@ -88,13 +86,13 @@ suite('package.json lifter', () => {
.withArgs(pathToPackageJson, 'utf8')
.resolves(JSON.stringify({...packageJsonContents, scripts: {}, keywords: existingKeywords}));
scriptsLifter.default.withArgs({existingScripts: {}, scripts: {}}).returns(updatedScripts);
propertySorter.default
.withArgs({...packageJsonContents, scripts: updatedScripts, keywords: existingKeywords})
.returns(sortedPackageContents);

await liftPackage({projectRoot, scripts: {}});

assert.calledWith(
jsCore.writePackageJson,
{projectRoot, config: {...packageJsonContents, scripts: updatedScripts, keywords: existingKeywords}}
);
assert.calledWith(jsCore.writePackageJson, {projectRoot, config: sortedPackageContents});
});
});

Expand Down
5 changes: 3 additions & 2 deletions src/package/lifter.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {promises as fs} from 'fs';
import {error, info} from '@travi/cli-messages';
import {DEV_DEPENDENCY_TYPE, PROD_DEPENDENCY_TYPE, writePackageJson} from '@form8ion/javascript-core';

import sortPackageProperties from './property-sorter';
import {install} from '../dependencies';
import {lift as liftScripts} from './scripts';

Expand All @@ -22,13 +23,13 @@ export default async function ({

await writePackageJson({
projectRoot,
config: {
config: sortPackageProperties({
...existingPackageJsonContents,
scripts: liftScripts({existingScripts: existingPackageJsonContents.scripts, scripts}),
...tags && {
keywords: existingPackageJsonContents.keywords ? [...existingPackageJsonContents.keywords, ...tags] : tags
}
}
})
});
}

Expand Down
31 changes: 31 additions & 0 deletions src/package/property-sorter-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import {assert} from 'chai';
import any from '@travi/any';
import sinon from 'sinon';

import * as sortObjectKeys from '../../thirdparty-wrappers/sort-object-keys';
import sortProperties from './property-sorter';

suite('package.json property sorter', () => {
let sandbox;

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

sandbox.stub(sortObjectKeys, 'default');
});

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

test('that package properties are sorted based on the defined order', async () => {
const packageContents = any.simpleObject();
const sortedPackageContents = any.simpleObject();
sortObjectKeys.default
.withArgs(
packageContents,
['name', 'keywords', 'engines', 'scripts', 'dependencies', 'devDependencies', 'peerDependencies']
)
.returns(sortedPackageContents);

assert.deepEqual(sortProperties(packageContents), sortedPackageContents);
});
});
8 changes: 8 additions & 0 deletions src/package/property-sorter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import sortProperties from '../../thirdparty-wrappers/sort-object-keys';

export default function (packageContents) {
return sortProperties(
packageContents,
['name', 'keywords', 'engines', 'scripts', 'dependencies', 'devDependencies', 'peerDependencies']
);
}
8 changes: 8 additions & 0 deletions test/integration/features/lift/package-properties.feature
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,11 @@ Feature: Package Properties
When the scaffolder results are processed
Then the existing keywords still exist
And keywords from the results exist

Scenario: properties in random order
Given an "npm" lockfile exists
And a definition exists for engines.node
And there are existing keywords
And husky is not installed
When the scaffolder results are processed
Then the package.json properties are sorted
7 changes: 5 additions & 2 deletions test/integration/features/step_definitions/common-steps.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,13 @@ When('the scaffolder results are processed', async function () {
await fs.writeFile(
`${projectRoot}/package.json`,
JSON.stringify({
name: this.projectName,
...this.enginesNode && {engines: {node: this.enginesNode}},
devDependencies: {},
scripts: this.existingScripts,
peerDependencies: {},
keywords: this.existingKeywords,
...this.enginesNode && {engines: {node: this.enginesNode}}
dependencies: {},
name: this.projectName
})
);

Expand Down
9 changes: 9 additions & 0 deletions test/integration/features/step_definitions/config-steps.mjs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import {promises as fs} from 'fs';

import {fileExists} from '@form8ion/core';
import {assert} from 'chai';
import {Then} from '@cucumber/cucumber';
Expand All @@ -6,3 +8,10 @@ Then(/^Babel and ESLint are not scaffolded$/, async function () {
assert.isFalse(await fileExists(`${process.cwd()}/.eslintrc.yml`));
assert.isFalse(await fileExists(`${process.cwd()}/.babelrc.json`));
});

Then('the package.json properties are sorted', async function () {
assert.deepEqual(
Object.keys(JSON.parse(await fs.readFile(`${process.cwd()}/package.json`, 'utf-8'))),
['name', 'keywords', 'engines', 'scripts', 'dependencies', 'devDependencies', 'peerDependencies']
);
});
3 changes: 3 additions & 0 deletions thirdparty-wrappers/sort-object-keys.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import sortObjectKeys from 'sort-object-keys';

export default sortObjectKeys;

0 comments on commit 6aaa77c

Please sign in to comment.