Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sitecore-jss-cli package unit test coverage #1263

Merged
merged 9 commits into from
Dec 20, 2022
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion packages/sitecore-jss-cli/.nycrc
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,19 @@
".ts"
],
"exclude": [
"src/bin/**",
art-alexeyenko marked this conversation as resolved.
Show resolved Hide resolved
"**/*.d.ts",
"**/*.test.ts",
"src/test-data",
"dist",
"src/test.ts"
"src/test.ts",
"**/create.ts",
"**/deploy.package.ts",
"**/index.global.ts",
"**/index.ts",
"**/cli.global.ts",
"**/cli-shared.ts",
"src/resolve-package.ts"
],
"all": true,
"reporter": [
Expand Down
4 changes: 2 additions & 2 deletions packages/sitecore-jss-cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
"lint": "eslint ./src/**/*.ts",
"prepublishOnly": "npm run build",
"jss": "node ./dist/cjs/bin/jss.js",
"test": "mocha --require ts-node/register \"./src/**/*.test.ts\"",
"coverage": "nyc npm test"
"test": "mocha --require ts-node/register/transpile-only \"./src/**/*.test.ts\"",
"coverage": "nyc --require ts-node/register/transpile-only npm test"
art-alexeyenko marked this conversation as resolved.
Show resolved Hide resolved
},
"engines": {
"node": ">=12",
Expand Down
27 changes: 27 additions & 0 deletions packages/sitecore-jss-cli/src/cli.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { expect } from 'chai';
import sinon from 'sinon';
import { getPackageScriptCommands } from './cli';
import * as resolvePkg from './resolve-package';

describe('cli', () => {
describe('getPackageScriptCommands', async () => {
art-alexeyenko marked this conversation as resolved.
Show resolved Hide resolved
afterEach(() => {
sinon.restore();
});
const packageJson = {
scripts: {
first: 'do --this',
second: 'do --that',
third: 'do --all',
},
};

it('should read scripts from package.json', async () => {
sinon.stub(resolvePkg, 'default').resolves(packageJson);

const result = await getPackageScriptCommands();

expect(Object.keys(packageJson.scripts)).to.be.deep.equal(Object.keys(result));
art-alexeyenko marked this conversation as resolved.
Show resolved Hide resolved
});
});
});
2 changes: 1 addition & 1 deletion packages/sitecore-jss-cli/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import * as commands from './scripts';
/**
* Get package script commands
*/
async function getPackageScriptCommands() {
export async function getPackageScriptCommands() {
const packageJson = await resolvePackage();
const result: { [key: string]: CommandModule } = {};

Expand Down
130 changes: 130 additions & 0 deletions packages/sitecore-jss-cli/src/micro-manifest.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable no-unused-expressions */
/* eslint-disable @typescript-eslint/no-explicit-any */
import { expect } from 'chai';
import sinon from 'sinon';
import fs from 'fs';
import * as microManifest from './micro-manifest';
import * as resolvePkg from './resolve-package';
import * as manifestHandler from './scripts/manifest';
import * as packageHandler from './scripts/package';

import * as packageDeploy from '@sitecore-jss/sitecore-jss-dev-tools/dist/cjs/package-deploy';
import * as verify from '@sitecore-jss/sitecore-jss-dev-tools/dist/cjs/setup/verify-setup';
import * as resolveJssConfig from '@sitecore-jss/sitecore-jss-dev-tools/dist/cjs/resolve-scjssconfig';
import tmp from 'tmp';
import path from 'path';

describe('micro-manifest script', () => {
afterEach(() => {
sinon.restore();
});

const packageJson = {
config: {
appName: 'jss-unit-package',
},
};

const scJssConfig = {
sitecore: {
deploySecret: 'you-are-85%-water',
deployUrl: 'deploy.jss.com',
},
};

const argv = {
appName: 'jss-manifest',
deployUrl: 'customs.jss.com',
deploySecret: 'snape-kills-dumbledore',
debugSecurity: true,
acceptCertificate: 'yes',
};

const tmpDirReturnsDefault = {
err: false,
tempDir: 'C:/temp',
cleanupTempDir: sinon.stub(),
};

describe('verifyArgs', () => {
it('should use fallaback for appName, deployUrl, deploySecret, if not proided', async () => {
const localArgv = {
...argv,
appName: undefined,
deployUrl: undefined,
deploySecret: undefined,
};

const expectedArgv = {
...argv,
appName: packageJson.config.appName,
deployUrl: scJssConfig.sitecore.deployUrl,
deploySecret: scJssConfig.sitecore.deploySecret,
};

sinon.stub(verify, 'verifySetup');
sinon.stub(resolveJssConfig, 'resolveScJssConfig').resolves(scJssConfig);
sinon.stub(resolvePkg, 'default').resolves(packageJson);
expect(await microManifest.verifyArgs(localArgv)).to.deep.equal(expectedArgv);
});
});

describe('microManifest', () => {
it('should create temp directory and finalize manifest creation', async () => {
const tmpDirReturns = {
...tmpDirReturnsDefault,
cleanUpTempDir: sinon.stub(),
};

sinon.stub(resolveJssConfig, 'resolveScJssConfig').resolves(scJssConfig);
sinon.stub(resolvePkg, 'default').resolves(packageJson);
const tmpStub = sinon
.stub(tmp, 'dir')
.callsArgWith(1, tmpDirReturns.err, tmpDirReturns.tempDir, tmpDirReturns.cleanupTempDir);
const writeFileStub = sinon.stub(fs, 'writeFileSync');
sinon.stub(fs, 'existsSync').returns(true);
const manifestStub = sinon.stub(manifestHandler, 'handler');
const packageStub = sinon.stub(packageHandler, 'handler');
const deployStub = sinon.stub(packageDeploy, 'packageDeploy');

const manifestFolder = path.join(tmpDirReturnsDefault.tempDir, 'manifest');
const packageDir = path.join(tmpDirReturnsDefault.tempDir, 'package');
const manifestContents = 'stub';

const manifestArgs = {
manifestSourceFiles: [path.join(manifestFolder, 'tempManifestSource.js')],
manifestOutputPath: path.join(manifestFolder, 'tempManifest.json'),
noDictionary: true,
...argv,
};

const packageArgs = {
skipManifest: true,
noFiles: true,
packageOutputPath: path.join(packageDir, 'tempPackage.manifest.zip'),
...manifestArgs,
};

const deployArgs = {
appName: argv.appName,
packagePath: packageArgs.packageOutputPath,
importServiceUrl: argv.deployUrl,
secret: argv.deploySecret,
debugSecurity: argv.debugSecurity,
acceptCertificate: argv.acceptCertificate,
};

await microManifest.default(argv, manifestContents);

expect(tmpStub.called).to.be.true;
expect(
writeFileStub.calledWith(manifestArgs.manifestSourceFiles[0], manifestContents, 'utf8')
).to.be.true;
expect(manifestStub.calledWith(manifestArgs)).to.be.true;
expect(packageStub.calledWith(packageArgs)).to.be.true;
expect(deployStub.calledWith(deployArgs)).to.be.true;
expect(tmpDirReturns.cleanupTempDir.called).to.be.true;
});
});
});
72 changes: 40 additions & 32 deletions packages/sitecore-jss-cli/src/micro-manifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,38 +21,7 @@ export default async function microManifest(
) {
verifySetup();

const packageJson = await resolvePackage();

if (!argv.appName) {
argv.appName = packageJson.config.appName;
}
if (!argv.appName) {
throw new Error('App Name was not defined as a parameter or in the package.json config');
}

const jssConfig = await resolveScJssConfig({ configPath: argv.config as string });

if (!argv.deployUrl) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const legacyConfig = jssConfig.sitecore as any;
argv.deployUrl = legacyConfig.shipUrl ? legacyConfig.shipUrl : jssConfig.sitecore.deployUrl;
}
if (!argv.deployUrl) {
throw new Error('deployUrl was not defined as a parameter or in the scjssconfig.json file');
}

if (/\/ship\/services\/package/.test(argv.deployUrl)) {
throw new Error(
'deployUrl appears to be a Sitecore.Ship endpoint. JSS no longer uses Ship. You will need to reconfigure your endpoint to the JSS deploy service and provide an app shared secret to deploy.'
);
}

if (!argv.deploySecret) {
argv.deploySecret = jssConfig.sitecore.deploySecret;
}
if (!argv.deploySecret) {
throw new Error('deploySecret was not defined as a parameter or in the scjssconfig.json file');
}
argv = await verifyArgs(argv);

return new Promise<void>((resolve, reject) => {
tmp.dir({ unsafeCleanup: true }, async (err, tempDir, cleanupTempDir) => {
Expand Down Expand Up @@ -110,3 +79,42 @@ export default async function microManifest(
});
});
}

/**
*
*/
export async function verifyArgs(argv: { [key: string]: any }) {
art-alexeyenko marked this conversation as resolved.
Show resolved Hide resolved
const packageJson = await resolvePackage();
if (!argv.appName) {
argv.appName = packageJson.config.appName;
}
if (!argv.appName) {
throw new Error('App Name was not defined as a parameter or in the package.json config');
}

const jssConfig = await resolveScJssConfig({ configPath: argv.config as string });

if (!argv.deployUrl) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const legacyConfig = jssConfig.sitecore as any;
argv.deployUrl = legacyConfig.shipUrl ? legacyConfig.shipUrl : jssConfig.sitecore.deployUrl;
}
if (!argv.deployUrl) {
throw new Error('deployUrl was not defined as a parameter or in the scjssconfig.json file');
}

if (/\/ship\/services\/package/.test(argv.deployUrl)) {
throw new Error(
'deployUrl appears to be a Sitecore.Ship endpoint. JSS no longer uses Ship. You will need to reconfigure your endpoint to the JSS deploy service and provide an app shared secret to deploy.'
);
}

if (!argv.deploySecret) {
argv.deploySecret = jssConfig.sitecore.deploySecret;
}
if (!argv.deploySecret) {
throw new Error('deploySecret was not defined as a parameter or in the scjssconfig.json file');
}

return argv;
}
44 changes: 44 additions & 0 deletions packages/sitecore-jss-cli/src/scripts/clean.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable no-unused-expressions */
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable prettier/prettier */
import { expect } from 'chai';
import sinon from 'sinon';
import * as resolvePackage from '../resolve-package';
import { handler } from './clean';

import * as devTools from '@sitecore-jss/sitecore-jss-dev-tools/dist/cjs/clean';

describe('clean script', () => {

afterEach(() => {
sinon.restore();
});

it('clean should be called with path from argv', async () => {
const stub = sinon.stub(devTools, 'clean');
const argv = {
path: 'C:/The-Curious-Case-of-Benjamin-Button',
};

await handler(argv);
expect(stub.calledWith(argv)).to.equal(true);
});

it('should exit on missing path', async () => {
const processStub = sinon.stub(process, 'exit');
const logSpy = sinon.spy(console, 'error');
const errorMsg = 'Path argument was not specified and no \'buildArtifactsPath\' in package.json.';
const argv = { path: '' };

// ensure clean is not executed - since we stub process.exit - and the script execution will continue
const stub = sinon.stub(devTools, 'clean');
sinon.stub(resolvePackage, 'default').resolves({ config: { buildArtifactsPath: '' } });
const cleanImpl = require('./clean');

await cleanImpl.handler(argv);

expect(processStub.calledWith(1)).to.be.true;
expect(logSpy.getCall(0).args[0].toString()).to.contain(errorMsg);
});
});
36 changes: 36 additions & 0 deletions packages/sitecore-jss-cli/src/scripts/deploy.app.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable no-unused-expressions */
/* eslint-disable @typescript-eslint/no-explicit-any */
import { expect } from 'chai';
import sinon from 'sinon';
import * as deployFiles from './deploy.files';
import * as deployItems from './deploy.items';
import { handler } from './deploy.app';

describe('deploy.app script', () => {
afterEach(() => {
sinon.restore();
});

it('should deploy both items and files', async () => {
const deployFilesStub = sinon.stub(deployFiles, 'handler').resolves();
const deployItemsStub = sinon.stub(deployItems, 'handler').resolves();
const argv = {};
await handler(argv);

expect(deployItemsStub.calledWith(argv)).to.be.true;
expect(deployFilesStub.calledWith(argv)).to.be.true;
});

it('should log error and exit on deployItems error', async () => {
const errorMsg = 'Cant connect to Sitecore if youre a unit test :(';
const deployItemsStub = sinon.stub(deployItems, 'handler').rejects(errorMsg);
const processStub = sinon.stub(process, 'exit');
const logSpy = sinon.spy(console, 'log');
await handler({});

expect(deployItemsStub.called).to.be.true;
expect(processStub.calledWith(1)).to.be.true;
expect(logSpy.getCall(0).args[0].toString()).to.contain(errorMsg);
});
});
Loading