Skip to content

Commit

Permalink
Substitute project variables into params during update (#1588)
Browse files Browse the repository at this point in the history
* subsitutes project values into params during update

* works on tests

* cleans logs, adds await to test

* cleans tests, fixes whitespace

* switches to sinon.restore()

* fixes style

* formats

* changes tests to cover param subbing;

* adds tests for defaults
  • Loading branch information
joehan committed Aug 27, 2019
1 parent 60c3901 commit 3e4a99a
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 29 deletions.
7 changes: 6 additions & 1 deletion src/commands/ext-update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,12 @@ export default new Command("ext:update <instanceId>")
const newSource = await modsApi.getSource(sourceUrl);
const newSpec = newSource.spec;
await displayChanges(currentSpec, newSpec);
const newParams = await paramHelper.promptForNewParams(currentSpec, newSpec, currentParams);
const newParams = await paramHelper.promptForNewParams(
currentSpec,
newSpec,
currentParams,
projectId
);
const rolesToRemove = _.differenceWith(
currentSpec.roles,
_.get(newSpec, "roles", []),
Expand Down
2 changes: 1 addition & 1 deletion src/extensions/askUserForParam.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ export async function ask(
}

utils.logLabeledBullet(logPrefix, "answer the questions below to configure your extension:");
const substituted = substituteParams(paramSpecs, firebaseProjectParams) as Param[];
const substituted = substituteParams(paramSpecs, firebaseProjectParams);
const result: any = {};
const promises = _.map(substituted, (paramSpec: Param) => {
return async () => {
Expand Down
3 changes: 2 additions & 1 deletion src/extensions/modsHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { FirebaseError } from "../error";
import { checkResponse } from "./askUserForParam";
import { ensure } from "../ensureApiEnabled";
import * as getProjectId from "../getProjectId";
import { Param } from "./modsApi";
import { generateInstanceId } from "./generateInstanceId";
import { promptOnce } from "../prompt";
import * as logger from "../logger";
Expand Down Expand Up @@ -55,7 +56,7 @@ export async function getFirebaseProjectParams(projectId: string): Promise<any>
* @param params params to substitute the placeholders for
* @return Resources object with substituted params
*/
export function substituteParams(original: object[], params: { [key: string]: string }): object[] {
export function substituteParams(original: object[], params: { [key: string]: string }): Param[] {
const startingString = JSON.stringify(original);
const reduceFunction = (intermediateResult: string, paramVal: string, paramKey: string) => {
const regex = new RegExp("\\$\\{" + paramKey + "\\}", "g");
Expand Down
22 changes: 11 additions & 11 deletions src/extensions/paramHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import * as modsApi from "./modsApi";
import {
getFirebaseProjectParams,
populateDefaultParams,
substituteParams,
validateCommandLineParams,
} from "./modsHelper";
import * as askUserForParam from "./askUserForParam";
Expand Down Expand Up @@ -96,18 +97,17 @@ export async function getParams(
export async function promptForNewParams(
spec: modsApi.ModSpec,
newSpec: modsApi.ModSpec,
currentParams: { [option: string]: string }
currentParams: { [option: string]: string },
projectId: string
): Promise<any> {
const paramsDiffDeletions = _.differenceWith(
spec.params,
_.get(newSpec, "params", []),
_.isEqual
);
const paramsDiffAdditions = _.differenceWith(
newSpec.params,
_.get(spec, "params", []),
_.isEqual
);
const firebaseProjectParams = await getFirebaseProjectParams(projectId);

let paramsDiffDeletions = _.differenceWith(spec.params, _.get(newSpec, "params", []), _.isEqual);
paramsDiffDeletions = substituteParams(paramsDiffDeletions, firebaseProjectParams);

let paramsDiffAdditions = _.differenceWith(newSpec.params, _.get(spec, "params", []), _.isEqual);
paramsDiffAdditions = substituteParams(paramsDiffAdditions, firebaseProjectParams);

if (paramsDiffDeletions.length) {
logger.info("The following params will no longer be used:");
paramsDiffDeletions.forEach((param) => {
Expand Down
90 changes: 75 additions & 15 deletions src/test/extensions/paramHelper.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const TEST_PARAMS_2 = [
param: "NEW_PARAMETER",
label: "New Param",
type: ParamType.STRING,
default: "default",
default: "${PROJECT_ID}",
},
{
param: "THIRD_PARAMETER",
Expand Down Expand Up @@ -250,23 +250,32 @@ describe("paramHelper", () => {

describe("promptForNewParams", () => {
let promptStub: sinon.SinonStub;
let getFirebaseVariableStub: sinon.SinonStub;
beforeEach(() => {
promptStub = sinon.stub(prompt, "promptOnce");
getFirebaseVariableStub = sinon
.stub(modsHelper, "getFirebaseProjectParams")
.resolves({ PROJECT_ID });
});

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

it("should prompt the user for any params in the new spec that are not in the current one", async () => {
promptStub.resolves("user input");
const newSpec = _.cloneDeep(SPEC);
newSpec.params = TEST_PARAMS_2;

const newParams = await paramHelper.promptForNewParams(SPEC, newSpec, {
A_PARAMETER: "value",
ANOTHER_PARAMETER: "value",
});
const newParams = await paramHelper.promptForNewParams(
SPEC,
newSpec,
{
A_PARAMETER: "value",
ANOTHER_PARAMETER: "value",
},
PROJECT_ID
);

const expected = {
ANOTHER_PARAMETER: "value",
Expand All @@ -276,8 +285,49 @@ describe("paramHelper", () => {
expect(newParams).to.eql(expected);
expect(promptStub.callCount).to.equal(2);
expect(promptStub.firstCall.args).to.eql([
{
default: "test-proj",
message: "Enter a value for New Param:",
name: "NEW_PARAMETER",
type: "input",
},
]);
expect(promptStub.secondCall.args).to.eql([
{
default: "default",
message: "Enter a value for 3:",
name: "THIRD_PARAMETER",
type: "input",
},
]);
});

it("should populate the spec with the default value if it is returned by prompt", async () => {
promptStub.onFirstCall().resolves("test-proj");
promptStub.onSecondCall().resolves("user input");
const newSpec = _.cloneDeep(SPEC);
newSpec.params = TEST_PARAMS_2;

const newParams = await paramHelper.promptForNewParams(
SPEC,
newSpec,
{
A_PARAMETER: "value",
ANOTHER_PARAMETER: "value",
},
PROJECT_ID
);

const expected = {
ANOTHER_PARAMETER: "value",
NEW_PARAMETER: "test-proj",
THIRD_PARAMETER: "user input",
};
expect(newParams).to.eql(expected);
expect(promptStub.callCount).to.equal(2);
expect(promptStub.firstCall.args).to.eql([
{
default: "test-proj",
message: "Enter a value for New Param:",
name: "NEW_PARAMETER",
type: "input",
Expand All @@ -297,10 +347,15 @@ describe("paramHelper", () => {
promptStub.resolves("Fail");
const newSpec = _.cloneDeep(SPEC);

const newParams = await paramHelper.promptForNewParams(SPEC, newSpec, {
A_PARAMETER: "value",
ANOTHER_PARAMETER: "value",
});
const newParams = await paramHelper.promptForNewParams(
SPEC,
newSpec,
{
A_PARAMETER: "value",
ANOTHER_PARAMETER: "value",
},
PROJECT_ID
);

const expected = {
ANOTHER_PARAMETER: "value",
Expand All @@ -315,11 +370,16 @@ describe("paramHelper", () => {
const newSpec = _.cloneDeep(SPEC);
newSpec.params = TEST_PARAMS_2;

expect(
paramHelper.promptForNewParams(SPEC, newSpec, {
A_PARAMETER: "value",
ANOTHER_PARAMETER: "value",
})
await expect(
paramHelper.promptForNewParams(
SPEC,
newSpec,
{
A_PARAMETER: "value",
ANOTHER_PARAMETER: "value",
},
PROJECT_ID
)
).to.be.rejectedWith(FirebaseError, "this is an error");
// Ensure that we don't continue prompting if one fails
expect(promptStub).to.have.been.calledOnce;
Expand Down

0 comments on commit 3e4a99a

Please sign in to comment.