Skip to content

Commit

Permalink
More fixes to http specs and add validation client vs server (#4580)
Browse files Browse the repository at this point in the history
  • Loading branch information
timotheeguerin authored Sep 30, 2024
1 parent f33c3ff commit ac2de4b
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 48 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ lib-cov
# Coverage directory used by tools like istanbul
coverage
!packages/spec-core/src/coverage
spec-coverage.json

# nyc test coverage
.nyc_output
Expand Down
14 changes: 8 additions & 6 deletions packages/http-specs/package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"name": "@typespec/http-specs",
"private": true,
"version": "0.37.2",
"description": "Spec scenarios and mock apis",
"main": "dist/index.js",
Expand All @@ -8,11 +9,13 @@
"watch": "tsc -p ./tsconfig.build.json --watch",
"build": "tsc -p ./tsconfig.build.json",
"clean": "rimraf dist/ temp/",
"test:e2e": "pnpm validate-scenarios && pnpm validate-mock-apis",
"test:e2e": "pnpm validate-scenarios && pnpm validate-mock-apis && pnpm validate-client-server",
"validate-scenarios": "spec-core validate-scenarios ./specs",
"generate-scenarios-summary": "spec-core generate-scenarios-summary ./specs",
"validate-mock-apis": "spec-core validate-mock-apis ./specs",
"check-scenario-coverage": "spec-core check-coverage ./specs",
"validate-client-server": "concurrently \"spec-core server start ./specs\" \"npm run client\" && spec-core server stop",
"client": "spec-core server-test ./specs",
"serve": "spec-core serve ./specs",
"test": "echo \"Error: no test specified\" && exit 1"
},
Expand All @@ -30,24 +33,23 @@
},
"homepage": "https://github.com/microsoft/typespec#readme",
"dependencies": {
"@typespec/spec-core": "workspace:~",
"@typespec/spec-api": "workspace:~",
"multer": "^1.4.5-lts.1",
"dotenv": "~16.4.5"
"@typespec/spec-core": "workspace:~"
},
"devDependencies": {
"@types/node": "~22.7.1",
"@types/multer": "^1.4.10",
"@types/node": "~22.7.1",
"@typespec/openapi": "workspace:~",
"@typespec/openapi3": "workspace:~",
"concurrently": "^9.0.1",
"rimraf": "~6.0.1",
"typescript": "~5.6.2"
},
"peerDependencies": {
"@typespec/spec-lib": "workspace:~",
"@typespec/compiler": "workspace:~",
"@typespec/http": "workspace:~",
"@typespec/rest": "workspace:~",
"@typespec/spec-lib": "workspace:~",
"@typespec/versioning": "workspace:~",
"@typespec/xml": "workspace:~"
}
Expand Down
50 changes: 37 additions & 13 deletions packages/spec-core/src/actions/server-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { logger } from "../logger.js";
import { loadScenarioMockApis } from "../scenarios-resolver.js";
import { makeServiceCall, uint8ArrayToString } from "./helper.js";

const DEFAULT_BASE_URL = "http://localhost:3000";

class ServerTestsGenerator {
private name: string = "";
private mockApiDefinition: MockApiDefinition;
Expand Down Expand Up @@ -137,20 +139,42 @@ class ServerTestsGenerator {
}
}

