Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
210 changes: 210 additions & 0 deletions src/init/features/hosting/index.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
import { expect } from "chai";
import * as sinon from "sinon";
import * as prompt from "../../../prompt";
import * as config from "../../../config";
import * as getDefaultHostingSiteMod from "../../../getDefaultHostingSite";
import * as hostingInteractive from "../../../hosting/interactive";
import * as hostingApi from "../../../hosting/api";
import { Client } from "../../../apiv2";
import { askQuestions, actuate } from "./index";
import { Setup } from "../..";
import * as github from "./github";

describe("hosting feature init", () => {
let sandbox: sinon.SinonSandbox;

beforeEach(() => {
sandbox = sinon.createSandbox();
});

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

describe("askQuestions", () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The mock options object is created inline with as any in multiple tests. To improve readability, reduce repetition, and make it easier to manage, consider defining a constant for these mock options at the top of the describe block and reusing it in your tests.

it("should prompt for public directory and spa", async () => {
const setup: Setup = {
config: {},
rcfile: { projects: {}, targets: {}, etags: {} },
projectId: "test-project",
instructions: [],
};
const cfg = new config.Config({}, { projectDir: "/", cwd: "/" });

// Mock existing site check
sandbox.stub(getDefaultHostingSiteMod, "getDefaultHostingSite").resolves("test-site");

const inputStub = sandbox.stub(prompt, "input").resolves("public");
const confirmStub = sandbox.stub(prompt, "confirm").resolves(false);
sandbox.stub(github, "initGitHub").resolves();

await askQuestions(setup, cfg, {
cwd: "/",
configPath: "",
only: "",
except: "",
nonInteractive: false,
} as any);

expect(
inputStub.calledWith(
sinon.match({ message: "What do you want to use as your public directory?" }),
),
).to.be.true;
expect(
confirmStub.calledWith(
sinon.match("Configure as a single-page app (rewrite all urls to /index.html)?"),
),
).to.be.true;

expect(setup.featureInfo?.hosting).to.deep.include({
public: "public",
spa: false,
});
});

it("should prompt to create a site if none exists", async () => {
const setup: Setup = {
config: {},
rcfile: { projects: {}, targets: {}, etags: {} },
projectId: "test-project",
instructions: [],
};
const cfg = new config.Config({}, { projectDir: "/", cwd: "/" });

sandbox
.stub(getDefaultHostingSiteMod, "getDefaultHostingSite")
.rejects(getDefaultHostingSiteMod.errNoDefaultSite);
sandbox.stub(prompt, "confirm").resolves(true);
const pickSiteStub = sandbox
.stub(hostingInteractive, "pickHostingSiteName")
.resolves("new-site-id");
sandbox.stub(prompt, "input").resolves("public");
sandbox.stub(github, "initGitHub").resolves();

await askQuestions(setup, cfg, {
cwd: "/",
configPath: "",
only: "",
except: "",
nonInteractive: false,
} as any);

expect(pickSiteStub.called).to.be.true;
expect(setup.featureInfo?.hosting?.newSiteId).to.equal("new-site-id");
});
});

describe("actuate", () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The stub for Client.prototype.get is repeated across all tests within this describe block. To reduce code duplication and improve maintainability, consider moving this common setup into a beforeEach hook.

it("should write 404.html and index.html for non-SPA", async () => {
const setup: Setup = {
config: {},
rcfile: { projects: {}, targets: {}, etags: {} },
projectId: "test-project",
featureInfo: {
hosting: {
public: "public",
spa: false,
},
},
instructions: [],
};
const cfg = new config.Config({}, { projectDir: "/", cwd: "/" });
const askWriteStub = sandbox.stub(cfg, "askWriteProjectFile").resolves();

const clientStub = sandbox.stub(Client.prototype, "get").resolves({
body: { current: { version: "1.2.3" } },
status: 200,
response: {} as any,
});

await actuate(setup, cfg, {
cwd: "/",
configPath: "",
only: "",
except: "",
nonInteractive: false,
} as any);

expect(askWriteStub.calledTwice).to.be.true;
expect(askWriteStub.firstCall.args[0]).to.equal("public/404.html");
expect(askWriteStub.secondCall.args[0]).to.equal("public/index.html");
expect(clientStub.calledWith("/firebasejs/releases.json")).to.be.true;
});

it("should configure rewrites for SPA", async () => {
const setup: Setup = {
config: {},
rcfile: { projects: {}, targets: {}, etags: {} },
projectId: "test-project",
featureInfo: {
hosting: {
public: "public",
spa: true,
},
},
instructions: [],
};
const cfg = new config.Config({}, { projectDir: "/", cwd: "/" });
const askWriteStub = sandbox.stub(cfg, "askWriteProjectFile").resolves();
sandbox.stub(Client.prototype, "get").resolves({
body: { current: { version: "1.2.3" } },
status: 200,
response: {} as any,
});

await actuate(setup, cfg, {
cwd: "/",
configPath: "",
only: "",
except: "",
nonInteractive: false,
} as any);

expect(setup.config.hosting).to.deep.include({
rewrites: [{ source: "**", destination: "/index.html" }],
});
expect(askWriteStub.calledOnce).to.be.true; // Only index.html
});

it("should create site if newSiteId is present", async () => {
const setup: Setup = {
config: {},
rcfile: { projects: {}, targets: {}, etags: {} },
projectId: "test-project",
featureInfo: {
hosting: {
public: "public",
spa: false,
newSiteId: "new-site",
},
},
instructions: [],
};
const cfg = new config.Config({}, { projectDir: "/", cwd: "/" });
sandbox.stub(cfg, "askWriteProjectFile").resolves();
sandbox.stub(Client.prototype, "get").resolves({
body: { current: { version: "1.2.3" } },
status: 200,
response: {} as any,
});
const createSiteStub = sandbox.stub(hostingApi, "createSite").resolves({
name: "new-site",
defaultUrl: "https://new-site.web.app",
type: hostingApi.SiteType.DEFAULT_SITE,
appId: "app-id",
labels: {},
});

await actuate(setup, cfg, {
cwd: "/",
configPath: "",
only: "",
except: "",
nonInteractive: false,
} as any);

expect(createSiteStub.calledWith("test-project", "new-site")).to.be.true;
});
});
}).timeout(5000);
Loading
Loading