Skip to content

Commit 2d0c342

Browse files
authored
fix(💚): add support for testID on Canvas in Jest (#3058)
1 parent d366abd commit 2d0c342

File tree

15 files changed

+49
-57
lines changed

15 files changed

+49
-57
lines changed

‎apps/paper/jestSetup.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ jest.mock("react-native-reanimated", () => {
2424
Reanimated.useEvent = () => {};
2525
Reanimated.scrollTo = () => {};
2626
Reanimated.useFrameCallback = () => {};
27+
Reanimated.convertToRGBA = () => {};
2728
return Reanimated;
2829
});
2930
// Silence the warning: Animated: `useNativeDriver` is not supported because the native animated module is missing

‎apps/paper/src/Examples/Breathe/Breathe.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ export const Breathe = () => {
6868

6969
return (
7070
<View style={{ flex: 1 }}>
71-
<Canvas style={styles.container} opaque>
71+
<Canvas style={styles.container} testID="breathe-canvas" opaque>
7272
<Fill color="rgb(36,43,56)" />
7373
<Group origin={center} transform={transform} blendMode="screen">
7474
<BlurMask style="solid" blur={40} />

‎apps/paper/src/Examples/Examples.test.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ import { Filters } from "./Filters";
1919
import { Boxes } from "./Boxes";
2020

2121
it("should render the Breathe example correctly", () => {
22-
render(<Breathe />);
22+
const { getByTestId } = render(<Breathe />);
23+
const breatheCanvas = getByTestId("breathe-canvas");
24+
expect(breatheCanvas).toBeTruthy();
2325
});
2426

2527
it("should render the Gooey example correctly", () => {

‎externals/skia

Submodule skia updated from b1fb88a to aefbd94

‎packages/skia/src/mock/index.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@ export const Mock = (CanvasKit: CanvasKit) => {
2121
...require("../animation"),
2222
...require("../dom/types"),
2323
...require("../dom/nodes"),
24-
// We could use the real Canvas if we mock the SkiaView component for node
25-
Canvas: Noop,
24+
Canvas: require("react-native").View,
2625
// Skia Animations
2726
useValue: NoopValue,
2827
useComputedValue: NoopValue,

‎packages/skia/src/skia/web/Host.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@ import type { CanvasKit, EmbindEnumEntity, EmbindEnum } from "canvaskit-wasm";
22

33
import type { SkJSIInstance } from "../types";
44

5-
export class NotImplementedOnRNWeb extends Error {
6-
constructor(msg?: string) {
7-
super(msg ?? "Not implemented on React Native Web");
5+
export const throwNotImplementedOnRNWeb = <T>(): T => {
6+
if (typeof jest !== "undefined") {
7+
return jest.fn() as unknown as T;
88
}
9-
}
9+
throw new Error("Not implemented on React Native Web");
10+
};
1011

1112
export abstract class Host {
1213
readonly CanvasKit: CanvasKit;

‎packages/skia/src/skia/web/JsiSkFont.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import type {
1010
SkTypeface,
1111
} from "../types";
1212

13-
import { HostObject, NotImplementedOnRNWeb, getEnum } from "./Host";
13+
import { HostObject, getEnum, throwNotImplementedOnRNWeb } from "./Host";
1414
import { JsiSkPaint } from "./JsiSkPaint";
1515
import { JsiSkPoint } from "./JsiSkPoint";
1616
import { JsiSkRect } from "./JsiSkRect";
@@ -21,8 +21,8 @@ export class JsiSkFont extends HostObject<Font, "Font"> implements SkFont {
2121
super(CanvasKit, ref, "Font");
2222
}
2323

24-
measureText(_text: string, _paint?: SkPaint | undefined): SkRect {
25-
throw new NotImplementedOnRNWeb();
24+
measureText(_text: string, _paint?: SkPaint | undefined) {
25+
return throwNotImplementedOnRNWeb<SkRect>();
2626
}
2727

2828
dispose = () => {

‎packages/skia/src/skia/web/JsiSkFontMgr.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type { CanvasKit, FontMgr } from "canvaskit-wasm";
22

33
import type { FontStyle, SkFontMgr, SkTypeface } from "../types";
44

5-
import { HostObject, NotImplementedOnRNWeb } from "./Host";
5+
import { HostObject, throwNotImplementedOnRNWeb } from "./Host";
66

77
export class JsiSkFontMgr
88
extends HostObject<FontMgr, "FontMgr">
@@ -20,7 +20,7 @@ export class JsiSkFontMgr
2020
getFamilyName(index: number) {
2121
return this.ref.getFamilyName(index);
2222
}
23-
matchFamilyStyle(_familyName: string, _fontStyle: FontStyle): SkTypeface {
24-
throw new NotImplementedOnRNWeb();
23+
matchFamilyStyle(_familyName: string, _fontStyle: FontStyle) {
24+
return throwNotImplementedOnRNWeb<SkTypeface>();
2525
}
2626
}

‎packages/skia/src/skia/web/JsiSkImageFactory.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import type {
99
ImageFactory,
1010
} from "../types";
1111

12-
import { Host, getEnum } from "./Host";
12+
import { Host, getEnum, throwNotImplementedOnRNWeb } from "./Host";
1313
import { JsiSkImage } from "./JsiSkImage";
1414
import { JsiSkData } from "./JsiSkData";
1515
import type { JsiSkSurface } from "./JsiSkSurface";
@@ -75,8 +75,8 @@ export class JsiSkImageFactory extends Host implements ImageFactory {
7575
return new JsiSkImage(this.CanvasKit, image);
7676
}
7777

78-
MakeImageFromNativeTextureUnstable(): SkImage {
79-
throw new Error("MakeImageFromNativeTexture is not implemented on web");
78+
MakeImageFromNativeTextureUnstable() {
79+
return throwNotImplementedOnRNWeb<SkImage>();
8080
}
8181

8282
MakeImage(info: ImageInfo, data: SkData, bytesPerRow: number) {

‎packages/skia/src/skia/web/JsiSkImageFilterFactory.ts

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import type {
1313
TileMode,
1414
} from "../types";
1515

16-
import { Host, NotImplementedOnRNWeb, getEnum } from "./Host";
16+
import { Host, throwNotImplementedOnRNWeb, getEnum } from "./Host";
1717
import { JsiSkImageFilter } from "./JsiSkImageFilter";
1818
import { JsiSkColorFilter } from "./JsiSkColorFilter";
1919

@@ -107,9 +107,7 @@ export class JsiSkImageFilterFactory
107107
const inputFilter =
108108
input === null ? null : JsiSkImageFilter.fromValue<ImageFilter>(input);
109109
if (cropRect) {
110-
throw new NotImplementedOnRNWeb(
111-
"The cropRect argument is not yet supported on React Native Web."
112-
);
110+
throwNotImplementedOnRNWeb<SkImageFilter>();
113111
}
114112
const filter = this.CanvasKit.ImageFilter.MakeDropShadow(
115113
dx,
@@ -134,9 +132,7 @@ export class JsiSkImageFilterFactory
134132
const inputFilter =
135133
input === null ? null : JsiSkImageFilter.fromValue<ImageFilter>(input);
136134
if (cropRect) {
137-
throw new NotImplementedOnRNWeb(
138-
"The cropRect argument is not yet supported on React Native Web."
139-
);
135+
throwNotImplementedOnRNWeb<SkImageFilter>();
140136
}
141137
const filter = this.CanvasKit.ImageFilter.MakeDropShadowOnly(
142138
dx,
@@ -158,9 +154,7 @@ export class JsiSkImageFilterFactory
158154
const inputFilter =
159155
input === null ? null : JsiSkImageFilter.fromValue<ImageFilter>(input);
160156
if (cropRect) {
161-
throw new NotImplementedOnRNWeb(
162-
"The cropRect argument is not yet supported on React Native Web."
163-
);
157+
throwNotImplementedOnRNWeb<SkImageFilter>();
164158
}
165159
const filter = this.CanvasKit.ImageFilter.MakeErode(rx, ry, inputFilter);
166160
return new JsiSkImageFilter(this.CanvasKit, filter);
@@ -175,9 +169,7 @@ export class JsiSkImageFilterFactory
175169
const inputFilter =
176170
input === null ? null : JsiSkImageFilter.fromValue<ImageFilter>(input);
177171
if (cropRect) {
178-
throw new NotImplementedOnRNWeb(
179-
"The cropRect argument is not yet supported on React Native Web."
180-
);
172+
throwNotImplementedOnRNWeb<SkImageFilter>();
181173
}
182174
const filter = this.CanvasKit.ImageFilter.MakeDilate(rx, ry, inputFilter);
183175
return new JsiSkImageFilter(this.CanvasKit, filter);
@@ -194,9 +186,7 @@ export class JsiSkImageFilterFactory
194186
? null
195187
: JsiSkImageFilter.fromValue<ImageFilter>(foreground);
196188
if (cropRect) {
197-
throw new NotImplementedOnRNWeb(
198-
"The cropRect argument is not yet supported on React Native Web."
199-
);
189+
throwNotImplementedOnRNWeb<SkImageFilter>();
200190
}
201191
const filter = this.CanvasKit.ImageFilter.MakeBlend(
202192
getEnum(this.CanvasKit.BlendMode, mode),
@@ -210,7 +200,7 @@ export class JsiSkImageFilterFactory
210200
_builder: SkRuntimeShaderBuilder,
211201
_childShaderName: string | null,
212202
_input: SkImageFilter | null
213-
): SkImageFilter {
214-
throw new NotImplementedOnRNWeb();
203+
) {
204+
return throwNotImplementedOnRNWeb<SkImageFilter>();
215205
}
216206
}

0 commit comments

Comments
 (0)