Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix bug: Unable to use {service-name} interpolation for filenames with openapi3-emitter when only one service is defined #6182

Merged
merged 12 commits into from
Mar 3, 2025
Prev Previous commit
Next Next commit
update
  • Loading branch information
albertxavier100 committed Feb 28, 2025
commit 5c1b366144dcc37b5ec9d25b34955b5d05e9320c
55 changes: 0 additions & 55 deletions packages/openapi3/test/emit-openapi.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { resolveVirtualPath } from "@typespec/compiler/testing";
import { describe, expect, it } from "vitest";
import { worksFor } from "./works-for.js";

@@ -78,59 +77,5 @@ describe("Scalar formats of serialized document in YAML", () => {
- oFF
`);
});

interface ServiceNameCase {
description: string;
code: string;
outputFilePattern: string;
expectedOutputFiles: string[];
}
it.each([
// {service-name} cases
{
description: "{service-name} for one service",
code: "@service namespace AAA { model M {a: string} }",
outputFilePattern: "{service-name}.yaml",
expectedOutputFiles: [resolveVirtualPath("AAA.yaml")],
},
{
description: "{service-name} for multiple services",
code:
"@service namespace AAA { model M {a: string} }" +
"@service namespace BBB { model N {b: string} }",
outputFilePattern: "{service-name}.yaml",
expectedOutputFiles: [resolveVirtualPath("AAA.yaml"), resolveVirtualPath("BBB.yaml")],
},
// {service-name-if-multiple} cases
{
description: "{service-name-if-multiple} for one service",
code: "@service namespace AAA { model M {a: string} }",
outputFilePattern: "{service-name-if-multiple}.yaml",
expectedOutputFiles: [resolveVirtualPath("yaml")],
},
{
description: "{service-name-if-multiple} for multiple services",
code:
"@service namespace AAA { model M {a: string} }" +
"@service namespace BBB { model N {b: string} }",
outputFilePattern: "{service-name-if-multiple}.yaml",
expectedOutputFiles: [resolveVirtualPath("AAA.yaml"), resolveVirtualPath("BBB.yaml")],
},
// fixed name cases
{
description: "fixed name for one service",
code: "@service namespace AAA { model M {a: string} }",
outputFilePattern: "fixed-name.yaml",
expectedOutputFiles: [resolveVirtualPath("fixed-name.yaml")],
},
])("$description", async (c: ServiceNameCase) => {
const options = {
"output-file": c.outputFilePattern,
"emitter-output-dir": "{output-dir}",
};
const [diag, load, _] = await helper.emitOpenApi(c.code, options);
expect(diag.length).toBe(0);
for (const outputFile of c.expectedOutputFiles) expect(load(outputFile)).toBeDefined();
});
});
});
66 changes: 66 additions & 0 deletions packages/openapi3/test/predefined-variable.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { resolveVirtualPath } from "@typespec/compiler/testing";
import { describe, expect, it } from "vitest";
import { createOpenAPITestRunner } from "./test-host.js";

describe("Predefined variable name behavior", () => {
interface ServiceNameCase {
description: string;
code: string;
outputFilePattern: string;
expectedOutputFiles: string[];
}
it.each([
// {service-name} cases
{
description: "{service-name} for one service",
code: "@service namespace AAA { model M {a: string} }",
outputFilePattern: "{service-name}.yaml",
expectedOutputFiles: ["AAA.yaml"],
},
{
description: "{service-name} for multiple services",
code:
"@service namespace AAA { model M {a: string} }" +
"@service namespace BBB { model N {b: string} }",
outputFilePattern: "{service-name}.yaml",
expectedOutputFiles: ["AAA.yaml", "BBB.yaml"],
},
// {service-name-if-multiple} cases
{
description: "{service-name-if-multiple} for one service",
code: "@service namespace AAA { model M {a: string} }",
outputFilePattern: "{service-name-if-multiple}.yaml",
expectedOutputFiles: ["yaml"],
},
{
description: "{service-name-if-multiple} for multiple services",
code:
"@service namespace AAA { model M {a: string} }" +
"@service namespace BBB { model N {b: string} }",
outputFilePattern: "{service-name-if-multiple}.yaml",
expectedOutputFiles: ["AAA.yaml", "BBB.yaml"],
},
// fixed name cases
{
description: "fixed name for one service",
code: "@service namespace AAA { model M {a: string} }",
outputFilePattern: "fixed-name.yaml",
expectedOutputFiles: ["fixed-name.yaml"],
},
])("$description", async (c: ServiceNameCase) => {
const runner = await createOpenAPITestRunner();
const diagnostics = await runner.diagnose(c.code, {
noEmit: false,
emit: ["@typespec/openapi3"],
options: {
"@typespec/openapi3": {
"output-file": c.outputFilePattern,
"emitter-output-dir": "{output-dir}",
},
},
});
expect(diagnostics.length).toBe(0);
for (const outputFile of c.expectedOutputFiles)
expect(runner.fs.has(resolveVirtualPath(outputFile))).toBe(true);
});
});
32 changes: 0 additions & 32 deletions packages/openapi3/test/test-host.ts
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@
import { XmlTestLibrary } from "@typespec/xml/testing";
import { ok } from "assert";
import { parse as yamlParse } from "yaml";
import { EmitterOptions } from "../../compiler/src/config/types.js";

Check warning on line 16 in packages/openapi3/test/test-host.ts

GitHub Actions / Lint

'EmitterOptions' is defined but never used. Allowed unused vars must match /^_/u
import { OpenAPI3EmitterOptions } from "../src/lib.js";
import { OpenAPI3TestLibrary } from "../src/testing/index.js";
import { OpenAPI3Document } from "../src/types.js";
@@ -82,38 +82,6 @@
return [doc, diagnostics, content];
}

export async function emitOpenApi(
code: string,
options: OpenAPI3EmitterOptions & EmitterOptions = {},
): Promise<
[
readonly Diagnostic[],
(outputFile: string) => string | undefined,
(outputFile: string) => OpenAPI3Document | undefined,
]
> {
const runner = await createOpenAPITestRunner();
const fileType = options["file-type"] || "yaml";
const diagnostics = await runner.diagnose(code, {
noEmit: false,
emit: ["@typespec/openapi3"],
options: {
"@typespec/openapi3": options,
},
});
return [diagnostics, load, parse];

function load(outputFile: string): string | undefined {
const absoluteOutputFile = resolveVirtualPath(outputFile);
return runner.fs.get(absoluteOutputFile);
}

function parse(outputFile: string): OpenAPI3Document | undefined {
const content = load(outputFile);
if (!content) return;
return fileType === "json" ? JSON.parse(content) : yamlParse(content);
}
}

export async function diagnoseOpenApiFor(code: string, options: OpenAPI3EmitterOptions = {}) {
const runner = await createOpenAPITestRunner();
Loading
Oops, something went wrong.