counterfact 0.10.2 → 0.10.3
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 +6 -0
- package/README.md +74 -19
- package/package.json +1 -1
- package/src/typescript-generator/operation-coder.js +2 -2
- package/src/typescript-generator/script.js +5 -4
- package/test/typescript-generator/__snapshots__/end-to-end.test.js.snap +26 -26
- package/test/typescript-generator/__snapshots__/operation-coder.test.js.snap +4 -4
- package/test/typescript-generator/integration.test.js +2 -2
- package/test/typescript-generator/script.test.js +1 -1
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -1,44 +1,99 @@
|
|
|
1
|
+
|
|
2
|
+
<div align="right">
|
|
3
|
+
|
|
4
|
+
[](https://coveralls.io/github/pmcelhaney/counterfact) [](https://dashboard.stryker-mutator.io/reports/github.com/pmcelhaney/counterfact/main) 
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
</div>
|
|
8
|
+
|
|
9
|
+
<div align="center">
|
|
10
|
+
|
|
1
11
|
# Counterfact
|
|
2
12
|
|
|
3
|
-
|
|
13
|
+
_Front end development without back end headaches_
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
[Watch Demo](#watch-demo) | [Quick Start](#quick-start) | [Documentation](#documentation) | [Support](#support)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
</div>
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
<div align="center">
|
|
27
|
+
Counterfact is a stand-in REST server powered by Node, TypeScript, and OpenAPI.<br>It simulates complex, stateful back end behavior without running the whole stack.
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
<br>
|
|
31
|
+
|
|
32
|
+
<table align="center" cols="2">
|
|
33
|
+
|
|
34
|
+
<tr>
|
|
35
|
+
<td>
|
|
36
|
+
|
|
37
|
+
💪 build the UI before the API or build both in parallel<br>
|
|
38
|
+
🏎️ quickly and cheaply prototype UX workflows<br>
|
|
39
|
+
🎉 turn OpenAPI docs into functional code
|
|
40
|
+
|
|
41
|
+
</td>
|
|
42
|
+
|
|
43
|
+
<td>
|
|
44
|
+
|
|
45
|
+
⛓️ write fast, repeatable UI integration tests<br>
|
|
46
|
+
🧑🔬 test UI code against hard-to-recreate edge cases<br>
|
|
47
|
+
🔌 plug into your existing toolchain
|
|
48
|
+
|
|
49
|
+
</td>
|
|
50
|
+
|
|
51
|
+
</tr>
|
|
52
|
+
|
|
53
|
+
</table>
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
<div id="watch-demo" align="center">
|
|
4
57
|
|
|
5
|
-
|
|
58
|
+
```
|
|
6
59
|
|
|
7
|
-
> This project is a work in progress. As of September 18, 2022, most of the plumbing is in place but the [APIs are still solidifying](https://github.com/pmcelhaney/counterfact/issues/204) and it's not quite ready for day-to-day use. See the [Version 1.0](https://github.com/pmcelhaney/counterfact/milestone/3) and [Future](https://github.com/pmcelhaney/counterfact/milestone/5) milestones.
|
|
8
60
|
|
|
9
61
|
|
|
10
|
-
## What is Counterfact?
|
|
11
62
|
|
|
12
|
-
Counterfact automatically builds a reference implementation of your [OpenAPI](https://www.openapis.org/) document. It uses metadata from the OpenAPI document to generate random, valid responses.
|
|
13
63
|
|
|
14
|
-
|
|
64
|
+
video will go here
|
|
15
65
|
|
|
16
|
-
Counterfact generates **TypeScript** code that you can **edit** to replace the random responses with real implementations.
|
|
17
66
|
|
|
18
|
-
## What do you mean "real" implementation?
|
|
19
67
|
|
|
20
|
-
That's up to you! You can build a fully functional back-end if you like. Connect to a MongoDB, call other APIs, etc.
|
|
21
68
|
|
|
22
|
-
|
|
69
|
+
```
|
|
70
|
+
</div>
|
|
23
71
|
|
|
24
|
-
## What do you mean by "fake" implementation?
|
|
25
72
|
|
|
26
|
-
|
|
73
|
+
## Quick Start
|
|
27
74
|
|
|
28
|
-
|
|
75
|
+
Try it now with one command. The only prequisite is Node 16+.
|
|
29
76
|
|
|
30
|
-
|
|
77
|
+
```sh copy
|
|
78
|
+
npx counterfact@latest https://petstore3.swagger.io/api/v3/openapi.json api --open
|
|
79
|
+
```
|
|
31
80
|
|
|
32
|
-
|
|
81
|
+
### What does it do?
|
|
33
82
|
|
|
34
|
-
|
|
83
|
+
1. installs the `@latest` version of `counterfact`
|
|
84
|
+
2. reads an [OpenAPI 3](https://oai.github.io/Documentation/) document (`https://petstore3.swagger.io/api/v3/openapi.json`)
|
|
85
|
+
3. generates TypeScript files in the `api` directory
|
|
86
|
+
4. starts a server which implements the API
|
|
87
|
+
5. opens your browser to [Swagger UI](https://swagger.io/tools/swagger-ui/) (`--open`)
|
|
35
88
|
|
|
36
|
-
You
|
|
89
|
+
You can use Swagger to try out the auto-generated API. Out of the box, it returns random responses using metadata from the OpenAPI document. You can edit the files under `./api/paths` to add more realistic behavior. There's no need to restart the server.
|
|
37
90
|
|
|
38
|
-
## What else does it do!
|
|
39
91
|
|
|
40
|
-
|
|
92
|
+
## Documentation
|
|
41
93
|
|
|
94
|
+
Coming soon!
|
|
42
95
|
|
|
43
96
|
|
|
97
|
+
## Support
|
|
44
98
|
|
|
99
|
+
Counterfact is brand new as of October 3, 2022. Please send feedback / questions to pmcelhaney@gmail.com or [create a new issue](https://github.com/pmcelhaney/counterfact/issues/new). If you like what you see, please give this project a star!
|
package/package.json
CHANGED
|
@@ -23,8 +23,8 @@ export class OperationCoder extends Coder {
|
|
|
23
23
|
return "() => { /* no response content specified in the OpenAPI document */ }";
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
return `(
|
|
27
|
-
return response[${
|
|
26
|
+
return `($) => {
|
|
27
|
+
return $.response[${
|
|
28
28
|
firstStatusCode === "default" ? 200 : firstStatusCode
|
|
29
29
|
}].random();
|
|
30
30
|
}`;
|
|
@@ -181,9 +181,10 @@ export class Script {
|
|
|
181
181
|
|
|
182
182
|
contents() {
|
|
183
183
|
return [
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
184
|
+
this.externalImportsStatements().join("\n"),
|
|
185
|
+
this.importStatements().join("\n"),
|
|
186
|
+
"\n\n",
|
|
187
|
+
this.exportStatements().join("\n\n"),
|
|
188
|
+
].join("");
|
|
188
189
|
}
|
|
189
190
|
}
|
|
@@ -11,8 +11,8 @@ Map {
|
|
|
11
11
|
},
|
|
12
12
|
"exports": Map {
|
|
13
13
|
"POST" => Object {
|
|
14
|
-
"code": "(
|
|
15
|
-
return response[200].random();
|
|
14
|
+
"code": "($) => {
|
|
15
|
+
return $.response[200].random();
|
|
16
16
|
}",
|
|
17
17
|
"done": true,
|
|
18
18
|
"id": "OperationCoder@petstore.yaml#/paths/~1pet/post",
|
|
@@ -23,8 +23,8 @@ Map {
|
|
|
23
23
|
"typeDeclaration": "HTTP_POST",
|
|
24
24
|
},
|
|
25
25
|
"PUT" => Object {
|
|
26
|
-
"code": "(
|
|
27
|
-
return response[200].random();
|
|
26
|
+
"code": "($) => {
|
|
27
|
+
return $.response[200].random();
|
|
28
28
|
}",
|
|
29
29
|
"done": true,
|
|
30
30
|
"id": "OperationCoder@petstore.yaml#/paths/~1pet/put",
|
|
@@ -926,8 +926,8 @@ Map {
|
|
|
926
926
|
},
|
|
927
927
|
"exports": Map {
|
|
928
928
|
"GET" => Object {
|
|
929
|
-
"code": "(
|
|
930
|
-
return response[200].random();
|
|
929
|
+
"code": "($) => {
|
|
930
|
+
return $.response[200].random();
|
|
931
931
|
}",
|
|
932
932
|
"done": true,
|
|
933
933
|
"id": "OperationCoder@petstore.yaml#/paths/~1pet~1findByStatus/get",
|
|
@@ -1350,8 +1350,8 @@ Map {
|
|
|
1350
1350
|
},
|
|
1351
1351
|
"exports": Map {
|
|
1352
1352
|
"GET" => Object {
|
|
1353
|
-
"code": "(
|
|
1354
|
-
return response[200].random();
|
|
1353
|
+
"code": "($) => {
|
|
1354
|
+
return $.response[200].random();
|
|
1355
1355
|
}",
|
|
1356
1356
|
"done": true,
|
|
1357
1357
|
"id": "OperationCoder@petstore.yaml#/paths/~1pet~1findByTags/get",
|
|
@@ -1778,8 +1778,8 @@ Map {
|
|
|
1778
1778
|
},
|
|
1779
1779
|
"exports": Map {
|
|
1780
1780
|
"GET" => Object {
|
|
1781
|
-
"code": "(
|
|
1782
|
-
return response[200].random();
|
|
1781
|
+
"code": "($) => {
|
|
1782
|
+
return $.response[200].random();
|
|
1783
1783
|
}",
|
|
1784
1784
|
"done": true,
|
|
1785
1785
|
"id": "OperationCoder@petstore.yaml#/paths/~1pet~1{petId}/get",
|
|
@@ -3118,8 +3118,8 @@ Map {
|
|
|
3118
3118
|
},
|
|
3119
3119
|
"exports": Map {
|
|
3120
3120
|
"POST" => Object {
|
|
3121
|
-
"code": "(
|
|
3122
|
-
return response[200].random();
|
|
3121
|
+
"code": "($) => {
|
|
3122
|
+
return $.response[200].random();
|
|
3123
3123
|
}",
|
|
3124
3124
|
"done": true,
|
|
3125
3125
|
"id": "OperationCoder@petstore.yaml#/paths/~1pet~1{petId}~1uploadImage/post",
|
|
@@ -3380,8 +3380,8 @@ Map {
|
|
|
3380
3380
|
},
|
|
3381
3381
|
"exports": Map {
|
|
3382
3382
|
"GET" => Object {
|
|
3383
|
-
"code": "(
|
|
3384
|
-
return response[200].random();
|
|
3383
|
+
"code": "($) => {
|
|
3384
|
+
return $.response[200].random();
|
|
3385
3385
|
}",
|
|
3386
3386
|
"done": true,
|
|
3387
3387
|
"id": "OperationCoder@petstore.yaml#/paths/~1store~1inventory/get",
|
|
@@ -3580,8 +3580,8 @@ Map {
|
|
|
3580
3580
|
},
|
|
3581
3581
|
"exports": Map {
|
|
3582
3582
|
"POST" => Object {
|
|
3583
|
-
"code": "(
|
|
3584
|
-
return response[200].random();
|
|
3583
|
+
"code": "($) => {
|
|
3584
|
+
return $.response[200].random();
|
|
3585
3585
|
}",
|
|
3586
3586
|
"done": true,
|
|
3587
3587
|
"id": "OperationCoder@petstore.yaml#/paths/~1store~1order/post",
|
|
@@ -3864,8 +3864,8 @@ Map {
|
|
|
3864
3864
|
},
|
|
3865
3865
|
"exports": Map {
|
|
3866
3866
|
"GET" => Object {
|
|
3867
|
-
"code": "(
|
|
3868
|
-
return response[200].random();
|
|
3867
|
+
"code": "($) => {
|
|
3868
|
+
return $.response[200].random();
|
|
3869
3869
|
}",
|
|
3870
3870
|
"done": true,
|
|
3871
3871
|
"id": "OperationCoder@petstore.yaml#/paths/~1store~1order~1{orderId}/get",
|
|
@@ -4540,8 +4540,8 @@ Map {
|
|
|
4540
4540
|
},
|
|
4541
4541
|
"exports": Map {
|
|
4542
4542
|
"POST" => Object {
|
|
4543
|
-
"code": "(
|
|
4544
|
-
return response[200].random();
|
|
4543
|
+
"code": "($) => {
|
|
4544
|
+
return $.response[200].random();
|
|
4545
4545
|
}",
|
|
4546
4546
|
"done": true,
|
|
4547
4547
|
"id": "OperationCoder@petstore.yaml#/paths/~1user/post",
|
|
@@ -4814,8 +4814,8 @@ Map {
|
|
|
4814
4814
|
},
|
|
4815
4815
|
"exports": Map {
|
|
4816
4816
|
"POST" => Object {
|
|
4817
|
-
"code": "(
|
|
4818
|
-
return response[200].random();
|
|
4817
|
+
"code": "($) => {
|
|
4818
|
+
return $.response[200].random();
|
|
4819
4819
|
}",
|
|
4820
4820
|
"done": true,
|
|
4821
4821
|
"id": "OperationCoder@petstore.yaml#/paths/~1user~1createWithList/post",
|
|
@@ -5112,8 +5112,8 @@ Map {
|
|
|
5112
5112
|
},
|
|
5113
5113
|
"exports": Map {
|
|
5114
5114
|
"GET" => Object {
|
|
5115
|
-
"code": "(
|
|
5116
|
-
return response[200].random();
|
|
5115
|
+
"code": "($) => {
|
|
5116
|
+
return $.response[200].random();
|
|
5117
5117
|
}",
|
|
5118
5118
|
"done": true,
|
|
5119
5119
|
"id": "OperationCoder@petstore.yaml#/paths/~1user~1login/get",
|
|
@@ -5546,8 +5546,8 @@ Map {
|
|
|
5546
5546
|
},
|
|
5547
5547
|
"exports": Map {
|
|
5548
5548
|
"GET" => Object {
|
|
5549
|
-
"code": "(
|
|
5550
|
-
return response[200].random();
|
|
5549
|
+
"code": "($) => {
|
|
5550
|
+
return $.response[200].random();
|
|
5551
5551
|
}",
|
|
5552
5552
|
"done": true,
|
|
5553
5553
|
"id": "OperationCoder@petstore.yaml#/paths/~1user~1{username}/get",
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
2
|
|
|
3
3
|
exports[`an OperationCoder generates a complex get operation 1`] = `
|
|
4
|
-
"(
|
|
5
|
-
return response[200].random();
|
|
4
|
+
"($) => {
|
|
5
|
+
return $.response[200].random();
|
|
6
6
|
};
|
|
7
7
|
"
|
|
8
8
|
`;
|
|
9
9
|
|
|
10
10
|
exports[`an OperationCoder generates a simple post operation 1`] = `
|
|
11
|
-
"(
|
|
12
|
-
return response[200].random();
|
|
11
|
+
"($) => {
|
|
12
|
+
return $.response[200].random();
|
|
13
13
|
};
|
|
14
14
|
"
|
|
15
15
|
`;
|
|
@@ -47,10 +47,10 @@ describe("integration Test", () => {
|
|
|
47
47
|
await account.finished();
|
|
48
48
|
|
|
49
49
|
expect(account.contents()).toBe(
|
|
50
|
-
"
|
|
50
|
+
"\n\nexport const HTTP_GET = () => {};\n\nexport const HTTP_POST = () => {};"
|
|
51
51
|
);
|
|
52
52
|
expect(accountId.contents()).toBe(
|
|
53
|
-
"
|
|
53
|
+
"\n\nexport const HTTP_GET = () => {};\n\nexport const HTTP_PUT = () => {};"
|
|
54
54
|
);
|
|
55
55
|
});
|
|
56
56
|
});
|
|
@@ -147,7 +147,7 @@ describe("a Script", () => {
|
|
|
147
147
|
];
|
|
148
148
|
|
|
149
149
|
expect(script.contents()).toBe(
|
|
150
|
-
'import { foo } from \'./foo.js;\nexport const bar = "Bar";\nexport default class {};'
|
|
150
|
+
'import { foo } from \'./foo.js;\n\nexport const bar = "Bar";\n\nexport default class {};'
|
|
151
151
|
);
|
|
152
152
|
});
|
|
153
153
|
});
|