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

[create-sitecore-jss] Allow proxies to be initialized with main app and rework angular initializer #1858

Merged
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ Our versioning strategy is as follows:
* XMCloud-based: 'angular,angular-xmcloud'
* Rework Angular initializer to support XMCloud and SXP journeys;

* `[create-sitecore-jss]` Rework Angular initializer to support XMCloud and SXP journeys ([#1845](https://github.com/Sitecore/jss/pull/1845))([#1858](https://github.com/Sitecore/jss/pull/1858))
* `[create-sitecore-jss]` Allows proxy apps to be installed alongside main apps ([#1858](https://github.com/Sitecore/jss/pull/1858))
* `nodeAppDestination` arg can be passed into `create-sitecore-jss` command to define path for proxy to be installed in

### 🛠 Breaking Change

### 🧹 Chores
Expand Down
227 changes: 151 additions & 76 deletions packages/create-sitecore-jss/src/bin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { sep } from 'path';
import chalk from 'chalk';
import inquirer from 'inquirer';
import { ParsedArgs } from 'minimist';
import { parseArgs, main } from './bin';
import { parseArgs, main, promptDestination, getDestinations } from './bin';
import * as helpers from './common/utils/helpers';
import * as initRunner from './init-runner';

Expand Down Expand Up @@ -37,6 +37,8 @@ describe('bin', () => {
'test',
'--destination',
'.\\test\\path',
'--proxyAppDestination',
'.\\test\\proxypath',
'--templates',
'foo,bar',
'--hostName',
Expand Down Expand Up @@ -231,34 +233,6 @@ describe('bin', () => {
});
});

it('should prompt for destination if missing', async () => {
getAllTemplatesStub.returns(['foo', 'bar']);
getBaseTemplatesStub.returns(['foo']);
fsExistsSyncStub.returns(false);
fsReaddirSyncStub.returns([]);
inquirerPromptStub.returns({
prePushHook: true,
});

const mockDestination = 'my\\path';
inquirerPromptStub.returns({
destination: mockDestination,
});

const args = mockArgs({
templates: 'foo',
});
const expectedTemplates = ['foo'];
await main(args);

expect(inquirerPromptStub).to.have.been.called;
expect(initRunnerStub).to.have.been.calledWith(expectedTemplates, {
...args,
destination: mockDestination,
templates: expectedTemplates,
});
});

it('should prompt for prePushHook if missing', async () => {
getAllTemplatesStub.returns(['foo', 'bar']);
getBaseTemplatesStub.returns(['foo']);
Expand Down Expand Up @@ -287,88 +261,189 @@ describe('bin', () => {
});
});

describe('destination default', () => {
it('should use appName', async () => {
getAllTemplatesStub.returns(['foo', 'bar']);
getBaseTemplatesStub.returns(['foo']);
fsExistsSyncStub.returns(false);
fsReaddirSyncStub.returns([]);

describe('promptDestination', () => {
it('should prompt with provided prompt text and return input value', async () => {
const mockDestination = 'my\\path';
const mockPrompt = 'Enter the mocking path';
inquirerPromptStub.returns({
destination: mockDestination,
});
const result = await promptDestination(mockPrompt, 'default');
expect(inquirerPromptStub).to.have.been.called;
expect(inquirerPromptStub.getCall(0).args[0].message).to.be.equal(mockPrompt);
expect(result).to.be.equal(mockDestination);
});

const args = mockArgs({
templates: 'foo',
appName: 'testApp',
it('should use default value', async () => {
inquirerPromptStub.returns({
destination: undefined,
});
const expectedTemplates = ['foo'];
const expectedDestinationDefault = `${process.cwd()}${sep + args.appName}`;
const defaultDestination = 'defa\\ult';
await promptDestination('use default here', defaultDestination);
expect(inquirerPromptStub).to.have.been.called;
expect(inquirerPromptStub.getCall(0).args[0].default()).to.be.equal(defaultDestination);
});
});

await main(args);
describe('getDestinations', () => {
const testTemplates = ['foo', 'bar'];

expect(inquirerPromptStub).to.have.been.called;
expect(inquirerPromptStub.getCall(0).args[0].default()).to.equal(
expectedDestinationDefault
);
expect(initRunnerStub).to.have.been.calledWith(expectedTemplates, {
...args,
destination: mockDestination,
templates: expectedTemplates,
it('should return base args.destination value only when provided', async () => {
const testPath = 'test\\path';
const testArgs = mockArgs({
destination: testPath,
});
expect(await getDestinations(testArgs, testTemplates)).to.deep.equal({
destination: testPath,
});
});

it('should use template if appName not provided', async () => {
getAllTemplatesStub.returns(['foo', 'bar']);
getBaseTemplatesStub.returns(['foo']);
fsExistsSyncStub.returns(false);
fsReaddirSyncStub.returns([]);
it('should return base and proxy destinations from args when templates contain proxy app', async () => {
const testPath = 'test\\path';
const proxyPath = 'proxy\\path';
const testArgs = mockArgs({
destination: testPath,
proxyAppDestination: proxyPath,
});
const templatesWithProxy = [...testTemplates, 'node-app-proxy'];
expect(await getDestinations(testArgs, templatesWithProxy)).to.deep.equal({
destination: testPath,
proxyAppDestination: proxyPath,
});
});

const mockDestination = 'my\\path';
it('should prompt to get base destination when args.destination is empty', async () => {
const testPath = 'test\\path';
inquirerPromptStub.returns({
destination: mockDestination,
destination: testPath,
});
const testArgs = mockArgs({
destination: undefined,
});
await getDestinations(testArgs, testTemplates);
expect(inquirerPromptStub).to.have.been.calledOnce;
expect(inquirerPromptStub.getCall(0).args[0].message).to.be.equal(
'Where would you like your new app created?'
);
});

const args = mockArgs({
templates: 'foo,bar',
it('should prompt for both base and proxy when destinations are missing in args and templates contain proxy app', async () => {
const testPath = 'test\\path';
const proxyPath = 'proxy\\path';
inquirerPromptStub.onCall(0).returns({
destination: testPath,
});
const expectedTemplates = ['foo', 'bar'];
const expectedDestinationDefault = `${process.cwd()}${sep + expectedTemplates[0]}`;
// avoid paths being equal - this case is tested further down
inquirerPromptStub.onCall(1).returns({
destination: proxyPath,
});
const testArgs = mockArgs({
destination: undefined,
proxyAppDestination: undefined,
});
const templatesWithProxy = [...testTemplates, 'node-app-proxy'];
await getDestinations(testArgs, templatesWithProxy);
expect(inquirerPromptStub).to.have.been.calledTwice;
expect(inquirerPromptStub.getCall(0).args[0].message).to.be.equal(
'Where would you like your new app created?'
);
expect(inquirerPromptStub.getCall(1).args[0].message).to.be.equal(
'Where would you like your proxy app created?'
);
});

await main(args);
it('should return default base destination with base template when --yes arg is used', async () => {
const testArgs = mockArgs({
destination: undefined,
yes: true,
});
const expectedDestination = `${process.cwd()}${sep + testTemplates[0]}`;
expect(await getDestinations(testArgs, testTemplates)).to.deep.equal({
destination: expectedDestination,
});
});

expect(inquirerPromptStub).to.have.been.called;
expect(inquirerPromptStub.getCall(0).args[0].default()).to.equal(
expectedDestinationDefault
it('should return default base destination with args.appName when provided and --yes arg is used', async () => {
const testAppName = 'myapp';
const testArgs = mockArgs({
destination: undefined,
appName: testAppName,
yes: true,
});
const expectedDestination = `${process.cwd()}${sep + testAppName}`;
expect(await getDestinations(testArgs, testTemplates)).to.deep.equal({
destination: expectedDestination,
});
});

it('should return default proxy destination when -- yes arg is used', async () => {
const testPath = 'test\\path';
const testArgs = mockArgs({
destination: testPath,
yes: true,
});
const templatesWithProxy = [...testTemplates, 'node-app-proxy'];
const expectedProxyDestination = `${process.cwd()}${sep + 'node-app-proxy'}`;
expect(await getDestinations(testArgs, templatesWithProxy)).to.deep.equal({
destination: testPath,
proxyAppDestination: expectedProxyDestination,
});
});

it('should prompt for proxy destination again if proxy destination is the same as base destination', async () => {
const testPath = 'test\\path';
const proxyPath = 'proxy\\path';
// avoid paths being equal - this case is tested further down
inquirerPromptStub.onCall(0).returns({
destination: proxyPath,
});
const testArgs = mockArgs({
destination: testPath,
proxyAppDestination: testPath,
});
const templatesWithProxy = [...testTemplates, 'node-app-proxy'];
await getDestinations(testArgs, templatesWithProxy);
expect(inquirerPromptStub).to.have.been.calledOnce;
expect(inquirerPromptStub.getCall(0).args[0].message).to.be.equal(
'Proxy app and base app cannot be located in the same folder. Please input another path for proxy'
);
expect(initRunnerStub).to.have.been.calledWith(expectedTemplates, {
...args,
destination: mockDestination,
templates: expectedTemplates,
});

it('should throw when templates are empty', async () => {
const testArgs = mockArgs();
await getDestinations(testArgs, []).catch((error) => {
expect(error.message).to.be.equal(
'Unable to get destinations, provided templates are empty'
);
});
});
});

it('should respect yes', async () => {
// this partially duplicates tests for getDestinations, but we need to ensure initRunnerStub is called with correct values
// no way around it however - sinon cannot mock getDestinations on its own, which could've prevented this
describe('main with destinations from args', () => {
it('should call initRunnerStub with values from getDestinations', async () => {
getAllTemplatesStub.returns(['foo', 'bar']);
getBaseTemplatesStub.returns(['foo']);
fsExistsSyncStub.returns(false);
fsReaddirSyncStub.returns([]);

const mockDestination = 'my\\path';
const proxyDestination = 'my\\proxy';

const args = mockArgs({
templates: 'foo',
appName: 'testApp',
yes: true,
destination: mockDestination,
proxyAppDestination: proxyDestination,
});
const expectedTemplates = ['foo'];
const expectedDestinationDefault = `${process.cwd()}${sep + args.appName}`;

await main(args);

expect(inquirerPromptStub).to.not.have.been.called;
expect(initRunnerStub).to.have.been.calledOnceWith(expectedTemplates, {
expect(initRunnerStub).to.have.been.calledWith(expectedTemplates, {
...args,
destination: expectedDestinationDefault,
destination: mockDestination,
proxyAppDestination: proxyDestination,
templates: expectedTemplates,
});
});
Expand Down
Loading