Skip to content

Commit fe2d5f9

Browse files
author
iexitdev
committed
test(maintainability): enforce source file size budget
1 parent 712a396 commit fe2d5f9

6 files changed

Lines changed: 364 additions & 134 deletions

File tree

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@
4040
"registry": "https://registry.npmjs.org/"
4141
},
4242
"scripts": {
43-
"lint": "eslint .",
43+
"lint": "eslint . && npm run filesize:check",
44+
"filesize:check": "node scripts/check-file-sizes.mjs",
4445
"format": "prettier --write .",
4546
"format:check": "prettier --check .",
4647
"surface:check": "node scripts/verify-public-surface.mjs && node scripts/verify-package-boundaries.mjs && node scripts/verify-pro-preview-imports.mjs",
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
import {
2+
Children,
3+
isValidElement,
4+
type ReactElement,
5+
type ReactNode
6+
} from "react";
7+
import { describe, expect, it, vi } from "vitest";
8+
9+
vi.mock("@chart-kit/svg-renderer", () => {
10+
const MockPrimitive = () => null;
11+
12+
return {
13+
SvgClipRect: MockPrimitive,
14+
SvgCircle: MockPrimitive,
15+
SvgDefs: MockPrimitive,
16+
SvgGroup: MockPrimitive,
17+
SvgLayer: MockPrimitive,
18+
SvgLine: MockPrimitive,
19+
SvgLinearGradientDef: MockPrimitive,
20+
SvgPath: MockPrimitive,
21+
SvgRect: MockPrimitive,
22+
SvgSurface: MockPrimitive,
23+
SvgText: MockPrimitive,
24+
createSvgTextMeasurer: () => (text: string) => ({
25+
height: 14,
26+
width: text.length * 7
27+
}),
28+
createSvgTestId: (...parts: Array<string | number>) =>
29+
parts.map(String).join(".")
30+
};
31+
});
32+
33+
vi.mock("react-native", async () => {
34+
const React = await vi.importActual<typeof import("react")>("react");
35+
36+
return {
37+
View: ({
38+
children,
39+
...props
40+
}: {
41+
children?: ReactNode;
42+
[key: string]: unknown;
43+
}) => React.createElement("View", props, children)
44+
};
45+
});
46+
47+
import { renderLineChartDebugLayout } from "../src/charts/line/debugOverlay";
48+
import { StickyYAxis } from "../src/charts/line/StickyYAxis";
49+
import type { LineChartModel } from "../src/charts/line/useChartModel";
50+
import { resolveCartesianChartThemeConfig } from "../src/theme/presets";
51+
import {
52+
debugLayoutModel,
53+
getFragmentChildren,
54+
getRenderedChildren,
55+
skiaLikeRenderer
56+
} from "./line-renderer.fixtures";
57+
58+
describe("LineChart renderer overlay contract", () => {
59+
it("renders the debug overlay through injected primitives", () => {
60+
const debugNodes = getRenderedChildren(
61+
renderLineChartDebugLayout({
62+
fontFamily: undefined,
63+
model: debugLayoutModel,
64+
renderer: skiaLikeRenderer
65+
})
66+
);
67+
const debugChildren = getFragmentChildren(debugNodes[0]);
68+
69+
expect(debugNodes).toHaveLength(1);
70+
expect(debugChildren).toHaveLength(2);
71+
expect(debugChildren[0]?.props).toMatchObject({
72+
fill: "none",
73+
height: 120,
74+
stroke: "#22c55e",
75+
width: 240,
76+
x: 40,
77+
y: 20
78+
});
79+
expect(debugChildren[1]?.props).toMatchObject({
80+
fill: "#22c55e",
81+
fontSize: 9,
82+
text: "plot",
83+
x: 42,
84+
y: 17
85+
});
86+
});
87+
88+
it("renders sticky Y-axis labels through injected primitives", () => {
89+
const resolvedTheme = resolveCartesianChartThemeConfig({ mode: "light" });
90+
const node = StickyYAxis({
91+
fadeHeight: 120,
92+
fadeWidth: 16,
93+
fadeY: 0,
94+
gradientId: "sticky-y-axis-fade",
95+
mainHeight: 180,
96+
model: {
97+
boxes: {
98+
plot: {
99+
height: 120,
100+
width: 220,
101+
x: 48,
102+
y: 20
103+
}
104+
},
105+
resolvedTheme
106+
} as LineChartModel<Record<string, unknown>>,
107+
renderer: skiaLikeRenderer,
108+
width: 72,
109+
yAxisLabels: [
110+
{
111+
key: "tick-120000",
112+
opacity: 1,
113+
text: "$120k",
114+
y: 44
115+
}
116+
]
117+
});
118+
119+
expect(isValidElement<{ children?: ReactNode }>(node)).toBe(true);
120+
121+
if (!isValidElement<{ children?: ReactNode }>(node)) return;
122+
123+
const surface = Children.only(node.props.children);
124+
125+
expect(isValidElement<{ children?: ReactNode }>(surface)).toBe(true);
126+
127+
if (!isValidElement<{ children?: ReactNode }>(surface)) return;
128+
129+
const surfaceChildren = Children.toArray(surface.props.children).filter(
130+
isValidElement
131+
);
132+
const axesLayer = surfaceChildren[2];
133+
const labels = Children.toArray(
134+
isValidElement<{ children?: ReactNode }>(axesLayer)
135+
? axesLayer.props.children
136+
: undefined
137+
).filter(isValidElement);
138+
const firstLabel = labels[0] as
139+
| ReactElement<{ children?: ReactNode } & Record<string, unknown>>
140+
| undefined;
141+
142+
expect(labels).toHaveLength(1);
143+
expect(firstLabel?.props).toMatchObject({
144+
fill: resolvedTheme.mutedText,
145+
fontSize: resolvedTheme.typography.axisLabelSize,
146+
opacity: 1,
147+
textAnchor: "end",
148+
x: 40,
149+
y: 44
150+
});
151+
expect(firstLabel?.props.children).toBe("$120k");
152+
});
153+
154+
it("keeps debug rectangles when renderer text is unavailable", () => {
155+
const debugNodes = getRenderedChildren(
156+
renderLineChartDebugLayout({
157+
fontFamily: undefined,
158+
model: debugLayoutModel,
159+
renderer: {
160+
...skiaLikeRenderer,
161+
capabilities: {
162+
...skiaLikeRenderer.capabilities,
163+
text: false
164+
}
165+
}
166+
})
167+
);
168+
const debugChildren = getFragmentChildren(debugNodes[0]);
169+
170+
expect(debugChildren).toHaveLength(1);
171+
expect(debugChildren[0]?.props).toMatchObject({
172+
height: 120,
173+
stroke: "#22c55e",
174+
width: 240
175+
});
176+
});
177+
});

packages/react-native/test/line-renderer.test.ts

Lines changed: 1 addition & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,4 @@
1-
import {
2-
Children,
3-
isValidElement,
4-
type ReactElement,
5-
type ReactNode
6-
} from "react";
1+
import type { ReactNode } from "react";
72
import { describe, expect, it, vi } from "vitest";
83

94
vi.mock("@chart-kit/svg-renderer", () => {
@@ -49,10 +44,8 @@ import {
4944
lineChartSvgRenderer
5045
} from "../src/charts/line/renderer";
5146
import { renderDefaultTooltip } from "../src/charts/line/defaultTooltip";
52-
import { renderLineChartDebugLayout } from "../src/charts/line/debugOverlay";
5347
import { renderConfiguredLegend } from "../src/charts/line/legend";
5448
import { renderDefaultDot } from "../src/charts/line/markers";
55-
import { StickyYAxis } from "../src/charts/line/StickyYAxis";
5649
import { resolveCartesianChartThemeConfig } from "../src/theme/presets";
5750
import {
5851
LineChartAreaPaths,
@@ -68,13 +61,11 @@ import type { SkiaRenderer } from "../../skia-renderer/src/types";
6861
import {
6962
ElementPrimitive,
7063
Primitive,
71-
debugLayoutModel,
7264
defaultLegendConfig,
7365
defaultLegendProps,
7466
defaultTooltipProps,
7567
geometries,
7668
getFragmentChildren,
77-
getRenderedChildren,
7869
skiaLikeRenderer
7970
} from "./line-renderer.fixtures";
8071

@@ -385,127 +376,4 @@ describe("LineChart renderer parity contract", () => {
385376
})
386377
).toBeNull();
387378
});
388-
389-
it("renders the debug overlay through injected primitives", () => {
390-
const debugNodes = getRenderedChildren(
391-
renderLineChartDebugLayout({
392-
fontFamily: undefined,
393-
model: debugLayoutModel,
394-
renderer: skiaLikeRenderer
395-
})
396-
);
397-
const debugChildren = getFragmentChildren(debugNodes[0]);
398-
399-
expect(debugNodes).toHaveLength(1);
400-
expect(debugChildren).toHaveLength(2);
401-
expect(debugChildren[0]?.props).toMatchObject({
402-
fill: "none",
403-
height: 120,
404-
stroke: "#22c55e",
405-
width: 240,
406-
x: 40,
407-
y: 20
408-
});
409-
expect(debugChildren[1]?.props).toMatchObject({
410-
fill: "#22c55e",
411-
fontSize: 9,
412-
text: "plot",
413-
x: 42,
414-
y: 17
415-
});
416-
});
417-
418-
it("renders sticky Y-axis labels through injected primitives", () => {
419-
const resolvedTheme = resolveCartesianChartThemeConfig({ mode: "light" });
420-
const node = StickyYAxis({
421-
fadeHeight: 120,
422-
fadeWidth: 16,
423-
fadeY: 0,
424-
gradientId: "sticky-y-axis-fade",
425-
mainHeight: 180,
426-
model: {
427-
boxes: {
428-
plot: {
429-
height: 120,
430-
width: 220,
431-
x: 48,
432-
y: 20
433-
}
434-
},
435-
resolvedTheme
436-
} as LineChartModel<Record<string, unknown>>,
437-
renderer: skiaLikeRenderer,
438-
width: 72,
439-
yAxisLabels: [
440-
{
441-
key: "tick-120000",
442-
opacity: 1,
443-
text: "$120k",
444-
y: 44
445-
}
446-
]
447-
});
448-
449-
expect(isValidElement<{ children?: ReactNode }>(node)).toBe(true);
450-
451-
if (!isValidElement<{ children?: ReactNode }>(node)) {
452-
return;
453-
}
454-
455-
const surface = Children.only(node.props.children);
456-
457-
expect(isValidElement<{ children?: ReactNode }>(surface)).toBe(true);
458-
459-
if (!isValidElement<{ children?: ReactNode }>(surface)) {
460-
return;
461-
}
462-
463-
const surfaceChildren = Children.toArray(surface.props.children).filter(
464-
isValidElement
465-
);
466-
const axesLayer = surfaceChildren[2];
467-
const labels = Children.toArray(
468-
isValidElement<{ children?: ReactNode }>(axesLayer)
469-
? axesLayer.props.children
470-
: undefined
471-
).filter(isValidElement);
472-
const firstLabel = labels[0] as
473-
| ReactElement<{ children?: ReactNode } & Record<string, unknown>>
474-
| undefined;
475-
476-
expect(labels).toHaveLength(1);
477-
expect(firstLabel?.props).toMatchObject({
478-
fill: resolvedTheme.mutedText,
479-
fontSize: resolvedTheme.typography.axisLabelSize,
480-
opacity: 1,
481-
textAnchor: "end",
482-
x: 40,
483-
y: 44
484-
});
485-
expect(firstLabel?.props.children).toBe("$120k");
486-
});
487-
488-
it("keeps debug rectangles when renderer text is unavailable", () => {
489-
const debugNodes = getRenderedChildren(
490-
renderLineChartDebugLayout({
491-
fontFamily: undefined,
492-
model: debugLayoutModel,
493-
renderer: {
494-
...skiaLikeRenderer,
495-
capabilities: {
496-
...skiaLikeRenderer.capabilities,
497-
text: false
498-
}
499-
}
500-
})
501-
);
502-
const debugChildren = getFragmentChildren(debugNodes[0]);
503-
504-
expect(debugChildren).toHaveLength(1);
505-
expect(debugChildren[0]?.props).toMatchObject({
506-
height: 120,
507-
stroke: "#22c55e",
508-
width: 240
509-
});
510-
});
511379
});

0 commit comments

Comments
 (0)