Skip to content

Commit 96e8f63

Browse files
joehangoogle-labs-jules[bot]gemini-code-assist[bot]
authored
feat: Add unit tests for firestore feature initialization (#8996)
* feat: Add unit tests for firestore feature initialization Adds unit tests for the functions in `src/init/features/firestore`. This includes tests for: - `askQuestions` and `actuate` in `index.ts` - `initRules` and `getDefaultRules` in `rules.ts` - `initIndexes` in `indexes.ts` * format * Update src/init/features/firestore/index.spec.ts Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --------- Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
1 parent 2fb2577 commit 96e8f63

File tree

4 files changed

+259
-1
lines changed

4 files changed

+259
-1
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"lint:quiet": "npm run lint:ts -- --quiet && npm run lint:other",
2424
"lint:ts": "eslint --config .eslintrc.js --ext .ts,.js .",
2525
"mocha:fast": "mocha 'src/**/*.spec.{ts,js}'",
26-
"mocha": "nyc mocha 'src/**/*.spec.{ts,js}'",
26+
"mocha": "nyc --reporter=html mocha 'src/**/*.spec.{ts,js}'",
2727
"prepare": "npm run clean && npm run build:publish",
2828
"test": "npm run lint:quiet && npm run test:compile && npm run mocha",
2929
"test:apptesting": "npm run lint:quiet && npm run test:compile && nyc mocha 'src/apptesting/*.spec.{ts,js}'",
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import { expect } from "chai";
2+
import * as sinon from "sinon";
3+
import * as prompt from "../../../prompt";
4+
import * as config from "../../../config";
5+
import * as ensureApiEnabled from "../../../ensureApiEnabled";
6+
import { FirestoreApi } from "../../../firestore/api";
7+
import { askQuestions, actuate } from "./index";
8+
import * as rules from "./rules";
9+
import * as indexes from "./indexes";
10+
import { Setup } from "../..";
11+
12+
describe("firestore feature init", () => {
13+
let sandbox: sinon.SinonSandbox;
14+
15+
beforeEach(() => {
16+
sandbox = sinon.createSandbox();
17+
});
18+
19+
afterEach(() => {
20+
sandbox.restore();
21+
});
22+
23+
describe("askQuestions", () => {
24+
it("should prompt for database id and location", async () => {
25+
const setup: Setup = {
26+
config: {},
27+
rcfile: { projects: {}, targets: {}, etags: {} },
28+
projectId: "test-project",
29+
};
30+
const cfg = new config.Config({}, { projectDir: "/", cwd: "/" });
31+
sandbox.stub(ensureApiEnabled, "ensure").resolves();
32+
sandbox.stub(FirestoreApi.prototype, "listDatabases").resolves([]);
33+
sandbox.stub(FirestoreApi.prototype, "locations").resolves([
34+
{
35+
name: "projects/test-project/locations/us-central",
36+
locationId: "us-central",
37+
displayName: "us-central",
38+
labels: {},
39+
metadata: {},
40+
},
41+
]);
42+
const selectStub = sandbox.stub(prompt, "select").resolves("us-central");
43+
const initRulesStub = sandbox.stub(rules, "initRules").resolves();
44+
const initIndexesStub = sandbox.stub(indexes, "initIndexes").resolves();
45+
46+
await askQuestions(setup, cfg);
47+
48+
expect(selectStub.calledOnce).to.be.true;
49+
expect(initRulesStub.calledOnce).to.be.true;
50+
expect(initIndexesStub.calledOnce).to.be.true;
51+
});
52+
});
53+
54+
describe("actuate", () => {
55+
it("should write rules and indexes files", async () => {
56+
const setup: Setup = {
57+
config: {},
58+
rcfile: { projects: {}, targets: {}, etags: {} },
59+
featureInfo: {
60+
firestore: {
61+
rulesFilename: "firestore.rules",
62+
rules: "rules content",
63+
writeRules: true,
64+
indexesFilename: "firestore.indexes.json",
65+
indexes: "indexes content",
66+
writeIndexes: true,
67+
databaseId: "(default)",
68+
locationId: "us-central",
69+
},
70+
},
71+
};
72+
const cfg = new config.Config({}, { projectDir: "/", cwd: "/" });
73+
const writeStub = sandbox.stub(cfg, "writeProjectFile");
74+
75+
await actuate(setup, cfg);
76+
77+
expect(writeStub.calledTwice).to.be.true;
78+
expect(writeStub.firstCall.calledWith("firestore.rules", "rules content")).to.be.true;
79+
expect(writeStub.secondCall.calledWith("firestore.indexes.json", "indexes content")).to.be
80+
.true;
81+
});
82+
});
83+
});
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import { expect } from "chai";
2+
import * as sinon from "sinon";
3+
import * as prompt from "../../../prompt";
4+
import * as config from "../../../config";
5+
import { initIndexes, INDEXES_TEMPLATE } from "./indexes";
6+
import { FirestoreApi } from "../../../firestore/api";
7+
import { Setup } from "../..";
8+
9+
describe("firestore indexes", () => {
10+
let sandbox: sinon.SinonSandbox;
11+
12+
beforeEach(() => {
13+
sandbox = sinon.createSandbox();
14+
});
15+
16+
afterEach(() => {
17+
sandbox.restore();
18+
});
19+
20+
describe("initIndexes", () => {
21+
it("should prompt for indexes file and write default indexes", async () => {
22+
const setup: Setup = {
23+
config: {},
24+
rcfile: { projects: {}, targets: {}, etags: {} },
25+
};
26+
const cfg = new config.Config({}, { projectDir: "/", cwd: "/" });
27+
const inputStub = sandbox.stub(prompt, "input").resolves("firestore.indexes.json");
28+
const writeStub = sandbox.stub(cfg, "confirmWriteProjectFile").resolves(true);
29+
30+
await initIndexes(setup, cfg, {
31+
databaseId: "(default)",
32+
indexesFilename: "",
33+
indexes: "",
34+
writeIndexes: false,
35+
rulesFilename: "",
36+
rules: "",
37+
writeRules: false,
38+
locationId: "",
39+
});
40+
41+
expect(inputStub.calledOnce).to.be.true;
42+
expect(writeStub.calledOnceWith("firestore.indexes.json", INDEXES_TEMPLATE)).to.be.true;
43+
});
44+
45+
it("should download indexes from console", async () => {
46+
const setup: Setup = {
47+
config: {},
48+
rcfile: { projects: {}, targets: {}, etags: {} },
49+
projectId: "test-project",
50+
};
51+
const cfg = new config.Config({}, { projectDir: "/", cwd: "/" });
52+
const listIndexesStub = sandbox.stub(FirestoreApi.prototype, "listIndexes").resolves([]);
53+
const listFieldOverridesStub = sandbox
54+
.stub(FirestoreApi.prototype, "listFieldOverrides")
55+
.resolves([]);
56+
const makeIndexSpecStub = sandbox
57+
.stub(FirestoreApi.prototype, "makeIndexSpec")
58+
.returns({ indexes: [], fieldOverrides: [] });
59+
const writeStub = sandbox.stub(cfg, "confirmWriteProjectFile").resolves(true);
60+
61+
const info = {
62+
databaseId: "(default)",
63+
indexesFilename: "firestore.indexes.json",
64+
indexes: "",
65+
writeIndexes: false,
66+
rulesFilename: "",
67+
rules: "",
68+
writeRules: false,
69+
locationId: "",
70+
};
71+
await initIndexes(setup, cfg, info);
72+
73+
expect(listIndexesStub.calledOnceWith("test-project", "(default)")).to.be.true;
74+
expect(listFieldOverridesStub.calledOnceWith("test-project", "(default)")).to.be.true;
75+
expect(makeIndexSpecStub.calledOnceWith([], [])).to.be.true;
76+
expect(
77+
writeStub.calledOnceWith(
78+
"firestore.indexes.json",
79+
JSON.stringify({ indexes: [], fieldOverrides: [] }, null, 2),
80+
),
81+
).to.be.true;
82+
expect(info.indexes).to.equal(JSON.stringify({ indexes: [], fieldOverrides: [] }, null, 2));
83+
});
84+
});
85+
});
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import { expect } from "chai";
2+
import * as sinon from "sinon";
3+
import * as gcp from "../../../gcp";
4+
import * as prompt from "../../../prompt";
5+
import * as config from "../../../config";
6+
import { initRules, getDefaultRules } from "./rules";
7+
import { Setup } from "../..";
8+
9+
describe("firestore rules", () => {
10+
let sandbox: sinon.SinonSandbox;
11+
12+
beforeEach(() => {
13+
sandbox = sinon.createSandbox();
14+
});
15+
16+
afterEach(() => {
17+
sandbox.restore();
18+
});
19+
20+
describe("getDefaultRules", () => {
21+
it("should return the default rules with the correct date", () => {
22+
const date = new Date();
23+
date.setDate(date.getDate() + 30);
24+
const expectedDate = `${date.getFullYear()}, ${date.getMonth() + 1}, ${date.getDate()}`;
25+
const rules = getDefaultRules();
26+
expect(rules).to.include(
27+
`allow read, write: if request.time < timestamp.date(${expectedDate});`,
28+
);
29+
});
30+
});
31+
32+
describe("initRules", () => {
33+
it("should prompt for rules file and write default rules", async () => {
34+
const setup: Setup = {
35+
config: {},
36+
rcfile: { projects: {}, targets: {}, etags: {} },
37+
};
38+
const cfg = new config.Config({}, { projectDir: "/", cwd: "/" });
39+
sandbox.stub(prompt, "input").resolves("firestore.rules");
40+
sandbox.stub(cfg, "writeProjectFile");
41+
const confirmStub = sandbox.stub(cfg, "confirmWriteProjectFile").resolves(true);
42+
43+
await initRules(setup, cfg, {
44+
rulesFilename: "",
45+
rules: "",
46+
writeRules: false,
47+
databaseId: "",
48+
locationId: "",
49+
indexesFilename: "",
50+
indexes: "",
51+
writeIndexes: false,
52+
});
53+
54+
expect(confirmStub.calledOnceWith("firestore.rules", getDefaultRules())).to.be.true;
55+
});
56+
57+
it("should download rules from console", async () => {
58+
const setup: Setup = {
59+
config: {},
60+
rcfile: { projects: {}, targets: {}, etags: {} },
61+
projectId: "test-project",
62+
};
63+
const cfg = new config.Config({}, { projectDir: "/", cwd: "/" });
64+
const getRulesetNameStub = sandbox
65+
.stub(gcp.rules, "getLatestRulesetName")
66+
.resolves("ruleset-name");
67+
const getRulesetContentStub = sandbox
68+
.stub(gcp.rules, "getRulesetContent")
69+
.resolves([{ name: "file.rules", content: "console rules" }]);
70+
const writeStub = sandbox.stub(cfg, "confirmWriteProjectFile").resolves(true);
71+
72+
const info = {
73+
rulesFilename: "firestore.rules",
74+
rules: "",
75+
writeRules: false,
76+
databaseId: "",
77+
locationId: "",
78+
indexesFilename: "",
79+
indexes: "",
80+
writeIndexes: false,
81+
};
82+
await initRules(setup, cfg, info);
83+
84+
expect(getRulesetNameStub.calledOnceWith("test-project", "cloud.firestore")).to.be.true;
85+
expect(getRulesetContentStub.calledOnceWith("ruleset-name")).to.be.true;
86+
expect(writeStub.calledOnceWith("firestore.rules", "console rules")).to.be.true;
87+
expect(info.rules).to.equal("console rules");
88+
});
89+
});
90+
});

0 commit comments

Comments
 (0)