export async function serverTest(
scenariosPath: string,
serverBasePath: string,
scenariosConfig: {
runSingleScenario: string | undefined;
runScenariosFromFile: string | undefined;
},
) {
export interface ServerTestOptions {
baseUrl?: string;
runSingleScenario?: string;
runScenariosFromFile?: string;
}

async function delay(ms: number) {
return new Promise((resolve) => setTimeout(resolve, ms));
}

async function waitForServer(baseUrl: string) {
logger.info(`Executing server tests with base URL: ${baseUrl}`);
let retry = 0;

while (retry < 3) {
try {
await fetch(baseUrl);
break;
} catch (e) {
retry++;
logger.info("Retrying...");
await delay(retry * 1000);
}
}
logger.info(` ${baseUrl} is ready!`);
}

export async function serverTest(scenariosPath: string, options: ServerTestOptions = {}) {
const baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;
await waitForServer(baseUrl);
// 1. Get Testcases to run
const testCasesToRun: string[] = [];
if (scenariosConfig.runSingleScenario) {
testCasesToRun.push(scenariosConfig.runSingleScenario);
} else if (scenariosConfig.runScenariosFromFile) {
const data = fs.readFileSync(path.resolve(scenariosConfig.runScenariosFromFile), "utf8");
if (options.runSingleScenario) {
testCasesToRun.push(options.runSingleScenario);
} else if (options.runScenariosFromFile) {
const data = fs.readFileSync(path.resolve(options.runScenariosFromFile), "utf8");
const lines = data.split("\n");
lines.forEach((line) => {
testCasesToRun.push(line.trim());
Expand All @@ -164,7 +188,7 @@ export async function serverTest(
for (const api of scenario.apis) {
if (api.kind !== "MockApiDefinition") continue;
if (testCasesToRun.length === 0 || testCasesToRun.includes(name)) {
const obj: ServerTestsGenerator = new ServerTestsGenerator(name, api, serverBasePath);
const obj: ServerTestsGenerator = new ServerTestsGenerator(name, api, baseUrl);
await obj.executeScenario();
}
}
Expand Down
25 changes: 12 additions & 13 deletions packages/spec-core/src/cli/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ async function main() {
.scriptName("spec")
.strict()
.help()
// .strict()
.strict()
.parserConfiguration({
"greedy-arrays": false,
"boolean-negation": false,
Expand Down Expand Up @@ -158,24 +158,23 @@ async function main() {
type: "string",
demandOption: true,
})
.positional("serverBasePath", {
.option("baseUrl", {
description: "Path to the server",
type: "string",
demandOption: true,
})
.positional("runSingleScenario", {
.option("runSingleScenario", {
description: "Single Scenario Case to run",
type: "string",
demandOption: false,
})
.positional("runScenariosFromFile", {
.option("runScenariosFromFile", {
description: "File that has the Scenarios to run",
type: "string",
demandOption: false,
});
})
.demandOption("scenariosPath", "serverBasePath");
},
async (args) => {
await serverTest(args.scenariosPath, args.serverBasePath, {
await serverTest(args.scenariosPath, {
baseUrl: args.baseUrl,
runSingleScenario: args.runSingleScenario,
runScenariosFromFile: args.runScenariosFromFile,
});
Expand Down Expand Up @@ -321,7 +320,7 @@ main().catch((error) => {
process.exit(1);
});

process.on("SIGTERM", () => process.exit(2));
process.on("SIGINT", () => process.exit(2));
process.on("SIGUSR1", () => process.exit(2));
process.on("SIGUSR2", () => process.exit(2));
process.once("SIGTERM", () => process.exit(143));
process.once("SIGINT", () => process.exit(2));
process.once("SIGUSR1", () => process.exit(2));
process.once("SIGUSR2", () => process.exit(2));
1 change: 1 addition & 0 deletions packages/spec-core/src/utils/body-utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { describe, expect, it } from "vitest";
import { cleanupBody } from "./body-utils.js";

describe("BodyUtils", () => {
Expand Down
42 changes: 30 additions & 12 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions tsconfig.ws.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@
{ "path": "packages/tmlanguage-generator/tsconfig.json" },
{ "path": "packages/protobuf/tsconfig.json" },
{ "path": "packages/openapi3/tsconfig.json" },
{ "path": "packages/spec-api/tsconfig.json" },
{ "path": "packages/spec-core/tsconfig.json" },
{ "path": "packages/spec-lib/tsconfig.json" },
{ "path": "packages/http-specs/tsconfig.json" },
{ "path": "packages/spec-api/tsconfig.build.json" },
{ "path": "packages/spec-core/tsconfig.build.json" },
{ "path": "packages/spec-lib/tsconfig.build.json" },
{ "path": "packages/http-specs/tsconfig.build.json" },
{ "path": "packages/monarch/tsconfig.json" },
{ "path": "packages/bundler/tsconfig.json" },
{ "path": "packages/tspd/tsconfig.json" },
Expand Down

0 comments on commit ac2de4b

Please sign in to comment.