@typespec/spector 0.1.0-alpha.2-dev.2 → 0.1.0-alpha.20-dev.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +131 -1
- package/README.md +37 -0
- package/dist/generated-defs/TypeSpec.Spector.ts-test.js +5 -2
- package/dist/generated-defs/TypeSpec.Spector.ts-test.js.map +1 -1
- package/dist/src/actions/helper.d.ts +8 -15
- package/dist/src/actions/helper.d.ts.map +1 -1
- package/dist/src/actions/helper.js +61 -69
- package/dist/src/actions/helper.js.map +1 -1
- package/dist/src/actions/serve.d.ts.map +1 -1
- package/dist/src/actions/serve.js +3 -4
- package/dist/src/actions/serve.js.map +1 -1
- package/dist/src/actions/server-test.d.ts +3 -5
- package/dist/src/actions/server-test.d.ts.map +1 -1
- package/dist/src/actions/server-test.js +108 -132
- package/dist/src/actions/server-test.js.map +1 -1
- package/dist/src/actions/upload-coverage-report.d.ts +2 -1
- package/dist/src/actions/upload-coverage-report.d.ts.map +1 -1
- package/dist/src/actions/upload-coverage-report.js +6 -2
- package/dist/src/actions/upload-coverage-report.js.map +1 -1
- package/dist/src/actions/upload-scenario-manifest.d.ts +4 -2
- package/dist/src/actions/upload-scenario-manifest.d.ts.map +1 -1
- package/dist/src/actions/upload-scenario-manifest.js +17 -7
- package/dist/src/actions/upload-scenario-manifest.js.map +1 -1
- package/dist/src/actions/validate-mock-apis.js +1 -1
- package/dist/src/actions/validate-mock-apis.js.map +1 -1
- package/dist/src/app/app.d.ts +1 -0
- package/dist/src/app/app.d.ts.map +1 -1
- package/dist/src/app/app.js +48 -54
- package/dist/src/app/app.js.map +1 -1
- package/dist/src/app/request-processor.d.ts +2 -2
- package/dist/src/app/request-processor.d.ts.map +1 -1
- package/dist/src/app/request-processor.js +10 -6
- package/dist/src/app/request-processor.js.map +1 -1
- package/dist/src/cli/cli.js +33 -21
- package/dist/src/cli/cli.js.map +1 -1
- package/dist/src/coverage/common.d.ts.map +1 -1
- package/dist/src/coverage/common.js +1 -0
- package/dist/src/coverage/common.js.map +1 -1
- package/dist/src/coverage/coverage-tracker.d.ts.map +1 -1
- package/dist/src/coverage/coverage-tracker.js.map +1 -1
- package/dist/src/coverage/scenario-manifest.d.ts +2 -2
- package/dist/src/coverage/scenario-manifest.d.ts.map +1 -1
- package/dist/src/coverage/scenario-manifest.js +4 -5
- package/dist/src/coverage/scenario-manifest.js.map +1 -1
- package/dist/src/lib/decorators.d.ts.map +1 -1
- package/dist/src/lib/decorators.js +0 -2
- package/dist/src/lib/decorators.js.map +1 -1
- package/dist/src/logger.d.ts +16 -2
- package/dist/src/logger.d.ts.map +1 -1
- package/dist/src/logger.js +27 -8
- package/dist/src/logger.js.map +1 -1
- package/dist/src/server/server.d.ts +1 -1
- package/dist/src/server/server.d.ts.map +1 -1
- package/dist/src/server/server.js +18 -5
- package/dist/src/server/server.js.map +1 -1
- package/dist/src/utils/body-utils.d.ts.map +1 -1
- package/dist/src/utils/request-utils.d.ts.map +1 -1
- package/docs/decorators.md +24 -0
- package/docs/using-spector.md +99 -0
- package/docs/writing-mock-apis.md +116 -0
- package/docs/writing-scenario-spec.md +49 -0
- package/generated-defs/TypeSpec.Spector.ts-test.ts +7 -2
- package/lib/main.tsp +1 -1
- package/package.json +23 -28
- package/src/actions/helper.ts +79 -95
- package/src/actions/serve.ts +3 -4
- package/src/actions/server-test.ts +132 -156
- package/src/actions/upload-coverage-report.ts +7 -1
- package/src/actions/upload-scenario-manifest.ts +22 -9
- package/src/actions/validate-mock-apis.ts +1 -1
- package/src/app/app.ts +71 -72
- package/src/app/request-processor.ts +16 -4
- package/src/cli/cli.ts +33 -21
- package/src/coverage/common.ts +1 -0
- package/src/coverage/coverage-tracker.ts +2 -2
- package/src/coverage/scenario-manifest.ts +5 -3
- package/src/lib/decorators.ts +0 -2
- package/src/logger.ts +39 -8
- package/src/scenarios-resolver.ts +1 -1
- package/src/server/server.ts +21 -7
- package/temp/.tsbuildinfo +1 -1
package/dist/src/logger.js
CHANGED
|
@@ -1,10 +1,29 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
import pc from "picocolors";
|
|
3
|
+
const levels = {
|
|
4
|
+
debug: 10,
|
|
5
|
+
info: 20,
|
|
6
|
+
warn: 30,
|
|
7
|
+
error: 30,
|
|
8
|
+
};
|
|
9
|
+
const levelDisplay = {
|
|
10
|
+
debug: pc.blue("debug"),
|
|
11
|
+
info: pc.green("info"),
|
|
12
|
+
warn: pc.yellow("warn"),
|
|
13
|
+
error: pc.red("error"),
|
|
14
|
+
};
|
|
15
|
+
export const logger = {
|
|
3
16
|
level: "info",
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
17
|
+
debug: log("debug"),
|
|
18
|
+
info: log("info"),
|
|
19
|
+
warn: log("warn"),
|
|
20
|
+
error: log("error"),
|
|
21
|
+
};
|
|
22
|
+
function log(level) {
|
|
23
|
+
return (message, ...data) => {
|
|
24
|
+
if (levels[level] >= levels[logger.level]) {
|
|
25
|
+
console.log(levelDisplay[level], message, ...data);
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
}
|
|
10
29
|
//# sourceMappingURL=logger.js.map
|
package/dist/src/logger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/logger.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,MAAM,MAAM,GAAG;IACb,KAAK,EAAE,EAAE;IACT,IAAI,EAAE,EAAE;IACR,IAAI,EAAE,EAAE;IACR,KAAK,EAAE,EAAE;CACV,CAAC;AAGF,MAAM,YAAY,GAA0B;IAC1C,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC;IACvB,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC;IACtB,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC;IACvB,KAAK,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC;CACvB,CAAC;AAUF,MAAM,CAAC,MAAM,MAAM,GAAW;IAC5B,KAAK,EAAE,MAAM;IACb,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC;IACnB,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC;IACjB,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC;IACjB,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC;CACpB,CAAC;AAEF,SAAS,GAAG,CAAC,KAAY;IACvB,OAAO,CAAC,OAAe,EAAE,GAAG,IAAe,EAAE,EAAE;QAC7C,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1C,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;QACrD,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -8,7 +8,7 @@ export declare class MockApiServer {
|
|
|
8
8
|
private app;
|
|
9
9
|
constructor(config: MockApiServerConfig);
|
|
10
10
|
use(route: string, ...handlers: RequestHandler[]): void;
|
|
11
|
-
start():
|
|
11
|
+
start(): Promise<number>;
|
|
12
12
|
}
|
|
13
13
|
export type ServerRequestHandler = (request: RequestExt, response: Response) => void;
|
|
14
14
|
//# sourceMappingURL=server.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/server/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEhD,OAAgB,EAAuB,cAAc,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAOjF,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;CACd;AAyCD,qBAAa,aAAa;IAGZ,OAAO,CAAC,MAAM;IAF1B,OAAO,CAAC,GAAG,CAAsB;gBAEb,MAAM,EAAE,mBAAmB;IAyBxC,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,cAAc,EAAE,GAAG,IAAI;IAIvD,KAAK,IAAI,
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/server/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEhD,OAAgB,EAAuB,cAAc,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAOjF,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;CACd;AAyCD,qBAAa,aAAa;IAGZ,OAAO,CAAC,MAAM;IAF1B,OAAO,CAAC,GAAG,CAAsB;gBAEb,MAAM,EAAE,mBAAmB;IAyBxC,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,cAAc,EAAE,GAAG,IAAI;IAIvD,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;CAqBhC;AAED,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAC"}
|
|
@@ -45,7 +45,7 @@ export class MockApiServer {
|
|
|
45
45
|
this.app.use(bodyParser.text({ type: "*/pdf", verify: rawBodySaver }));
|
|
46
46
|
this.app.use(bodyParser.text({ type: "text/plain" }));
|
|
47
47
|
this.app.use(bodyParser.raw({
|
|
48
|
-
type: ["application/octet-stream", "image/png"],
|
|
48
|
+
type: ["application/octet-stream", "image/png", "application/jsonl"],
|
|
49
49
|
limit: "10mb",
|
|
50
50
|
verify: rawBinaryBodySaver,
|
|
51
51
|
}));
|
|
@@ -56,13 +56,26 @@ export class MockApiServer {
|
|
|
56
56
|
}
|
|
57
57
|
start() {
|
|
58
58
|
this.app.use(errorHandler);
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
return new Promise((resolve, reject) => {
|
|
60
|
+
const server = this.app.listen(this.config.port, () => {
|
|
61
|
+
const resolvedPort = getPort(server);
|
|
62
|
+
if (!resolvedPort) {
|
|
63
|
+
logger.error("Failed to resolve port");
|
|
64
|
+
reject(new Error("Failed to resolve port"));
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
logger.info(`Started server on ${resolvedPort}`);
|
|
68
|
+
resolve(resolvedPort);
|
|
69
|
+
});
|
|
70
|
+
server.on("error", (err) => {
|
|
71
|
+
logger.error("Error starting server", err);
|
|
72
|
+
reject(err);
|
|
73
|
+
});
|
|
61
74
|
});
|
|
62
75
|
}
|
|
63
76
|
}
|
|
64
|
-
const
|
|
77
|
+
const getPort = (server) => {
|
|
65
78
|
const address = server?.address();
|
|
66
|
-
return typeof address === "string" ?
|
|
79
|
+
return typeof address === "string" ? null : address?.port;
|
|
67
80
|
};
|
|
68
81
|
//# sourceMappingURL=server.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../../src/server/server.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../../src/server/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"body-utils.d.ts","sourceRoot":"","sources":["../../../src/utils/body-utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,eAAO,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"body-utils.d.ts","sourceRoot":"","sources":["../../../src/utils/body-utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,eAAO,MAAM,WAAW,GAAI,YAAY,MAAM,KAAG,MACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request-utils.d.ts","sourceRoot":"","sources":["../../../src/utils/request-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,eAAO,MAAM,iBAAiB,
|
|
1
|
+
{"version":3,"file":"request-utils.d.ts","sourceRoot":"","sources":["../../../src/utils/request-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,eAAO,MAAM,iBAAiB,GAAI,SAAS,OAAO,KAAG,MACL,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
## Spector decorators
|
|
2
|
+
|
|
3
|
+
### `@scenarioService`
|
|
4
|
+
|
|
5
|
+
Decorator setting up the boilerplate for specs service namespace. Will automatically set:
|
|
6
|
+
|
|
7
|
+
- `@service{title: '<namespace>', value: '1.0.0'}` using the namespace as a value
|
|
8
|
+
- `@server` to `localhost:3000`
|
|
9
|
+
- `@route` using the parameter passed.
|
|
10
|
+
|
|
11
|
+
Usage:
|
|
12
|
+
|
|
13
|
+
```tsp
|
|
14
|
+
@scenarioSpec("/my-spec")
|
|
15
|
+
namespace MySpec;
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### `@scenario`
|
|
19
|
+
|
|
20
|
+
Mark an operation, interface or namespace as a scenario. Optionally can provide the name of the scenario.
|
|
21
|
+
|
|
22
|
+
### `@scenarioDoc`
|
|
23
|
+
|
|
24
|
+
Specify how to implement this scenario. Value is markdown. Differ from @doc which describe the scenario to the end user.
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Using spector
|
|
2
|
+
|
|
3
|
+
Install `spector` CLI globally or as a local dependency:
|
|
4
|
+
|
|
5
|
+
- **Globally**: run `npm install -g @typespec/spector`. You can then use `tsp-spector` as a CLI tool.
|
|
6
|
+
- **Locally**: run `npm install @typespec/spector` which should add the dependency to package.json. You can then use `tsp-spector` with `npx tsp-spector`.
|
|
7
|
+
|
|
8
|
+
**NOTE** With local install you'll need to prefix `tsp-spector` with `npx`(unless commands are written directly as npm scripts)
|
|
9
|
+
|
|
10
|
+
## Test against scenarios
|
|
11
|
+
|
|
12
|
+
### Spector Config
|
|
13
|
+
|
|
14
|
+
Spector supports a config file where you can configure scenarios that are not supported by your generator.
|
|
15
|
+
|
|
16
|
+
Create a `spector-config.yaml` file.
|
|
17
|
+
|
|
18
|
+
```yaml
|
|
19
|
+
# List of unsupported scenarios
|
|
20
|
+
unsupportedScenarios:
|
|
21
|
+
- Foo_Bar
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Run mock api server
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# Minimal
|
|
28
|
+
tsp-spector serve ./path/to/scenarios
|
|
29
|
+
|
|
30
|
+
# Change the port
|
|
31
|
+
tsp-spector serve ./path/to/scenarios --port 1234
|
|
32
|
+
|
|
33
|
+
# Specify where the coverage file should go
|
|
34
|
+
tsp-spector serve ./path/to/scenarios --coverageFile ./path/to/spector-coverage.json
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Alternative to start in background
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
tsp-spector server start ./path/to/scenarios # Takes the same arguments as serve
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Stop running server
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
tsp-spector server stop # Stop at the default port
|
|
47
|
+
tsp-spector server stop --port 1234 # If started the server at another port
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Validate and merge coverage
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# Minimal
|
|
54
|
+
tsp-spector check-coverage ./path/to/scenarios
|
|
55
|
+
|
|
56
|
+
# Path to tsp-spector config file for generator
|
|
57
|
+
tsp-spector check-coverage ./path/to/scenarios --configFile ./spector-config.yaml
|
|
58
|
+
|
|
59
|
+
# In case where there was multiple serve instance each creating their own coverage file
|
|
60
|
+
tsp-spector check-coverage ./path/to/scenarios --coverageFiles ./path/to/*-coverage.json --coverageFiles ./other/to/*-coverage.json
|
|
61
|
+
|
|
62
|
+
# Specify where the merged coverage file should go
|
|
63
|
+
tsp-spector check-coverage ./path/to/scenarios --mergedCoverageFile ./path/to/spector-final-coverage.json
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Upload coverage
|
|
67
|
+
|
|
68
|
+
Upload the coverage. Upload from the `main` branch. DO NOT upload on PR this WILL override the latest index.
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
# Minimal
|
|
72
|
+
tsp-spector upload-coverage --generatorName typescript --version=0.1.0
|
|
73
|
+
|
|
74
|
+
# Specify Coverage file
|
|
75
|
+
tsp-spector upload-coverage --generatorName typescript --version=0.1.0 --coverageFile ./path/to/spector-final-coverage.json
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Options:
|
|
79
|
+
|
|
80
|
+
- `--storageAccountName`: Name of the storage account to publish coverage. Use `typespec` for Spector/Azure Spector dashboard.
|
|
81
|
+
- `--generatorName`: Name of the generator. Must be one of `"@typespec/http-client-python", "@typespec/http-client-csharp", "@azure-tools/typespec-ts-rlc", "@azure-tools/typespec-ts-modular", "@typespec/http-client-js", "@typespec/http-client-java"`.
|
|
82
|
+
- `--generatorVersion`: Version of the generator
|
|
83
|
+
- `--coverageFile`: Path to the coverage file
|
|
84
|
+
|
|
85
|
+
#### Upload in azure devops
|
|
86
|
+
|
|
87
|
+
**This is applicable in the azure-sdk/internal ado project only.**
|
|
88
|
+
|
|
89
|
+
Add the following step
|
|
90
|
+
|
|
91
|
+
```yaml
|
|
92
|
+
- task: AzureCLI@2
|
|
93
|
+
displayName: Upload scenario coverage
|
|
94
|
+
inputs:
|
|
95
|
+
azureSubscription: "Typespec Storage"
|
|
96
|
+
scriptType: "bash"
|
|
97
|
+
scriptLocation: "inlineScript"
|
|
98
|
+
inlineScript: `tsp-spector upload-coverage --storageAccountName typespec --containerName coverages --generatorMode standard ... FILL options fitting your generator here as described above...`
|
|
99
|
+
```
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# Writing mock apis
|
|
2
|
+
|
|
3
|
+
1. Create a `mockapi.ts` file next to the `main.tsp` of the scenario
|
|
4
|
+
2. Create and export a variable called `Scenarios` with a `Record<string, ScenarioMockApi>` type
|
|
5
|
+
3. For each of the scenario assign a new property to the `Scenarios` variable. The value use one of the following:
|
|
6
|
+
- `passOnSuccess`: This will take one or multiple routes and will only pass teh scenario if all the routes gets called with a 2xx success code.
|
|
7
|
+
|
|
8
|
+
## Example
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
import { passOnSuccess, mockapi } from "@typespec/spec-api";
|
|
12
|
+
import { ScenarioMockApi } from "@typespec/spec-api";
|
|
13
|
+
|
|
14
|
+
export const Scenarios: Record<string, ScenarioMockApi> = {};
|
|
15
|
+
|
|
16
|
+
Scenarios.Hello_world = passOnSuccess(
|
|
17
|
+
mockapi.get("/hello/world", () => {
|
|
18
|
+
return {
|
|
19
|
+
status: 200,
|
|
20
|
+
body: {
|
|
21
|
+
contentType: "application/json",
|
|
22
|
+
rawContent: `"Hello World!"`,
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
}),
|
|
26
|
+
);
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## How to build response
|
|
30
|
+
|
|
31
|
+
Return the response object. [See type](../../spec-api/src/types.ts)
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
// Minimum requirement is the status code.
|
|
35
|
+
return {
|
|
36
|
+
status: 200,
|
|
37
|
+
};
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Return a body
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
// Return json
|
|
44
|
+
return {
|
|
45
|
+
status: 200,
|
|
46
|
+
body: json({ foo: 123 }),
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
// Return raw content
|
|
50
|
+
return {
|
|
51
|
+
status: 200,
|
|
52
|
+
body: {
|
|
53
|
+
contentType: "application/text",
|
|
54
|
+
rawContent: "foobar",
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Return headers
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
// Return json
|
|
63
|
+
return {
|
|
64
|
+
status: 200,
|
|
65
|
+
headers: {
|
|
66
|
+
MyHeader: "value-1"
|
|
67
|
+
MyHeaderOther: req.headers.MyRequestHeader
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## How to validate the request:
|
|
74
|
+
|
|
75
|
+
All built-in validation tools can be accessed using `req.expect.`
|
|
76
|
+
|
|
77
|
+
### Validate the body
|
|
78
|
+
|
|
79
|
+
- With `req.expect.bodyEquals`
|
|
80
|
+
|
|
81
|
+
This will do a deep equals of the body to make sure it match.
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
app.post("/example", "Example", (req) => {
|
|
85
|
+
req.bodyEquals({ foo: "123", bar: "456" });
|
|
86
|
+
});
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
- With `req.expect.rawBodyEquals`
|
|
90
|
+
|
|
91
|
+
This will compare the raw body sent.
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
app.post("/example", "Example", (req) => {
|
|
95
|
+
req.rawBodyEquals('"foo"');
|
|
96
|
+
});
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Custom validation
|
|
100
|
+
|
|
101
|
+
You can do any kind of validation accessing the `req: MockRequest` object and deciding to return a different response in some cases.
|
|
102
|
+
You can also always `throw` a `ValidationError`
|
|
103
|
+
|
|
104
|
+
Example:
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
app.post("/example", "Example", (req) => {
|
|
108
|
+
if (req.headers.MyCustomHeader.startsWith("x-foo")) {
|
|
109
|
+
throw new ValidationError(
|
|
110
|
+
"MyCustomHeader shouldn't start with x-foo",
|
|
111
|
+
null,
|
|
112
|
+
req.headers.MyCustomHeader,
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
```
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
## Defining scenario
|
|
2
|
+
|
|
3
|
+
The goal of the testserver is to define scenarios that needs to be supported in client generators. This means to have a meaningful coverage we need scenarios to:
|
|
4
|
+
|
|
5
|
+
- have a specific behavior that is meant to be tested
|
|
6
|
+
- ❌ DO NOT use the same scenario for testing multiple things.
|
|
7
|
+
- have a meaningful name that can be used in a compatibility table to see what a given generator support(e.g. `get_string`)
|
|
8
|
+
- a description of what the scenario is validating(e.g. `"Support passing a simple string as JSON"`)
|
|
9
|
+
- have a good description on what the client is expecting to generate/receive/send(e.g `Validate that this operation returns a JSON string that match "abc"`)
|
|
10
|
+
- ✅ DO describe how to validate that this scenario is working from the client point of view
|
|
11
|
+
|
|
12
|
+
When naming scenario always think about what would it look like in the [compatibility table](#compatibility-table) and would that name be meaningful to someone looking to see what is supported.
|
|
13
|
+
|
|
14
|
+
```cadl
|
|
15
|
+
import "@typespec/spector";
|
|
16
|
+
|
|
17
|
+
@scenarioService("/strings")
|
|
18
|
+
namespace String;
|
|
19
|
+
|
|
20
|
+
@scenario("get_string")
|
|
21
|
+
@doc("Support passing a simple string as JSON")
|
|
22
|
+
@scenarioDoc("In this scenario the Client should expect a string matching 'abc' to be returned.")
|
|
23
|
+
@get
|
|
24
|
+
@route("/simple")
|
|
25
|
+
op returnString(): string;
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Decorators that should be provided in this test library `@typespec/spector`:
|
|
29
|
+
|
|
30
|
+
- `@scenario`: Specify that this operation, interface or namespace is a scenario. Optionally take a scenario name otherwise default to the namespace name + operation/interface name
|
|
31
|
+
- `@scenarioDoc`: Specify how to implement this scenario. Differ from `@doc` which describe the scenario to the end user.
|
|
32
|
+
- `@supportedBy`: Specify if something is supported only by some kind of SDK. Option: `arm`, `dpg`. By default everything.
|
|
33
|
+
|
|
34
|
+
## Compatibility table
|
|
35
|
+
|
|
36
|
+
With all this information, a detailed compatibility table should be able to be produced by compiling each one of the scenarios and extracting the cases. Providing something like
|
|
37
|
+
|
|
38
|
+
| Scenario | CSharp | Python | Go | Java | TS/JS |
|
|
39
|
+
| ---------------------------- | ------ | ------ | --- | ---- | ----- |
|
|
40
|
+
| Vanilla |
|
|
41
|
+
| `get_string` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
42
|
+
| `put_string` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
43
|
+
| Azure |
|
|
44
|
+
| `pageable_nextLink` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
45
|
+
| `pageable_continuationToken` | ❌ | ✅ | ✅ | ✅ | ✅ |
|
|
46
|
+
|
|
47
|
+
## Writing the mock api
|
|
48
|
+
|
|
49
|
+
Each scenario should be accompanied by a mock api. See [writing a mock api docs](./writing-mock-apis.md)
|
|
@@ -1,5 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
// An error in the imports would mean that the decorator is not exported or
|
|
2
|
+
// doesn't have the right name.
|
|
3
|
+
|
|
2
4
|
import { $decorators } from "@typespec/spector";
|
|
3
5
|
import type { TypeSpecSpectorDecorators } from "./TypeSpec.Spector.js";
|
|
4
|
-
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* An error here would mean that the exported decorator is not using the same signature. Make sure to have export const $decName: DecNameDecorator = (...) => ...
|
|
9
|
+
*/
|
|
5
10
|
const _: TypeSpecSpectorDecorators = $decorators["TypeSpec.Spector"];
|
package/lib/main.tsp
CHANGED
|
@@ -23,7 +23,7 @@ extern dec scenarioService(
|
|
|
23
23
|
/**
|
|
24
24
|
* Mark an operation, interface or namespace as a scenario. All containing operations will be part of the same scenario.
|
|
25
25
|
*/
|
|
26
|
-
extern dec scenario(target: Namespace | Interface | Operation, name?: valueof string);
|
|
26
|
+
extern dec `scenario`(target: Namespace | Interface | Operation, name?: valueof string);
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
29
|
* Specify documentation on how to implement this scenario.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@typespec/spector",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.20-dev.0",
|
|
4
4
|
"description": "Typespec Core Tool to validate, run mock api, collect coverage.",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -26,51 +26,46 @@
|
|
|
26
26
|
},
|
|
27
27
|
"homepage": "https://github.com/microsoft/typespec#readme",
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@azure/identity": "~4.
|
|
29
|
+
"@azure/identity": "~4.12.0",
|
|
30
30
|
"@types/js-yaml": "^4.0.5",
|
|
31
|
-
"@typespec/compiler": "
|
|
32
|
-
"@typespec/
|
|
33
|
-
"@typespec/
|
|
34
|
-
"@typespec/
|
|
35
|
-
"@typespec/spec-
|
|
36
|
-
"@typespec/
|
|
31
|
+
"@typespec/compiler": "^1.5.0",
|
|
32
|
+
"@typespec/http": "^1.5.0",
|
|
33
|
+
"@typespec/rest": "^0.75.0 || >=0.76.0-dev <0.76.0",
|
|
34
|
+
"@typespec/spec-api": "^0.1.0-alpha.9 || >=0.1.0-alpha.10-dev <0.1.0-alpha.10",
|
|
35
|
+
"@typespec/spec-coverage-sdk": "^0.1.0-alpha.11 || >=0.1.0-alpha.12-dev <0.1.0-alpha.12",
|
|
36
|
+
"@typespec/versioning": "^0.75.0 || >=0.76.0-dev <0.76.0",
|
|
37
37
|
"ajv": "~8.17.1",
|
|
38
|
-
"
|
|
39
|
-
"body-parser": "^1.20.3",
|
|
38
|
+
"body-parser": "^2.2.0",
|
|
40
39
|
"deep-equal": "^2.2.0",
|
|
41
|
-
"express": "^
|
|
42
|
-
"
|
|
43
|
-
"form-data": "^4.0.1",
|
|
44
|
-
"globby": "~14.0.2",
|
|
45
|
-
"jackspeak": "4.0.2",
|
|
40
|
+
"express": "^5.1.0",
|
|
41
|
+
"globby": "~14.1.0",
|
|
46
42
|
"js-yaml": "^4.1.0",
|
|
43
|
+
"micromatch": "^4.0.8",
|
|
47
44
|
"morgan": "^1.10.0",
|
|
48
|
-
"multer": "^
|
|
49
|
-
"
|
|
50
|
-
"picocolors": "~1.1.0",
|
|
45
|
+
"multer": "^2.0.1",
|
|
46
|
+
"picocolors": "~1.1.1",
|
|
51
47
|
"source-map-support": "~0.5.21",
|
|
52
|
-
"winston": "^3.15.0",
|
|
53
48
|
"xml2js": "^0.6.2",
|
|
54
|
-
"yargs": "~
|
|
49
|
+
"yargs": "~18.0.0"
|
|
55
50
|
},
|
|
56
51
|
"devDependencies": {
|
|
57
52
|
"@types/body-parser": "^1.19.2",
|
|
58
53
|
"@types/deep-equal": "^1.0.1",
|
|
59
|
-
"@types/express": "^5.0.
|
|
60
|
-
"@types/
|
|
61
|
-
"@types/
|
|
62
|
-
"@types/
|
|
63
|
-
"@types/node
|
|
54
|
+
"@types/express": "^5.0.1",
|
|
55
|
+
"@types/micromatch": "^4.0.9",
|
|
56
|
+
"@types/morgan": "^1.9.9",
|
|
57
|
+
"@types/multer": "^2.0.0",
|
|
58
|
+
"@types/node": "~24.3.0",
|
|
64
59
|
"@types/xml2js": "^0.4.11",
|
|
65
60
|
"@types/yargs": "~17.0.33",
|
|
61
|
+
"@typespec/tspd": "^0.73.0 || >=0.74.0-dev <0.74.0",
|
|
66
62
|
"rimraf": "~6.0.1",
|
|
67
|
-
"typescript": "~5.
|
|
68
|
-
"@typespec/tspd": "~0.46.0"
|
|
63
|
+
"typescript": "~5.9.2"
|
|
69
64
|
},
|
|
70
65
|
"peerDependencies": {},
|
|
71
66
|
"scripts": {
|
|
72
67
|
"watch": "tsc -p ./tsconfig.build.json --watch",
|
|
73
|
-
"build": "
|
|
68
|
+
"build": "pnpm gen-extern-signature && tsc -p tsconfig.build.json",
|
|
74
69
|
"clean": "rimraf dist/ temp/",
|
|
75
70
|
"gen-extern-signature": "tspd --enable-experimental gen-extern-signature .",
|
|
76
71
|
"test": "vitest run",
|