Skip to content

Commit 3de8438

Browse files
committed
add tests for all main package api usage of blobOptions
1 parent a7fb31f commit 3de8438

File tree

2 files changed

+145
-109
lines changed

2 files changed

+145
-109
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"devDependencies": {
1919
"@types/jest": "^25.1.4",
2020
"jest": "^25.1.0",
21+
"jest-canvas-mock": "^2.2.0",
2122
"parcel": "^1.12.4",
2223
"prettier": "^2.0.2",
2324
"rollup": "^1.1.0",
@@ -54,6 +55,6 @@
5455
},
5556
"jest": {
5657
"preset": "ts-jest",
57-
"testEnvironment": "node"
58+
"setupFiles": ["jest-canvas-mock"]
5859
}
5960
}

public/blobs.test.ts

Lines changed: 143 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -1,129 +1,164 @@
1-
import {BlobOptions, svgPath} from "./blobs";
1+
import {BlobOptions, svg, svgPath, canvasPath, SvgOptions, CanvasOptions} from "./blobs";
22

3-
const genOptions = (): BlobOptions => ({
3+
const genBlobOptions = (): BlobOptions => ({
44
extraPoints: Math.floor(10 * Math.random()),
55
randomness: Math.floor(10 * Math.random()),
66
seed: Math.random(),
77
size: 100 + 200 * Math.random(),
88
});
99

10+
const genSvgOptions = (): SvgOptions => ({
11+
fill: String(Math.random()),
12+
stroke: String(Math.random()),
13+
strokeWidth: 4 * Math.random(),
14+
});
15+
16+
const genCanvasOptions = (): CanvasOptions => ({
17+
offsetX: 100 * Math.random(),
18+
offsetY: 100 * Math.random(),
19+
});
20+
1021
interface TestCase<T> {
1122
name: string;
1223
edit: (options: T) => void;
1324
error?: RegExp;
1425
}
1526

16-
describe("blobs", () => {
17-
describe("svgPath", () => {
18-
describe("options", () => {
19-
it("should accept generated blobOptions", () => {
20-
expect(() => svgPath(genOptions())).not.toThrow();
21-
});
27+
const runSuite = <T>(t: {
28+
optionsGenerator: () => T;
29+
functionBeingTested: (options: any) => void;
30+
}) => (testCases: TestCase<T>[]) => {
31+
for (const testCase of testCases) {
32+
it(testCase.name, () => {
33+
const options = t.optionsGenerator();
34+
testCase.edit(options);
2235

23-
it("should reject undefined blobOptions", () => {
24-
expect(() => svgPath(undefined as any)).toThrow(/blobOptions.*object.*undefined/g);
25-
});
36+
if (testCase.error) {
37+
// Copy regexp because they are stateful.
38+
const pattern = new RegExp(testCase.error);
39+
expect(() => t.functionBeingTested(options)).toThrow(pattern);
40+
} else {
41+
expect(() => t.functionBeingTested(options)).not.toThrow();
42+
}
43+
});
44+
}
45+
};
2646

27-
it("should reject invalid blobOptions", () => {
28-
expect(() => svgPath(null as any)).toThrow(/blobOptions.*object.*null/g);
29-
});
47+
const testBlobOptions = (functionBeingTested: (options: any) => void) => {
48+
it("should accept generated blobOptions", () => {
49+
expect(() => svgPath(genBlobOptions())).not.toThrow();
50+
});
3051

31-
const testCases: Array<TestCase<BlobOptions>> = [
32-
// seed
33-
{
34-
name: "should accept number blobOptions seed",
35-
edit: (blobOptions) => (blobOptions.seed = 123),
36-
},
37-
{
38-
name: "should accept string blobOptions seed",
39-
edit: (blobOptions) => (blobOptions.seed = "test"),
40-
},
41-
{
42-
name: "should reject undefined blobOptions seed",
43-
edit: (blobOptions) => delete blobOptions.seed,
44-
error: /seed.*string.*number.*undefined/g,
45-
},
46-
{
47-
name: "should reject broken blobOptions seed",
48-
edit: (blobOptions) => (blobOptions.seed = NaN),
49-
error: /seed.*string.*number.*NaN/g,
50-
},
51-
// extraPoints
52-
{
53-
name: "should accept valid blobOptions extraPoints",
54-
edit: (blobOptions) => (blobOptions.extraPoints = 4),
55-
},
56-
{
57-
name: "should reject undefined blobOptions extraPoints",
58-
edit: (blobOptions) => delete blobOptions.extraPoints,
59-
error: /blobOptions.*extraPoints.*number.*undefined/g,
60-
},
61-
{
62-
name: "should reject broken blobOptions extraPoints",
63-
edit: (blobOptions) => (blobOptions.extraPoints = NaN),
64-
error: /blobOptions.*extraPoints.*number.*NaN/g,
65-
},
66-
{
67-
name: "should reject negative blobOptions extraPoints",
68-
edit: (blobOptions) => (blobOptions.extraPoints = -2),
69-
error: /blobOptions.*extraPoints.*invalid/g,
70-
},
71-
// randomness
72-
{
73-
name: "should accept valid blobOptions randomness",
74-
edit: (blobOptions) => (blobOptions.randomness = 3),
75-
},
76-
{
77-
name: "should reject undefined blobOptions randomness",
78-
edit: (blobOptions) => delete blobOptions.randomness,
79-
error: /blobOptions.*randomness.*number.*undefined/g,
80-
},
81-
{
82-
name: "should reject broken blobOptions randomness",
83-
edit: (blobOptions) => (blobOptions.randomness = NaN),
84-
error: /blobOptions.*randomness.*number.*NaN/g,
85-
},
86-
{
87-
name: "should reject negative blobOptions randomness",
88-
edit: (blobOptions) => (blobOptions.randomness = -10),
89-
error: /blobOptions.*randomness.*invalid/g,
90-
},
91-
// size
92-
{
93-
name: "should accept valid blobOptions size",
94-
edit: (blobOptions) => (blobOptions.size = 40),
95-
},
96-
{
97-
name: "should reject undefined blobOptions size",
98-
edit: (blobOptions) => delete blobOptions.size,
99-
error: /blobOptions.*size.*number.*undefined/g,
100-
},
101-
{
102-
name: "should reject broken blobOptions size",
103-
edit: (blobOptions) => (blobOptions.size = NaN),
104-
error: /blobOptions.*size.*number.*NaN/g,
105-
},
106-
{
107-
name: "should reject negative blobOptions size",
108-
edit: (blobOptions) => (blobOptions.size = -1),
109-
error: /blobOptions.*size.*invalid/g,
110-
},
111-
];
52+
it("should reject undefined blobOptions", () => {
53+
expect(() => svgPath(undefined as any)).toThrow(/blobOptions.*object.*undefined/g);
54+
});
11255

113-
for (const testCase of testCases) {
114-
it(testCase.name, () => {
115-
const options = genOptions();
116-
testCase.edit(options);
56+
it("should reject invalid blobOptions", () => {
57+
expect(() => svgPath(null as any)).toThrow(/blobOptions.*object.*null/g);
58+
});
11759

118-
if (testCase.error) {
119-
// Copy regexp because they are stateful.
120-
const pattern = new RegExp(testCase.error);
121-
expect(() => svgPath(options)).toThrow(pattern);
122-
} else {
123-
expect(() => svgPath(options)).not.toThrow();
124-
}
125-
});
126-
}
60+
runSuite<BlobOptions>({
61+
functionBeingTested,
62+
optionsGenerator: genBlobOptions,
63+
})([
64+
// seed
65+
{
66+
name: "should accept number blobOptions seed",
67+
edit: (blobOptions) => (blobOptions.seed = 123),
68+
},
69+
{
70+
name: "should accept string blobOptions seed",
71+
edit: (blobOptions) => (blobOptions.seed = "test"),
72+
},
73+
{
74+
name: "should reject undefined blobOptions seed",
75+
edit: (blobOptions) => delete blobOptions.seed,
76+
error: /seed.*string.*number.*undefined/g,
77+
},
78+
{
79+
name: "should reject broken blobOptions seed",
80+
edit: (blobOptions) => (blobOptions.seed = NaN),
81+
error: /seed.*string.*number.*NaN/g,
82+
},
83+
// extraPoints
84+
{
85+
name: "should accept valid blobOptions extraPoints",
86+
edit: (blobOptions) => (blobOptions.extraPoints = 4),
87+
},
88+
{
89+
name: "should reject undefined blobOptions extraPoints",
90+
edit: (blobOptions) => delete blobOptions.extraPoints,
91+
error: /blobOptions.*extraPoints.*number.*undefined/g,
92+
},
93+
{
94+
name: "should reject broken blobOptions extraPoints",
95+
edit: (blobOptions) => (blobOptions.extraPoints = NaN),
96+
error: /blobOptions.*extraPoints.*number.*NaN/g,
97+
},
98+
{
99+
name: "should reject negative blobOptions extraPoints",
100+
edit: (blobOptions) => (blobOptions.extraPoints = -2),
101+
error: /blobOptions.*extraPoints.*invalid/g,
102+
},
103+
// randomness
104+
{
105+
name: "should accept valid blobOptions randomness",
106+
edit: (blobOptions) => (blobOptions.randomness = 3),
107+
},
108+
{
109+
name: "should reject undefined blobOptions randomness",
110+
edit: (blobOptions) => delete blobOptions.randomness,
111+
error: /blobOptions.*randomness.*number.*undefined/g,
112+
},
113+
{
114+
name: "should reject broken blobOptions randomness",
115+
edit: (blobOptions) => (blobOptions.randomness = NaN),
116+
error: /blobOptions.*randomness.*number.*NaN/g,
117+
},
118+
{
119+
name: "should reject negative blobOptions randomness",
120+
edit: (blobOptions) => (blobOptions.randomness = -10),
121+
error: /blobOptions.*randomness.*invalid/g,
122+
},
123+
// size
124+
{
125+
name: "should accept valid blobOptions size",
126+
edit: (blobOptions) => (blobOptions.size = 40),
127+
},
128+
{
129+
name: "should reject undefined blobOptions size",
130+
edit: (blobOptions) => delete blobOptions.size,
131+
error: /blobOptions.*size.*number.*undefined/g,
132+
},
133+
{
134+
name: "should reject broken blobOptions size",
135+
edit: (blobOptions) => (blobOptions.size = NaN),
136+
error: /blobOptions.*size.*number.*NaN/g,
137+
},
138+
{
139+
name: "should reject negative blobOptions size",
140+
edit: (blobOptions) => (blobOptions.size = -1),
141+
error: /blobOptions.*size.*invalid/g,
142+
},
143+
]);
144+
};
145+
146+
describe("blobs", () => {
147+
describe("canvasPath", () => {
148+
describe("blobOptions", () => {
149+
testBlobOptions((blobOptions) => canvasPath(blobOptions, genCanvasOptions()));
150+
});
151+
});
152+
153+
describe("svg", () => {
154+
describe("blobOptions", () => {
155+
testBlobOptions((blobOptions) => svg(blobOptions, genSvgOptions()));
156+
});
157+
});
158+
159+
describe("svgPath", () => {
160+
describe("blobOptions", () => {
161+
testBlobOptions(svgPath);
127162
});
128163
});
129164
});

0 commit comments

Comments
 (0)