Skip to content

Commit 9f70407

Browse files
authored
Merge pull request #477 from open-rpc/feat/rules-refactor
feat: add the concept of rules and refactor existing code into rules
2 parents 4925105 + cc53ffc commit 9f70407

15 files changed

+840
-159
lines changed

bin/cli.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ program
1515
.version(require('./get-version'))
1616
.usage('[options]')
1717
.option('-s, --schema [schema]', 'JSON string or a Path/Url pointing to an open rpc schema')
18-
.option('-r, --reporters <reporters>', 'Use the specified reporter [console] [json] [empty]. Can be a comma separated list of reporters.')
18+
.option('-r, --reporters <reporters>', 'Use the specified reporter [console] [console-rule] [console-streaming] [json] [empty]. Can be a comma separated list of reporters.')
1919
.option('-t, --transport <transport>', 'Use the specified transport [http]')
2020
.option('--skip <skip>', 'Methods to skip. Comma separated list of method names')
2121
.option('--only <only>', 'Methods to only run. Comma separated list of method names')

src/coverage.test.ts

Lines changed: 78 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
import coverage, { ExampleCall, IOptions } from "./coverage";
1+
import coverage, { Call, IOptions } from "./coverage";
22
import { OpenrpcDocument } from "@open-rpc/meta-schema";
33
import EmptyReporter from "./reporters/emptyReporter";
44
import ConsoleReporter from "./reporters/console";
5+
import Rule from "./rules/rule";
6+
import ExamplesRule from "./rules/examples-rule";
7+
import JsonSchemaFakerRule from "./rules/json-schema-faker-rule";
58

