"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const chai_1 = require("chai");
const sinon = require("sinon");
const convertConfig_1 = require("../../../deploy/hosting/convertConfig");
const backend = require("../../../deploy/functions/backend");
const error_1 = require("../../../error");
const FUNCTION_ID = "function";
const PROJECT_ID = "project";
const REGION = "region";
function endpoint(opts) {
    const ret = Object.assign({ id: FUNCTION_ID, project: PROJECT_ID, entryPoint: FUNCTION_ID, region: REGION, runtime: "nodejs16", platform: "gcfv1" }, opts);
    if (!("httpsTrigger" in ret ||
        "eventTrigger" in ret ||
        "callableTrigger" in ret ||
        "scheduledTrigger" in ret ||
        "taskQueueTrigger" in ret ||
        "blockingTrigger" in ret)) {
        ret.httpsTrigger = {};
    }
    return ret;
}
describe("convertConfig", () => {
    const tests = [
        {
            name: "returns rewrites for glob destination",
            input: { rewrites: [{ glob: "/foo", destination: "https://example.com" }] },
            want: { rewrites: [{ glob: "/foo", path: "https://example.com" }] },
        },
        {
            name: "returns rewrites for regex destination",
            input: { rewrites: [{ glob: "/foo$", destination: "https://example.com" }] },
            want: { rewrites: [{ glob: "/foo$", path: "https://example.com" }] },
        },
        {
            name: "checks for function region if unspecified",
            input: { rewrites: [{ glob: "/foo", function: { functionId: FUNCTION_ID } }] },
            want: {
                rewrites: [
                    {
                        glob: "/foo",
                        function: FUNCTION_ID,
                        functionRegion: "us-central2",
                    },
                ],
            },
            functionsPayload: {
                functions: {
                    default: {
                        wantBackend: backend.of({
                            id: FUNCTION_ID,
                            project: PROJECT_ID,
                            entryPoint: FUNCTION_ID,
                            runtime: "nodejs16",
                            region: "us-central2",
                            platform: "gcfv1",
                            httpsTrigger: {},
                        }),
                        haveBackend: backend.empty(),
                    },
                },
            },
        },
        {
            name: "discovers the function region of a callable function",
            input: { rewrites: [{ glob: "/foo", function: { functionId: FUNCTION_ID } }] },
            want: { rewrites: [{ glob: "/foo", function: FUNCTION_ID, functionRegion: "us-central2" }] },
            functionsPayload: {
                functions: {
                    default: {
                        wantBackend: backend.of({
                            id: FUNCTION_ID,
                            project: PROJECT_ID,
                            entryPoint: FUNCTION_ID,
                            runtime: "nodejs16",
                            region: "us-central2",
                            platform: "gcfv1",
                            httpsTrigger: {},
                        }),
                        haveBackend: backend.empty(),
                    },
                },
            },
        },
        {
            name: "returns rewrites for glob CF3",
            input: {
                rewrites: [{ glob: "/foo", function: { functionId: FUNCTION_ID, region: "europe-west2" } }],
            },
            want: { rewrites: [{ glob: "/foo", function: FUNCTION_ID, functionRegion: "europe-west2" }] },
            functionsPayload: {
                functions: {
                    default: {
                        wantBackend: backend.of({
                            id: FUNCTION_ID,
                            project: PROJECT_ID,
                            entryPoint: FUNCTION_ID,
                            runtime: "nodejs16",
                            region: "europe-west2",
                            platform: "gcfv1",
                            httpsTrigger: {},
                        }, {
                            id: FUNCTION_ID,
                            project: PROJECT_ID,
                            entryPoint: FUNCTION_ID,
                            runtime: "nodejs16",
                            region: "us-central1",
                            platform: "gcfv2",
                            httpsTrigger: {},
                        }),
                        haveBackend: backend.empty(),
                    },
                },
            },
        },
        {
            name: "defaults to a us-central1 rewrite if one is avaiable, v1 edition",
            input: { rewrites: [{ glob: "/foo", function: { functionId: FUNCTION_ID } }] },
            want: { rewrites: [{ glob: "/foo", function: FUNCTION_ID, functionRegion: "us-central1" }] },
            functionsPayload: {
                functions: {
                    default: {
                        wantBackend: backend.of({
                            id: FUNCTION_ID,
                            project: PROJECT_ID,
                            entryPoint: FUNCTION_ID,
                            runtime: "nodejs16",
                            region: "europe-west2",
                            platform: "gcfv1",
                            httpsTrigger: {},
                        }, {
                            id: FUNCTION_ID,
                            project: PROJECT_ID,
                            entryPoint: FUNCTION_ID,
                            runtime: "nodejs16",
                            region: "us-central1",
                            platform: "gcfv1",
                            httpsTrigger: {},
                        }),
                        haveBackend: backend.empty(),
                    },
                },
            },
        },
        {
            name: "defaults to a us-central1 rewrite if one is avaiable, v2 edition",
            input: { rewrites: [{ glob: "/foo", function: { functionId: FUNCTION_ID } }] },
            want: {
                rewrites: [{ glob: "/foo", run: { region: "us-central1", serviceId: FUNCTION_ID } }],
            },
            functionsPayload: {
                functions: {
                    default: {
                        wantBackend: backend.of({
                            id: FUNCTION_ID,
                            project: PROJECT_ID,
                            entryPoint: FUNCTION_ID,
                            runtime: "nodejs16",
                            region: "europe-west2",
                            platform: "gcfv2",
                            httpsTrigger: {},
                        }, {
                            id: FUNCTION_ID,
                            project: PROJECT_ID,
                            entryPoint: FUNCTION_ID,
                            runtime: "nodejs16",
                            region: "us-central1",
                            platform: "gcfv2",
                            httpsTrigger: {},
                        }),
                        haveBackend: backend.empty(),
                    },
                },
            },
        },
        {
            name: "returns rewrites for regex CF3",
            input: {
                rewrites: [{ regex: "/foo$", function: { functionId: FUNCTION_ID, region: REGION } }],
            },
            want: {
                rewrites: [{ regex: "/foo$", function: FUNCTION_ID, functionRegion: REGION }],
            },
            functionsPayload: {
                functions: {
                    default: {
                        wantBackend: backend.of({
                            id: FUNCTION_ID,
                            project: PROJECT_ID,
                            entryPoint: FUNCTION_ID,
                            runtime: "nodejs16",
                            region: REGION,
                            platform: "gcfv1",
                            httpsTrigger: {},
                        }),
                        haveBackend: backend.empty(),
                    },
                },
            },
        },
        {
            name: "rewrites referencing CF3v2 functions being deployed are changed to Cloud Run (during release)",
            input: { rewrites: [{ regex: "/foo$", function: { functionId: FUNCTION_ID } }] },
            want: { rewrites: [{ regex: "/foo$", run: { serviceId: FUNCTION_ID, region: REGION } }] },
            functionsPayload: {
                functions: {
                    default: {
                        wantBackend: backend.of({
                            id: FUNCTION_ID,
                            project: PROJECT_ID,
                            entryPoint: FUNCTION_ID,
                            runtime: "nodejs16",
                            region: REGION,
                            platform: "gcfv2",
                            httpsTrigger: {},
                        }),
                        haveBackend: backend.empty(),
                    },
                },
            },
        },
        {
            name: "rewrites referencing existing CF3v2 functions are changed to Cloud Run (during prepare)",
            input: {
                rewrites: [
                    { regex: "/foo$", function: { functionId: FUNCTION_ID, region: "us-central1" } },
                ],
            },
            want: {
                rewrites: [{ regex: "/foo$", run: { serviceId: FUNCTION_ID, region: "us-central1" } }],
            },
            existingBackend: backend.of(endpoint({ platform: "gcfv2", region: "us-central1" })),
        },
        {
            name: "rewrites referencing existing CF3v2 functions are changed to Cloud Run (during release)",
            input: {
                rewrites: [
                    { regex: "/foo$", function: { functionId: FUNCTION_ID, region: "us-central1" } },
                ],
            },
            existingBackend: backend.of(endpoint({ platform: "gcfv2", region: "us-central1" })),
            want: {
                rewrites: [{ regex: "/foo$", run: { serviceId: FUNCTION_ID, region: "us-central1" } }],
            },
        },
        {
            name: "returns rewrites for glob Run",
            input: { rewrites: [{ glob: "/foo", run: { serviceId: "hello" } }] },
            want: { rewrites: [{ glob: "/foo", run: { region: "us-central1", serviceId: "hello" } }] },
        },
        {
            name: "returns rewrites for regex Run",
            input: { rewrites: [{ regex: "/foo$", run: { serviceId: "hello" } }] },
            want: { rewrites: [{ regex: "/foo$", run: { region: "us-central1", serviceId: "hello" } }] },
        },
        {
            name: "return rewrites for Cloud Run instances being deployed (during release)",
            input: { rewrites: [{ regex: "/foo$", run: { serviceId: "hello" } }] },
            want: { rewrites: [{ regex: "/foo$", run: { region: "us-central1", serviceId: "hello" } }] },
        },
        {
            name: "returns the specified rewrite even if it's not found",
            input: { rewrites: [{ glob: "/foo", function: { functionId: FUNCTION_ID } }] },
            want: { rewrites: [{ glob: "/foo", function: FUNCTION_ID }] },
            existingBackend: backend.empty(),
        },
        {
            name: "returns rewrites for Run with specified regions",
            input: { rewrites: [{ glob: "/foo", run: { serviceId: "hello", region: "us-midwest" } }] },
            want: { rewrites: [{ glob: "/foo", run: { region: "us-midwest", serviceId: "hello" } }] },
        },
        {
            name: "returns rewrites for glob Dynamic Links",
            input: { rewrites: [{ glob: "/foo", dynamicLinks: true }] },
            want: { rewrites: [{ glob: "/foo", dynamicLinks: true }] },
        },
        {
            name: "returns rewrites for regex Dynamic Links",
            input: { rewrites: [{ regex: "/foo$", dynamicLinks: true }] },
            want: { rewrites: [{ regex: "/foo$", dynamicLinks: true }] },
        },
        {
            name: "returns glob redirects without a specified code/type",
            input: { redirects: [{ glob: "/foo", destination: "https://example.com" }] },
            want: { redirects: [{ glob: "/foo", location: "https://example.com" }] },
        },
        {
            name: "returns regex redirects without a specified code/type",
            input: { redirects: [{ regex: "/foo$", destination: "https://example.com" }] },
            want: { redirects: [{ regex: "/foo$", location: "https://example.com" }] },
        },
        {
            name: "returns glob redirects with a specified code/type",
            input: { redirects: [{ glob: "/foo", destination: "https://example.com", type: 301 }] },
            want: { redirects: [{ glob: "/foo", location: "https://example.com", statusCode: 301 }] },
        },
        {
            name: "returns no headers if they weren't specified",
            input: { headers: [{ glob: "/foo", headers: [] }] },
            want: { headers: [{ glob: "/foo", headers: {} }] },
        },
        {
            name: "returns glob headers as a map",
            input: {
                headers: [
                    {
                        glob: "/foo",
                        headers: [
                            { key: "x-foo", value: "bar" },
                            { key: "x-baz", value: "zap" },
                        ],
                    },
                ],
            },
            want: { headers: [{ glob: "/foo", headers: { "x-foo": "bar", "x-baz": "zap" } }] },
        },
        {
            name: "returns regex headers as a map",
            input: {
                headers: [
                    {
                        regex: "/foo&",
                        headers: [
                            { key: "x-foo", value: "bar" },
                            { key: "x-baz", value: "zap" },
                        ],
                    },
                ],
            },
            want: { headers: [{ regex: "/foo&", headers: { "x-foo": "bar", "x-baz": "zap" } }] },
        },
        {
            name: "returns clean URLs when it is false",
            input: { cleanUrls: false },
            want: { cleanUrls: false },
        },
        {
            name: "returns clean URLs when it is true",
            input: { cleanUrls: true },
            want: { cleanUrls: true },
        },
        {
            name: "returns trailing slash as ADD when true",
            input: { trailingSlash: true },
            want: { trailingSlashBehavior: "ADD" },
        },
        {
            name: "returns trailing slash as REMOVE when false",
            input: { trailingSlash: false },
            want: { trailingSlashBehavior: "REMOVE" },
        },
        {
            name: "returns app association as it is set",
            input: { appAssociation: "AUTO" },
            want: { appAssociation: "AUTO" },
        },
        {
            name: "returns i18n as it is set",
            input: { i18n: { root: "bar" } },
            want: { i18n: { root: "bar" } },
        },
    ];
    for (const { name, input, existingBackend, want, functionsPayload } of tests) {
        it(name, async () => {
            const context = {
                projectId: PROJECT_ID,
                loadedExistingBackend: true,
                existingBackend: existingBackend || backend.empty(),
                unreachableRegions: {
                    gcfV1: [],
                    gcfV2: [],
                },
            };
            const deploy = {
                config: Object.assign({ site: "site" }, input),
                version: "version",
            };
            const config = await (0, convertConfig_1.convertConfig)(context, functionsPayload || {}, deploy);
            (0, chai_1.expect)(config).to.deep.equal(want);
        });
    }
    describe("rewrites errors", () => {
        it("should throw when rewrite points to function in the wrong region", async () => {
            await (0, chai_1.expect)((0, convertConfig_1.convertConfig)({ projectId: "1" }, {
                functions: {
                    default: {
                        wantBackend: backend.of({
                            id: FUNCTION_ID,
                            project: PROJECT_ID,
                            entryPoint: FUNCTION_ID,
                            runtime: "nodejs16",
                            region: "europe-west1",
                            platform: "gcfv1",
                            httpsTrigger: {},
                        }),
                        haveBackend: backend.empty(),
                    },
                },
            }, {
                config: {
                    site: "foo",
                    rewrites: [
                        { glob: "/foo", function: { functionId: FUNCTION_ID, region: "asia-northeast1" } },
                    ],
                },
                version: "14",
            })).to.eventually.be.rejectedWith(error_1.FirebaseError);
        });
        it("should throw when rewrite points to function being deleted", async () => {
            await (0, chai_1.expect)((0, convertConfig_1.convertConfig)({ projectId: "1" }, {
                functions: {
                    default: {
                        wantBackend: backend.of({
                            id: FUNCTION_ID,
                            project: PROJECT_ID,
                            entryPoint: FUNCTION_ID,
                            runtime: "nodejs16",
                            region: "europe-west1",
                            platform: "gcfv1",
                            httpsTrigger: {},
                        }),
                        haveBackend: backend.of({
                            id: FUNCTION_ID,
                            project: PROJECT_ID,
                            entryPoint: FUNCTION_ID,
                            runtime: "nodejs16",
                            region: "asia-northeast1",
                            platform: "gcfv1",
                            httpsTrigger: {},
                        }),
                    },
                },
            }, {
                config: {
                    site: "foo",
                    rewrites: [
                        { glob: "/foo", function: { functionId: FUNCTION_ID, region: "asia-northeast1" } },
                    ],
                },
                version: "14",
            })).to.eventually.be.rejectedWith(error_1.FirebaseError);
        });
    });
    describe("with permissions issues", () => {
        let existingBackendStub;
        beforeEach(() => {
            existingBackendStub = sinon
                .stub(backend, "existingBackend")
                .rejects("existingBackend unspecified behavior");
        });
        afterEach(() => {
            sinon.restore();
        });
        it("should not throw when resolving backends", async () => {
            existingBackendStub.rejects(new error_1.FirebaseError("Some permissions 403 error (that should be caught)", { status: 403 }));
            await (0, chai_1.expect)((0, convertConfig_1.convertConfig)({ projectId: "1" }, {}, {
                config: {
                    site: "foo",
                    rewrites: [{ glob: "/foo", function: { functionId: FUNCTION_ID } }],
                },
                version: "14",
            })).to.not.be.rejected;
        });
    });
});
//# sourceMappingURL=convertConfig.spec.js.map