import assert from "node:assert";
import { describe, it } from "node:test";
import { mergeOpenApiDocuments } from "./merge.js";
import { extractServerPathname, transformPathsWithServerPathname, } from "./path-transform.js";
const emptyOpenApi = {
    openapi: "3.0.0",
    info: {
        title: "Test",
        version: "1.0.0",
    },
    paths: {},
};
describe("Path Transformation", () => {
    describe("extractServerPathname", () => {
        it("should extract pathname from server URL with path", () => {
            const doc = {
                ...emptyOpenApi,
                servers: [{ url: "https://api.example.com/v1" }],
            };
            assert.strictEqual(extractServerPathname(doc), "/v1");
        });
        it("should extract pathname from server URL with nested path", () => {
            const doc = {
                ...emptyOpenApi,
                servers: [{ url: "https://api.example.com/api/v2" }],
            };
            assert.strictEqual(extractServerPathname(doc), "/api/v2");
        });
        it("should return empty string for server URL without path", () => {
            const doc = {
                ...emptyOpenApi,
                servers: [{ url: "https://api.example.com" }],
            };
            assert.strictEqual(extractServerPathname(doc), "");
        });
        it("should return empty string for server URL with root path", () => {
            const doc = {
                ...emptyOpenApi,
                servers: [{ url: "https://api.example.com/" }],
            };
            assert.strictEqual(extractServerPathname(doc), "");
        });
        it("should handle relative server URLs", () => {
            const doc = {
                ...emptyOpenApi,
                servers: [{ url: "/api/v1" }],
            };
            assert.strictEqual(extractServerPathname(doc), "/api/v1");
        });
        it("should handle server URLs without leading slash", () => {
            const doc = {
                ...emptyOpenApi,
                servers: [{ url: "api/v1" }],
            };
            assert.strictEqual(extractServerPathname(doc), "/api/v1");
        });
        it("should return empty string when no servers defined", () => {
            const doc = { ...emptyOpenApi };
            assert.strictEqual(extractServerPathname(doc), "");
        });
        it("should return empty string when servers array is empty", () => {
            const doc = {
                ...emptyOpenApi,
                servers: [],
            };
            assert.strictEqual(extractServerPathname(doc), "");
        });
        it("should ignore query parameters in server URL", () => {
            const doc = {
                ...emptyOpenApi,
                servers: [{ url: "https://api.example.com/v1?foo=bar" }],
            };
            assert.strictEqual(extractServerPathname(doc), "/v1");
        });
        it("should ignore fragments in server URL", () => {
            const doc = {
                ...emptyOpenApi,
                servers: [{ url: "https://api.example.com/v1#section" }],
            };
            assert.strictEqual(extractServerPathname(doc), "/v1");
        });
    });
    describe("transformPathsWithServerPathname", () => {
        it("should prepend pathname to all paths", () => {
            const doc = {
                ...emptyOpenApi,
                paths: {
                    "/users": { get: { operationId: "getUsers" } },
                    "/products": { get: { operationId: "getProducts" } },
                },
            };
            const transformed = transformPathsWithServerPathname(doc, "/v1");
            assert.ok("/v1/users" in transformed.paths);
            assert.ok("/v1/products" in transformed.paths);
            assert.ok(!("/users" in transformed.paths));
            assert.ok(!("/products" in transformed.paths));
        });
        it("should handle pathname with trailing slash", () => {
            const doc = {
                ...emptyOpenApi,
                paths: {
                    "/users": { get: { operationId: "getUsers" } },
                },
            };
            const transformed = transformPathsWithServerPathname(doc, "/v1/");
            assert.ok("/v1/users" in transformed.paths);
            assert.ok(!("/v1//users" in transformed.paths));
        });
        it("should handle pathname without leading slash", () => {
            const doc = {
                ...emptyOpenApi,
                paths: {
                    "/users": { get: { operationId: "getUsers" } },
                },
            };
            const transformed = transformPathsWithServerPathname(doc, "v1");
            assert.ok("/v1/users" in transformed.paths);
        });
        it("should return unchanged document when pathname is empty", () => {
            const doc = {
                ...emptyOpenApi,
                paths: {
                    "/users": { get: { operationId: "getUsers" } },
                },
            };
            const transformed = transformPathsWithServerPathname(doc, "");
            assert.ok("/users" in transformed.paths);
        });
        it("should return unchanged document when pathname is just slash", () => {
            const doc = {
                ...emptyOpenApi,
                paths: {
                    "/users": { get: { operationId: "getUsers" } },
                },
            };
            const transformed = transformPathsWithServerPathname(doc, "/");
            assert.ok("/users" in transformed.paths);
        });
        it("should handle nested pathnames", () => {
            const doc = {
                ...emptyOpenApi,
                paths: {
                    "/users": { get: { operationId: "getUsers" } },
                },
            };
            const transformed = transformPathsWithServerPathname(doc, "/api/v2");
            assert.ok("/api/v2/users" in transformed.paths);
        });
        it("should preserve all path item properties", () => {
            const doc = {
                ...emptyOpenApi,
                paths: {
                    "/users": {
                        get: { operationId: "getUsers", summary: "Get users" },
                        post: { operationId: "createUser", summary: "Create user" },
                    },
                },
            };
            const transformed = transformPathsWithServerPathname(doc, "/v1");
            assert.strictEqual(transformed.paths["/v1/users"].get.summary, "Get users");
            assert.strictEqual(transformed.paths["/v1/users"].post.summary, "Create user");
        });
    });
    describe("mergeOpenApiDocuments with path options", () => {
        it("should apply prependServerPath when enabled", () => {
            const original = { ...emptyOpenApi };
            const newDoc = {
                ...emptyOpenApi,
                servers: [{ url: "https://api.example.com/v1" }],
                paths: {
                    "/users": { get: { operationId: "getUsers" } },
                },
            };
            const { mergedDocument } = mergeOpenApiDocuments(original, newDoc, {
                mergeMode: "path-method",
                prependServerPath: true,
            });
            assert.ok("/v1/users" in mergedDocument.paths);
            assert.ok(!("/users" in mergedDocument.paths));
        });
        it("should not apply prependServerPath when disabled", () => {
            const original = { ...emptyOpenApi };
            const newDoc = {
                ...emptyOpenApi,
                servers: [{ url: "https://api.example.com/v1" }],
                paths: {
                    "/users": { get: { operationId: "getUsers" } },
                },
            };
            const { mergedDocument } = mergeOpenApiDocuments(original, newDoc, {
                mergeMode: "path-method",
                prependServerPath: false,
            });
            // Original path should exist
            assert.ok("/users" in mergedDocument.paths);
            assert.strictEqual(mergedDocument.paths?.["/users"]?.get?.operationId, "getUsers");
        });
        it("should apply prependPath when provided", () => {
            const original = { ...emptyOpenApi };
            const newDoc = {
                ...emptyOpenApi,
                paths: {
                    "/users": { get: { operationId: "getUsers" } },
                },
            };
            const { mergedDocument } = mergeOpenApiDocuments(original, newDoc, {
                mergeMode: "path-method",
                prependPath: "/custom/path",
            });
            // Transformed path should exist with correct operation
            assert.ok("/custom/path/users" in mergedDocument.paths);
            assert.strictEqual(mergedDocument.paths?.["/custom/path/users"]?.get?.operationId, "getUsers");
        });
        it("should prioritize prependPath over prependServerPath", () => {
            const original = { ...emptyOpenApi };
            const newDoc = {
                ...emptyOpenApi,
                servers: [{ url: "https://api.example.com/v1" }],
                paths: {
                    "/users": { get: { operationId: "getUsers" } },
                },
            };
            const { mergedDocument } = mergeOpenApiDocuments(original, newDoc, {
                mergeMode: "path-method",
                prependServerPath: true,
                prependPath: "/custom",
            });
            // Custom prepend path should be used
            assert.ok("/custom/users" in mergedDocument.paths);
            assert.strictEqual(mergedDocument.paths?.["/custom/users"]?.get?.operationId, "getUsers");
        });
        it("should work with operation-id merge mode", () => {
            const original = {
                ...emptyOpenApi,
                paths: {
                    "/old-path": { get: { operationId: "getUsers" } },
                },
            };
            const newDoc = {
                ...emptyOpenApi,
                servers: [{ url: "https://api.example.com/v2" }],
                paths: {
                    "/users": { get: { operationId: "getUsers" } },
                },
            };
            const { mergedDocument } = mergeOpenApiDocuments(original, newDoc, {
                mergeMode: "operation-id",
                prependServerPath: true,
            });
            assert.ok("/v2/users" in mergedDocument.paths);
            // Old path operation should be removed since the operation was updated
            assert.strictEqual(mergedDocument.paths?.["/old-path"]?.get, undefined);
            // Original untransformed path should not exist
            assert.strictEqual(mergedDocument.paths?.["/users"]?.get, undefined);
        });
        it("should support backward compatible API with string merge mode", () => {
            const original = { ...emptyOpenApi };
            const newDoc = {
                ...emptyOpenApi,
                paths: {
                    "/users": { get: { operationId: "getUsers" } },
                },
            };
            const { mergedDocument } = mergeOpenApiDocuments(original, newDoc, "path-method");
            assert.ok("/users" in mergedDocument.paths);
        });
    });
});
//# sourceMappingURL=path-transform.spec.js.map