69
const mockSchema = {
710
openrpc: "1.0.0",
@@ -64,7 +67,7 @@ const mockSchema = {
6467
{
6568
name: "barParam2",
6669
value: "bar",
67-
}
70+
},
6871
],
6972
result: {
7073
name: "fooResult",
@@ -116,6 +119,53 @@ const mockSchema = {
116119
} as OpenrpcDocument;
117120

118121
describe("coverage", () => {
122+
describe("rules", () => {
123+
it("can call multiple rules with different async or sync lifecycle functions", async () => {
124+
const reporter = new EmptyReporter();
125+
const transport = () => Promise.resolve({});
126+
const openrpcDocument = mockSchema;
127+
const exampleRule = new ExamplesRule({ skip: ["foo"], only: ["baz"] });
128+
const jsonSchemaFakerRule = new JsonSchemaFakerRule({ skip: ["baz"], only: [] });
129+
const jsonSchemaFakerRule2 = new JsonSchemaFakerRule({
130+
skip: [],
131+
only: ["foo", "bar"],
132+
});
133+
class MyCustomRule implements Rule {
134+
getTitle(): string {
135+
return "My custom rule";
136+
}
137+
getCalls(openrpcDocument: OpenrpcDocument, method: any) {
138+
return [];
139+
}
140+
async validateCall(call: Call) {
141+
return call;
142+
}
143+
}
144+
const myCustomRule = new MyCustomRule();
145+
146+
const getCallsSpy = jest.spyOn(exampleRule, "getCalls");
147+
const getCallsCustomSpy = jest.spyOn(
148+
myCustomRule,
149+
"getCalls"
150+
);
151+
const getCallsJsonSchemaFakerSpy = jest.spyOn(
152+
jsonSchemaFakerRule,
153+
"getCalls"
154+
);
155+
const options = {
156+
reporters: [reporter],
157+
rules: [exampleRule, myCustomRule, jsonSchemaFakerRule, jsonSchemaFakerRule2],
158+
transport,
159+
openrpcDocument,
160+
skip: [],
161+
only: [],
162+
};
163+
await coverage(options);
164+
expect(getCallsSpy).toHaveBeenCalled();
165+
expect(getCallsCustomSpy).toHaveBeenCalled();
166+
expect(getCallsJsonSchemaFakerSpy).toHaveBeenCalled();
167+
});
168+
});
119169
describe("reporter", () => {
120170
it("can call the reporter", (done) => {
121171
class CustomReporter {
@@ -140,8 +190,8 @@ describe("coverage", () => {
140190
onBegin() {}
141191
onTestBegin() {}
142192
onTestEnd() {}
143-
onEnd(options: IOptions, exampleCalls: ExampleCall[]) {
144-
expect(exampleCalls[0].result).toBe(true);
193+
onEnd(options: IOptions, calls: Call[]) {
194+
expect(calls[0].result).toBe(true);
145195
done();
146196
}
147197
}
@@ -159,24 +209,24 @@ describe("coverage", () => {
159209
});
160210
describe("coverage tests", () => {
161211
it("throws an error when there are no methods", async () => {
162-
const reporter = new class CustomReporter {
212+
const reporter = new (class CustomReporter {
163213
onBegin() {}
164214
onTestBegin() {}
165215
onTestEnd() {}
166216
onEnd() {}
167-
};
217+
})();
168218
const spy = jest.spyOn(reporter, "onTestBegin");
169219
const transport = () => Promise.resolve({});
170220
const openrpcDocument = mockSchema;
171221
const options = {
172222
reporters: [reporter],
173223
transport,
174224
openrpcDocument,
175-
skip: ['foo', 'bar', 'baz'],
225+
skip: ["foo", "bar", "baz"],
176226
only: [],
177227
};
178228

179-
await expect(coverage(options)).rejects.toThrow('No methods to test');
229+
await expect(coverage(options)).rejects.toThrow("No methods to test");
180230
});
181231
it("can get to expectedResult checking with no servers", async () => {
182232
const reporter = new class CustomReporter {
@@ -187,32 +237,34 @@ describe("coverage", () => {
187237
};
188238
const spy = jest.spyOn(reporter, "onTestBegin");
189239
const transport = () => Promise.resolve({});
190-
const openrpcDocument = {...mockSchema};
240+
const openrpcDocument = { ...mockSchema };
191241
openrpcDocument.servers = undefined;
192242
const options = {
193243
reporters: [reporter],
194244
transport,
195245
openrpcDocument,
196246
skip: [],
197-
only: ['baz'],
247+
only: ["baz"],
198248
};
199249

200250
await expect(coverage(options)).resolves.toBeDefined();
201251
});
202252
});
203253
describe("transport", () => {
204-
it("can call the transport", (done) => {
205-
const transport = () => {
206-
done();
207-
return Promise.resolve({});
208-
};
209-
coverage({
254+
it("can call the transport", async () => {
255+
const transport = jest.fn();
256+
await coverage({
210257
reporters: [new EmptyReporter()],
211258
transport,
212-
openrpcDocument: mockSchema,
259+
openrpcDocument: {
260+
openrpc: "1.2.6",
261+
info: { title: "f", version: "0.0.0" },
262+
methods: [mockSchema.methods[0]],
263+
},
213264
skip: [],
214265
only: [],
215266
});
267+
await expect(transport).toHaveBeenCalled();
216268
});
217269
});
218270
describe("reporter more tests", () => {
@@ -234,13 +286,13 @@ describe("coverage", () => {
234286
await coverage(options);
235287
expect(reporter.onBegin).toHaveBeenCalled();
236288
});
237-
it("onTestBegin is called", async () => {
238-
const reporter = new class CustomReporter {
289+
it("onTestBegin is called", async () => {
290+
const reporter = new (class CustomReporter {
239291
onBegin() {}
240292
onTestBegin() {}
241293
onTestEnd() {}
242294
onEnd() {}
243-
};
295+
})();
244296
const spy = jest.spyOn(reporter, "onTestBegin");
245297
const transport = () => Promise.resolve({});
246298
const openrpcDocument = mockSchema;
@@ -253,7 +305,7 @@ describe("coverage", () => {
253305
};
254306

255307
await coverage(options);
256-
expect(spy).toHaveBeenCalledTimes(12);
308+
expect(spy).toHaveBeenCalledTimes(3);
257309
});
258310
it("can handle multiple reporters", async () => {
259311
const reporter = new EmptyReporter();
@@ -281,14 +333,14 @@ describe("coverage", () => {
281333
await coverage(options);
282334

283335
expect(onBeginSpy).toHaveBeenCalledTimes(1);
284-
expect(onTestBeginSpy).toHaveBeenCalledTimes(12);
285-
expect(onTestEndSpy).toHaveBeenCalledTimes(12);
336+
expect(onTestBeginSpy).toHaveBeenCalledTimes(3);
337+
expect(onTestEndSpy).toHaveBeenCalledTimes(3);
286338
expect(onEndSpy).toHaveBeenCalledTimes(1);
287339

288340
expect(onBeginSpy2).toHaveBeenCalledTimes(1);
289-
expect(onTestBeginSpy2).toHaveBeenCalledTimes(12);
290-
expect(onTestEndSpy2).toHaveBeenCalledTimes(12);
341+
expect(onTestBeginSpy2).toHaveBeenCalledTimes(3);
342+
expect(onTestEndSpy2).toHaveBeenCalledTimes(3);
291343
expect(onEndSpy2).toHaveBeenCalledTimes(1);
292-
})
344+
});
293345
});
294346
});

0 commit comments

Comments
 (0)