From c140588142e81e32d8800135f324ff1a073b8d73 Mon Sep 17 00:00:00 2001 From: Mark Lawlor Date: Mon, 31 Jul 2023 11:34:03 +1000 Subject: [PATCH] test: refactor tests --- .../src/__tests__/accessibility.tsx | 4 +- .../nativewind/src/__tests__/backgrounds.tsx | 1 - packages/nativewind/src/__tests__/borders.tsx | 62 +- .../src/__tests__/container-queries.tsx | 3 +- packages/nativewind/src/__tests__/custom.tsx | 3 +- .../nativewind/src/__tests__/dark-mode.tsx | 3 +- .../src/__tests__/interactivity.tsx | 69 +- packages/nativewind/src/__tests__/layout.tsx | 13 +- packages/nativewind/src/__tests__/sizing.tsx | 12 +- packages/nativewind/src/__tests__/tables.tsx | 101 +-- .../nativewind/src/__tests__/transforms.tsx | 678 +++++++----------- .../src/__tests__/transition-animations.tsx | 284 ++------ .../nativewind/src/__tests__/typography.tsx | 107 +-- packages/nativewind/src/test-utils.tsx | 37 +- .../src/__tests__/animations.test.tsx | 54 +- .../src/__tests__/container-queries.test.tsx | 26 +- .../src/__tests__/font.test.tsx | 15 +- .../src/__tests__/functions-test.ios.tsx | 21 +- .../src/__tests__/grouping.test.tsx | 40 +- .../src/__tests__/media-query.test.tsx | 52 +- .../src/__tests__/pseudo-classes.tsx | 88 ++- .../src/__tests__/selectors.test.tsx | 114 --- .../src/__tests__/smoke.test.tsx | 49 -- .../src/__tests__/transform.test.tsx | 24 +- .../src/__tests__/transitions.test.tsx | 37 +- .../src/__tests__/units.test.tsx | 54 +- .../src/__tests__/variables.test.tsx | 43 +- .../src/index.native.ts | 2 + .../react-native-css-interop/src/index.ts | 2 + .../src/runtime/native/animations.tsx | 14 +- .../src/runtime/native/interaction.ts | 1 + .../src/testing-library/index.tsx | 70 +- .../src/testing-library/setupAfterEnv.ts | 19 +- 33 files changed, 699 insertions(+), 1403 deletions(-) delete mode 100644 packages/react-native-css-interop/src/__tests__/selectors.test.tsx delete mode 100644 packages/react-native-css-interop/src/__tests__/smoke.test.tsx diff --git a/packages/nativewind/src/__tests__/accessibility.tsx b/packages/nativewind/src/__tests__/accessibility.tsx index cc8144e90..0d5e01375 100644 --- a/packages/nativewind/src/__tests__/accessibility.tsx +++ b/packages/nativewind/src/__tests__/accessibility.tsx @@ -1,5 +1,7 @@ import { resetStyles } from "react-native-css-interop/testing-library"; -import { invalidProperty, invalidValue, style, testCases } from "../test-utils"; +import { testCases } from "../test-utils"; + +afterEach(() => resetStyles()); describe.skip("Accessibility - Screen Readers", () => { // TODO diff --git a/packages/nativewind/src/__tests__/backgrounds.tsx b/packages/nativewind/src/__tests__/backgrounds.tsx index 730ff68ee..e613e3a05 100644 --- a/packages/nativewind/src/__tests__/backgrounds.tsx +++ b/packages/nativewind/src/__tests__/backgrounds.tsx @@ -28,7 +28,6 @@ describe("Backgrounds - Background Color", () => { "bg-white", { style: { backgroundColor: "rgba(255, 255, 255, 1)" }, - meta: { variables: { "--tw-bg-opacity": 1 } }, }, ], ); diff --git a/packages/nativewind/src/__tests__/borders.tsx b/packages/nativewind/src/__tests__/borders.tsx index 8f64ad19a..4174b2edd 100644 --- a/packages/nativewind/src/__tests__/borders.tsx +++ b/packages/nativewind/src/__tests__/borders.tsx @@ -81,61 +81,25 @@ describe("Border - Border Width", () => { describe("Border - Border Color", () => { testCases( - [ - "border-white", - { - ...style({ borderColor: "rgba(255, 255, 255, 1)" }), - meta: { variables: { "--tw-border-opacity": 1 } }, - }, - ], + ["border-white", style({ borderColor: "rgba(255, 255, 255, 1)" })], [ "border-x-white", - { - ...style({ - borderLeftColor: "rgba(255, 255, 255, 1)", - borderRightColor: "rgba(255, 255, 255, 1)", - }), - meta: { variables: { "--tw-border-opacity": 1 } }, - }, + style({ + borderLeftColor: "rgba(255, 255, 255, 1)", + borderRightColor: "rgba(255, 255, 255, 1)", + }), ], [ "border-y-white", - { - ...style({ - borderTopColor: "rgba(255, 255, 255, 1)", - borderBottomColor: "rgba(255, 255, 255, 1)", - }), - meta: { variables: { "--tw-border-opacity": 1 } }, - }, - ], - [ - "border-t-white", - { - ...style({ borderTopColor: "rgba(255, 255, 255, 1)" }), - meta: { variables: { "--tw-border-opacity": 1 } }, - }, - ], - [ - "border-b-white", - { - ...style({ borderBottomColor: "rgba(255, 255, 255, 1)" }), - meta: { variables: { "--tw-border-opacity": 1 } }, - }, - ], - [ - "border-l-white", - { - ...style({ borderLeftColor: "rgba(255, 255, 255, 1)" }), - meta: { variables: { "--tw-border-opacity": 1 } }, - }, - ], - [ - "border-r-white", - { - ...style({ borderRightColor: "rgba(255, 255, 255, 1)" }), - meta: { variables: { "--tw-border-opacity": 1 } }, - }, + style({ + borderTopColor: "rgba(255, 255, 255, 1)", + borderBottomColor: "rgba(255, 255, 255, 1)", + }), ], + ["border-t-white", style({ borderTopColor: "rgba(255, 255, 255, 1)" })], + ["border-b-white", style({ borderBottomColor: "rgba(255, 255, 255, 1)" })], + ["border-l-white", style({ borderLeftColor: "rgba(255, 255, 255, 1)" })], + ["border-r-white", style({ borderRightColor: "rgba(255, 255, 255, 1)" })], [ "border-current", { diff --git a/packages/nativewind/src/__tests__/container-queries.tsx b/packages/nativewind/src/__tests__/container-queries.tsx index 0e8fbf4f2..998bda458 100644 --- a/packages/nativewind/src/__tests__/container-queries.tsx +++ b/packages/nativewind/src/__tests__/container-queries.tsx @@ -1,5 +1,4 @@ -import { resetStyles } from "react-native-css-interop/testing-library"; -import { invalidProperty, invalidValue, style, testCases } from "../test-utils"; +import { testCases } from "../test-utils"; describe.skip("Container Queries", () => { // TODO diff --git a/packages/nativewind/src/__tests__/custom.tsx b/packages/nativewind/src/__tests__/custom.tsx index 9cc4b776a..fced76eed 100644 --- a/packages/nativewind/src/__tests__/custom.tsx +++ b/packages/nativewind/src/__tests__/custom.tsx @@ -1,5 +1,4 @@ -import { resetStyles } from "react-native-css-interop/testing-library"; -import { invalidProperty, invalidValue, style, testCases } from "../test-utils"; +import { testCases } from "../test-utils"; describe.skip("Custom - Elevation", () => { // TODO diff --git a/packages/nativewind/src/__tests__/dark-mode.tsx b/packages/nativewind/src/__tests__/dark-mode.tsx index 432aa5816..970faa7fb 100644 --- a/packages/nativewind/src/__tests__/dark-mode.tsx +++ b/packages/nativewind/src/__tests__/dark-mode.tsx @@ -1,5 +1,4 @@ -import { resetStyles } from "react-native-css-interop/testing-library"; -import { invalidProperty, invalidValue, style, testCases } from "../test-utils"; +import { testCases } from "../test-utils"; describe.skip("Dark Mode", () => { // TODO diff --git a/packages/nativewind/src/__tests__/interactivity.tsx b/packages/nativewind/src/__tests__/interactivity.tsx index 63f458363..3d3b1c2d2 100644 --- a/packages/nativewind/src/__tests__/interactivity.tsx +++ b/packages/nativewind/src/__tests__/interactivity.tsx @@ -1,5 +1,5 @@ import { resetStyles } from "react-native-css-interop/testing-library"; -import { invalidProperty, invalidValue, style, testCases } from "../test-utils"; +import { invalidProperty, testCases } from "../test-utils"; afterEach(() => resetStyles()); @@ -146,69 +146,22 @@ describe("Interactivity - Scroll Snap Type", () => { ["snap-x", invalidProperty("scroll-snap-type")], ["snap-y", invalidProperty("scroll-snap-type")], ["snap-both", invalidProperty("scroll-snap-type")], - [ - "snap-mandatory", - { meta: { variables: { "--tw-scroll-snap-strictness": "mandatory" } } }, - ], - [ - "snap-proximity", - { meta: { variables: { "--tw-scroll-snap-strictness": "proximity" } } }, - ], + // These properties just generate variables + ["snap-mandatory", {}], + ["snap-proximity", {}], ); }); describe("Interactivity - Touch Action", () => { testCases(["touch-auto", invalidProperty("touch-action")]); testCases(["touch-none", invalidProperty("touch-action")]); - testCases([ - "touch-pan-x", - { - ...invalidProperty("touch-action"), - meta: { variables: { "--tw-pan-x": "pan-x" } }, - }, - ]); - testCases([ - "touch-pan-left", - { - ...invalidProperty("touch-action"), - meta: { variables: { "--tw-pan-x": "pan-left" } }, - }, - ]); - testCases([ - "touch-pan-right", - { - ...invalidProperty("touch-action"), - meta: { variables: { "--tw-pan-x": "pan-right" } }, - }, - ]); - testCases([ - "touch-pan-y", - { - ...invalidProperty("touch-action"), - meta: { variables: { "--tw-pan-y": "pan-y" } }, - }, - ]); - testCases([ - "touch-pan-up", - { - ...invalidProperty("touch-action"), - meta: { variables: { "--tw-pan-y": "pan-up" } }, - }, - ]); - testCases([ - "touch-pan-down", - { - ...invalidProperty("touch-action"), - meta: { variables: { "--tw-pan-y": "pan-down" } }, - }, - ]); - testCases([ - "touch-pinch-zoom", - { - ...invalidProperty("touch-action"), - meta: { variables: { "--tw-pinch-zoom": "pinch-zoom" } }, - }, - ]); + testCases(["touch-pan-x", invalidProperty("touch-action")]); + testCases(["touch-pan-left", invalidProperty("touch-action")]); + testCases(["touch-pan-right", invalidProperty("touch-action")]); + testCases(["touch-pan-y", invalidProperty("touch-action")]); + testCases(["touch-pan-up", invalidProperty("touch-action")]); + testCases(["touch-pan-down", invalidProperty("touch-action")]); + testCases(["touch-pinch-zoom", invalidProperty("touch-action")]); testCases(["touch-manipulation", invalidProperty("touch-action")]); }); diff --git a/packages/nativewind/src/__tests__/layout.tsx b/packages/nativewind/src/__tests__/layout.tsx index f6915bc99..4056bef5e 100644 --- a/packages/nativewind/src/__tests__/layout.tsx +++ b/packages/nativewind/src/__tests__/layout.tsx @@ -3,7 +3,7 @@ import { invalidProperty, invalidValue, style, testCases } from "../test-utils"; afterEach(() => resetStyles()); -describe("Layout - Aspect Ratio", () => { +describe.only("Layout - Aspect Ratio", () => { testCases( ["aspect-square", style({ aspectRatio: 1 })], // ["aspect-video", style({ aspectRatio: "16 / 9" })], @@ -14,13 +14,10 @@ describe("Layout - Aspect Ratio", () => { describe("Layout - Container", () => { testCases([ "container", - { - style: { - maxWidth: 640, - width: "100%", - }, - meta: {}, - }, + style({ + maxWidth: 640, + width: "100%", + }), ]); }); diff --git a/packages/nativewind/src/__tests__/sizing.tsx b/packages/nativewind/src/__tests__/sizing.tsx index 2c0c86351..3348e108a 100644 --- a/packages/nativewind/src/__tests__/sizing.tsx +++ b/packages/nativewind/src/__tests__/sizing.tsx @@ -1,6 +1,6 @@ import { Dimensions } from "react-native"; import { resetStyles } from "react-native-css-interop/testing-library"; -import { invalidProperty, invalidValue, style, testCases } from "../test-utils"; +import { invalidValue, style, testCases } from "../test-utils"; afterEach(() => resetStyles()); @@ -15,10 +15,7 @@ describe("Sizing - Width", () => { ["w-min", invalidValue("width", "min-content")], ["w-max", invalidValue("width", "max-content")], ["w-fit", invalidValue("width", "fit-content")], - [ - "w-screen", - { ...style({ width: Dimensions.get("window").width }), meta: {} }, - ], + ["w-screen", style({ width: Dimensions.get("window").width })], ); }); @@ -53,10 +50,7 @@ describe("Sizing - Height", () => { ["h-min", invalidValue("height", "min-content")], ["h-max", invalidValue("height", "max-content")], ["h-fit", invalidValue("height", "fit-content")], - [ - "h-screen", - { ...style({ height: Dimensions.get("window").height }), meta: {} }, - ], + ["h-screen", style({ height: Dimensions.get("window").height })], ); }); diff --git a/packages/nativewind/src/__tests__/tables.tsx b/packages/nativewind/src/__tests__/tables.tsx index 71914eec0..6c9ee6ebf 100644 --- a/packages/nativewind/src/__tests__/tables.tsx +++ b/packages/nativewind/src/__tests__/tables.tsx @@ -1,5 +1,5 @@ import { resetStyles } from "react-native-css-interop/testing-library"; -import { invalidProperty, invalidValue, style, testCases } from "../test-utils"; +import { invalidProperty, testCases } from "../test-utils"; afterEach(() => resetStyles()); @@ -12,96 +12,15 @@ describe("Tables - Border Collapse", () => { describe("Tables - Border Spacing", () => { testCases( - [ - "border-spacing-0", - { - ...invalidProperty("border-spacing"), - meta: { - variables: { - "--tw-border-spacing-x": 0, - "--tw-border-spacing-y": 0, - }, - }, - }, - ], - [ - "border-spacing-x-0", - { - ...invalidProperty("border-spacing"), - meta: { - variables: { "--tw-border-spacing-x": 0 }, - }, - }, - ], - [ - "border-spacing-y-0", - { - ...invalidProperty("border-spacing"), - meta: { - variables: { "--tw-border-spacing-y": 0 }, - }, - }, - ], - [ - "border-spacing-px", - { - ...invalidProperty("border-spacing"), - meta: { - variables: { - "--tw-border-spacing-x": 1, - "--tw-border-spacing-y": 1, - }, - }, - }, - ], - [ - "border-spacing-x-px", - { - ...invalidProperty("border-spacing"), - meta: { - variables: { "--tw-border-spacing-x": 1 }, - }, - }, - ], - [ - "border-spacing-y-px", - { - ...invalidProperty("border-spacing"), - meta: { - variables: { "--tw-border-spacing-y": 1 }, - }, - }, - ], - [ - "border-spacing-1", - { - ...invalidProperty("border-spacing"), - meta: { - variables: { - "--tw-border-spacing-x": 3.5, - "--tw-border-spacing-y": 3.5, - }, - }, - }, - ], - [ - "border-spacing-x-1", - { - ...invalidProperty("border-spacing"), - meta: { - variables: { "--tw-border-spacing-x": 3.5 }, - }, - }, - ], - [ - "border-spacing-y-1", - { - ...invalidProperty("border-spacing"), - meta: { - variables: { "--tw-border-spacing-y": 3.5 }, - }, - }, - ], + ["border-spacing-0", invalidProperty("border-spacing")], + ["border-spacing-x-0", invalidProperty("border-spacing")], + ["border-spacing-y-0", invalidProperty("border-spacing")], + ["border-spacing-px", invalidProperty("border-spacing")], + ["border-spacing-x-px", invalidProperty("border-spacing")], + ["border-spacing-y-px", invalidProperty("border-spacing")], + ["border-spacing-1", invalidProperty("border-spacing")], + ["border-spacing-x-1", invalidProperty("border-spacing")], + ["border-spacing-y-1", invalidProperty("border-spacing")], ); }); diff --git a/packages/nativewind/src/__tests__/transforms.tsx b/packages/nativewind/src/__tests__/transforms.tsx index 8732e28e6..865ec5b6b 100644 --- a/packages/nativewind/src/__tests__/transforms.tsx +++ b/packages/nativewind/src/__tests__/transforms.tsx @@ -1,6 +1,7 @@ import { resetStyles } from "react-native-css-interop/testing-library"; import { invalidProperty, + style, testCases, testCasesWithOptions, } from "../test-utils"; @@ -14,131 +15,89 @@ describe("Transforms - Scale", () => { }, [ "scale-0", - { - style: { - transform: [ - { translateX: 0 }, - { translateY: 0 }, - { rotate: "0" }, - { skewX: "0" }, - { skewY: "0" }, - { scaleX: 0 }, - { scaleY: 0 }, - ], - }, - meta: { - variables: { - "--tw-scale-x": 0, - "--tw-scale-y": 0, - }, - }, - }, + style({ + transform: [ + { translateX: 0 }, + { translateY: 0 }, + { rotate: "0" }, + { skewX: "0" }, + { skewY: "0" }, + { scaleX: 0 }, + { scaleY: 0 }, + ], + }), ], [ "scale-x-0", - { - style: { - transform: [ - { translateX: 0 }, - { translateY: 0 }, - { rotate: "0" }, - { skewX: "0" }, - { skewY: "0" }, - { scaleX: 0 }, - { scaleY: 1 }, - ], - }, - meta: { - variables: { - "--tw-scale-x": 0, - }, - }, - }, + style({ + transform: [ + { translateX: 0 }, + { translateY: 0 }, + { rotate: "0" }, + { skewX: "0" }, + { skewY: "0" }, + { scaleX: 0 }, + { scaleY: 1 }, + ], + }), ], [ "scale-y-0", - { - style: { - transform: [ - { translateX: 0 }, - { translateY: 0 }, - { rotate: "0" }, - { skewX: "0" }, - { skewY: "0" }, - { scaleX: 1 }, - { scaleY: 0 }, - ], - }, - meta: { - variables: { - "--tw-scale-y": 0, - }, - }, - }, + style({ + transform: [ + { translateX: 0 }, + { translateY: 0 }, + { rotate: "0" }, + { skewX: "0" }, + { skewY: "0" }, + { scaleX: 1 }, + { scaleY: 0 }, + ], + }), ], [ "scale-50", - { - style: { - transform: [ - { translateX: 0 }, - { translateY: 0 }, - { rotate: "0" }, - { skewX: "0" }, - { skewY: "0" }, - { scaleX: 0.5 }, - { scaleY: 0.5 }, - ], - }, - meta: { - variables: { - "--tw-scale-x": 0.5, - "--tw-scale-y": 0.5, - }, - }, - }, + + style({ + transform: [ + { translateX: 0 }, + { translateY: 0 }, + { rotate: "0" }, + { skewX: "0" }, + { skewY: "0" }, + { scaleX: 0.5 }, + { scaleY: 0.5 }, + ], + }), ], [ "scale-x-50", - { - style: { - transform: [ - { translateX: 0 }, - { translateY: 0 }, - { rotate: "0" }, - { skewX: "0" }, - { skewY: "0" }, - { scaleX: 0.5 }, - { scaleY: 1 }, - ], - }, - meta: { - variables: { - "--tw-scale-x": 0.5, - }, - }, - }, + style({ + transform: [ + { translateX: 0 }, + { translateY: 0 }, + { rotate: "0" }, + { skewX: "0" }, + { skewY: "0" }, + { scaleX: 0.5 }, + { scaleY: 1 }, + ], + }), ], [ "scale-y-50", - { - style: { - transform: [ - { translateX: 0 }, - { translateY: 0 }, - { rotate: "0" }, - { skewX: "0" }, - { skewY: "0" }, - { scaleX: 1 }, - { scaleY: 0.5 }, - ], - }, - meta: { - variables: { - "--tw-scale-y": 0.5, - }, - }, - }, + + style({ + transform: [ + { translateX: 0 }, + { translateY: 0 }, + { rotate: "0" }, + { skewX: "0" }, + { skewY: "0" }, + { scaleX: 1 }, + { scaleY: 0.5 }, + ], + }), ], ); }); @@ -150,45 +109,32 @@ describe("Transforms - Rotate", () => { }, [ "rotate-0", - { - style: { - transform: [ - { translateX: 0 }, - { translateY: 0 }, - { rotate: "0deg" }, - { skewX: "0" }, - { skewY: "0" }, - { scaleX: 1 }, - { scaleY: 1 }, - ], - }, - meta: { - variables: { - "--tw-rotate": "0deg", - }, - }, - }, + style({ + transform: [ + { translateX: 0 }, + { translateY: 0 }, + { rotate: "0deg" }, + { skewX: "0" }, + { skewY: "0" }, + { scaleX: 1 }, + { scaleY: 1 }, + ], + }), ], [ "rotate-180", - { - style: { - transform: [ - { translateX: 0 }, - { translateY: 0 }, - { rotate: "180deg" }, - { skewX: "0" }, - { skewY: "0" }, - { scaleX: 1 }, - { scaleY: 1 }, - ], - }, - meta: { - variables: { - "--tw-rotate": "180deg", - }, - }, - }, + + style({ + transform: [ + { translateX: 0 }, + { translateY: 0 }, + { rotate: "180deg" }, + { skewX: "0" }, + { skewY: "0" }, + { scaleX: 1 }, + { scaleY: 1 }, + ], + }), ], ); }); @@ -200,129 +146,89 @@ describe("Transforms - Translate", () => { }, [ "translate-x-0", - { - style: { - transform: [ - { translateX: 0 }, - { translateY: 0 }, - { rotate: "0" }, - { skewX: "0" }, - { skewY: "0" }, - { scaleX: 1 }, - { scaleY: 1 }, - ], - }, - meta: { - variables: { - "--tw-translate-x": 0, - }, - }, - }, + style({ + transform: [ + { translateX: 0 }, + { translateY: 0 }, + { rotate: "0" }, + { skewX: "0" }, + { skewY: "0" }, + { scaleX: 1 }, + { scaleY: 1 }, + ], + }), ], [ "translate-y-0", - { - style: { - transform: [ - { translateX: 0 }, - { translateY: 0 }, - { rotate: "0" }, - { skewX: "0" }, - { skewY: "0" }, - { scaleX: 1 }, - { scaleY: 1 }, - ], - }, - meta: { - variables: { - "--tw-translate-y": 0, - }, - }, - }, + + style({ + transform: [ + { translateX: 0 }, + { translateY: 0 }, + { rotate: "0" }, + { skewX: "0" }, + { skewY: "0" }, + { scaleX: 1 }, + { scaleY: 1 }, + ], + }), ], [ "translate-x-px", - { - style: { - transform: [ - { translateX: 1 }, - { translateY: 0 }, - { rotate: "0" }, - { skewX: "0" }, - { skewY: "0" }, - { scaleX: 1 }, - { scaleY: 1 }, - ], - }, - meta: { - variables: { - "--tw-translate-x": 1, - }, - }, - }, + + style({ + transform: [ + { translateX: 1 }, + { translateY: 0 }, + { rotate: "0" }, + { skewX: "0" }, + { skewY: "0" }, + { scaleX: 1 }, + { scaleY: 1 }, + ], + }), ], [ "translate-y-px", - { - style: { - transform: [ - { translateX: 0 }, - { translateY: 1 }, - { rotate: "0" }, - { skewX: "0" }, - { skewY: "0" }, - { scaleX: 1 }, - { scaleY: 1 }, - ], - }, - meta: { - variables: { - "--tw-translate-y": 1, - }, - }, - }, + style({ + transform: [ + { translateX: 0 }, + { translateY: 1 }, + { rotate: "0" }, + { skewX: "0" }, + { skewY: "0" }, + { scaleX: 1 }, + { scaleY: 1 }, + ], + }), ], [ "translate-x-1", - { - style: { - transform: [ - { translateX: 3.5 }, - { translateY: 0 }, - { rotate: "0" }, - { skewX: "0" }, - { skewY: "0" }, - { scaleX: 1 }, - { scaleY: 1 }, - ], - }, - meta: { - variables: { - "--tw-translate-x": 3.5, - }, - }, - }, + style({ + transform: [ + { translateX: 3.5 }, + { translateY: 0 }, + { rotate: "0" }, + { skewX: "0" }, + { skewY: "0" }, + { scaleX: 1 }, + { scaleY: 1 }, + ], + }), ], [ "translate-y-1", - { - style: { - transform: [ - { translateX: 0 }, - { translateY: 3.5 }, - { rotate: "0" }, - { skewX: "0" }, - { skewY: "0" }, - { scaleX: 1 }, - { scaleY: 1 }, - ], - }, - meta: { - variables: { - "--tw-translate-y": 3.5, - }, - }, - }, + style({ + transform: [ + { translateX: 0 }, + { translateY: 3.5 }, + { rotate: "0" }, + { skewX: "0" }, + { skewY: "0" }, + { scaleX: 1 }, + { scaleY: 1 }, + ], + }), ], ); }); @@ -335,87 +241,62 @@ describe.skip("Transforms - Translate (%)", () => { }, [ "translate-x-1/2", - { - style: { - transform: [ - { translateX: 0 }, - { translateY: 0 }, - { rotate: "0" }, - { skewX: "0" }, - { skewY: "0" }, - { scaleX: 1 }, - { scaleY: 1 }, - ], - }, - meta: { - variables: { - "--tw-translate-x": 3.5, - }, - }, - }, + style({ + transform: [ + { translateX: 0 }, + { translateY: 0 }, + { rotate: "0" }, + { skewX: "0" }, + { skewY: "0" }, + { scaleX: 1 }, + { scaleY: 1 }, + ], + }), ], [ "translate-y-1/2", - { - style: { - transform: [ - { translateX: 0 }, - { translateY: 3.5 }, - { rotate: "0" }, - { skewX: "0" }, - { skewY: "0" }, - { scaleX: 1 }, - { scaleY: 1 }, - ], - }, - meta: { - variables: { - "--tw-translate-y": 3.5, - }, - }, - }, + + style({ + transform: [ + { translateX: 0 }, + { translateY: 3.5 }, + { rotate: "0" }, + { skewX: "0" }, + { skewY: "0" }, + { scaleX: 1 }, + { scaleY: 1 }, + ], + }), ], [ "translate-x-full", - { - style: { - transform: [ - { translateX: 3.5 }, - { translateY: 0 }, - { rotate: "0" }, - { skewX: "0" }, - { skewY: "0" }, - { scaleX: 1 }, - { scaleY: 1 }, - ], - }, - meta: { - variables: { - "--tw-translate-x": 3.5, - }, - }, - }, + + style({ + transform: [ + { translateX: 3.5 }, + { translateY: 0 }, + { rotate: "0" }, + { skewX: "0" }, + { skewY: "0" }, + { scaleX: 1 }, + { scaleY: 1 }, + ], + }), ], [ "translate-y-full", - { - style: { - transform: [ - { translateX: 0 }, - { translateY: 3.5 }, - { rotate: "0" }, - { skewX: "0" }, - { skewY: "0" }, - { scaleX: 1 }, - { scaleY: 1 }, - ], - }, - meta: { - variables: { - "--tw-translate-y": 3.5, - }, - }, - }, + + style({ + transform: [ + { translateX: 0 }, + { translateY: 3.5 }, + { rotate: "0" }, + { skewX: "0" }, + { skewY: "0" }, + { scaleX: 1 }, + { scaleY: 1 }, + ], + }), ], ); }); @@ -427,87 +308,63 @@ describe("Transforms - Skew", () => { }, [ "skew-x-0", - { - style: { - transform: [ - { translateX: 0 }, - { translateY: 0 }, - { rotate: "0" }, - { skewX: "0deg" }, - { skewY: "0" }, - { scaleX: 1 }, - { scaleY: 1 }, - ], - }, - meta: { - variables: { - "--tw-skew-x": "0deg", - }, - }, - }, + + style({ + transform: [ + { translateX: 0 }, + { translateY: 0 }, + { rotate: "0" }, + { skewX: "0deg" }, + { skewY: "0" }, + { scaleX: 1 }, + { scaleY: 1 }, + ], + }), ], [ "skew-y-0", - { - style: { - transform: [ - { translateX: 0 }, - { translateY: 0 }, - { rotate: "0" }, - { skewX: "0" }, - { skewY: "0deg" }, - { scaleX: 1 }, - { scaleY: 1 }, - ], - }, - meta: { - variables: { - "--tw-skew-y": "0deg", - }, - }, - }, + + style({ + transform: [ + { translateX: 0 }, + { translateY: 0 }, + { rotate: "0" }, + { skewX: "0" }, + { skewY: "0deg" }, + { scaleX: 1 }, + { scaleY: 1 }, + ], + }), ], [ "skew-x-1", - { - style: { - transform: [ - { translateX: 0 }, - { translateY: 0 }, - { rotate: "0" }, - { skewX: "1deg" }, - { skewY: "0" }, - { scaleX: 1 }, - { scaleY: 1 }, - ], - }, - meta: { - variables: { - "--tw-skew-x": "1deg", - }, - }, - }, + + style({ + transform: [ + { translateX: 0 }, + { translateY: 0 }, + { rotate: "0" }, + { skewX: "1deg" }, + { skewY: "0" }, + { scaleX: 1 }, + { scaleY: 1 }, + ], + }), ], [ "skew-y-1", - { - style: { - transform: [ - { translateX: 0 }, - { translateY: 0 }, - { rotate: "0" }, - { skewX: "0" }, - { skewY: "1deg" }, - { scaleX: 1 }, - { scaleY: 1 }, - ], - }, - meta: { - variables: { - "--tw-skew-y": "1deg", - }, - }, - }, + + style({ + transform: [ + { translateX: 0 }, + { translateY: 0 }, + { rotate: "0" }, + { skewX: "0" }, + { skewY: "1deg" }, + { scaleX: 1 }, + { scaleY: 1 }, + ], + }), ], ); }); @@ -519,19 +376,18 @@ describe("Transforms - Mixed", () => { }, [ "rotate-90 skew-y-1 translate-x-1", - { - style: { - transform: [ - { translateX: 3.5 }, - { translateY: 0 }, - { rotate: "90deg" }, - { skewX: "0" }, - { skewY: "1deg" }, - { scaleX: 1 }, - { scaleY: 1 }, - ], - }, - }, + + style({ + transform: [ + { translateX: 3.5 }, + { translateY: 0 }, + { rotate: "90deg" }, + { skewX: "0" }, + { skewY: "1deg" }, + { scaleX: 1 }, + { scaleY: 1 }, + ], + }), ], ); }); diff --git a/packages/nativewind/src/__tests__/transition-animations.tsx b/packages/nativewind/src/__tests__/transition-animations.tsx index 67774df3b..a9138ca95 100644 --- a/packages/nativewind/src/__tests__/transition-animations.tsx +++ b/packages/nativewind/src/__tests__/transition-animations.tsx @@ -1,10 +1,13 @@ import { resetStyles } from "react-native-css-interop/testing-library"; -import { testCases } from "../test-utils"; +import { style, testCasesWithOptions } from "../test-utils"; afterEach(() => resetStyles()); describe("Transitions & Animation - Transition Property", () => { - testCases( + testCasesWithOptions( + { + animated: true, + }, // TODO: Add tests for all transition properties // "transition-none", // "transition-all", @@ -15,236 +18,70 @@ describe("Transitions & Animation - Transition Property", () => { // "transition-transform", [ "transition-colors", - { - style: { - backgroundColor: "transparent", - borderColor: "transparent", - color: "transparent", - }, - meta: { - transition: { - duration: [{ value: 150, type: "milliseconds" }], - timingFunction: [ - { - type: "cubic-bezier", - x1: 0.4000000059604645, - x2: 0.20000000298023224, - y1: 0, - y2: 1, - }, - ], - property: [ - "color", - "backgroundColor", - "borderColor", - "textDecorationColor", - "fill", - "stroke", - ], - }, - }, - }, + style({ + backgroundColor: "transparent", + borderColor: "transparent", + color: "transparent", + }), ], [ "transition-opacity", - { - style: { - opacity: 1, - }, - meta: { - transition: { - duration: [{ value: 150, type: "milliseconds" }], - timingFunction: [ - { - type: "cubic-bezier", - x1: 0.4000000059604645, - x2: 0.20000000298023224, - y1: 0, - y2: 1, - }, - ], - property: ["opacity"], - }, - }, - }, + style({ + opacity: 1, + }), ], ); }); -describe("Transitions & Animation - Transition Duration", () => { - testCases([ - "duration-75", +describe.only("Transitions & Animation - Transition Duration", () => { + testCasesWithOptions( { - meta: { - transition: { duration: [{ value: 75, type: "milliseconds" }] }, - }, + animated: true, }, - ]); + ["duration-75", {}], + ); }); describe("Transitions & Animation - Transition Timing Function", () => { - testCases( - [ - "ease-linear", - { meta: { transition: { timingFunction: [{ type: "linear" }] } } }, - ], - [ - "ease-in", - { - meta: { - transition: { - timingFunction: [ - { - type: "cubic-bezier", - x1: 0.4000000059604645, - x2: 1, - y1: 0, - y2: 1, - }, - ], - }, - }, - }, - ], - [ - "ease-out", - { - meta: { - transition: { - timingFunction: [ - { - type: "cubic-bezier", - x1: 0, - x2: 0.20000000298023224, - y1: 0, - y2: 1, - }, - ], - }, - }, - }, - ], - [ - "ease-in-out", - { - meta: { - transition: { - timingFunction: [ - { - type: "cubic-bezier", - x1: 0.4000000059604645, - x2: 0.20000000298023224, - y1: 0, - y2: 1, - }, - ], - }, - }, - }, - ], + testCasesWithOptions( + { + animated: true, + }, + ["ease-linear", {}], + ["ease-in", {}], + ["ease-out", {}], + ["ease-in-out", {}], ); }); describe("Transitions & Animation - Transition Delay", () => { - testCases([ - "delay-0", + testCasesWithOptions( { - meta: { - transition: { delay: [{ value: 0, type: "seconds" }] }, - }, + animated: true, }, - ]); + ["delay-0", {}], + ); }); describe("Transitions & Animation - Animation", () => { - testCases( - // TODO: - // "animate-ping", - // "animate-pulse", - // "animate-bounce", - + testCasesWithOptions( + { + animated: true, + }, [ + // TODO: + // "animate-ping", + // "animate-pulse", + // "animate-bounce", + "animate-none", - { - meta: { - animations: { - delay: [ - { - type: "seconds", - value: 0, - }, - ], - direction: ["normal"], - duration: [ - { - type: "seconds", - value: 0, - }, - ], - fillMode: ["none"], - iterationCount: [ - { - type: "number", - value: 1, - }, - ], - name: [ - { - type: "none", - }, - ], - playState: ["running"], - timingFunction: [ - { - type: "ease", - }, - ], - }, - }, - }, + {}, ], [ "animate-spin", - { - style: { - transform: [{ rotate: "0deg" }], - }, - meta: { - animations: { - delay: [ - { - type: "seconds", - value: 0, - }, - ], - direction: ["normal"], - duration: [ - { - type: "seconds", - value: 1, - }, - ], - fillMode: ["none"], - iterationCount: [ - { - type: "infinite", - }, - ], - name: [ - { - type: "ident", - value: "spin", - }, - ], - playState: ["running"], - timingFunction: [ - { - type: "linear", - }, - ], - }, - }, - }, + style({ + transform: [{ rotate: "0deg" }], + }), ], // [ // "animate-ping", @@ -253,41 +90,6 @@ describe("Transitions & Animation - Animation", () => { // opacity: NaN, // transform: [{ scaleX: 1 }, { scaleY: 1 }], // }, - // meta: { - // animations: { - // delay: [ - // { - // type: "seconds", - // value: 0, - // }, - // ], - // direction: ["normal"], - // duration: [ - // { - // type: "seconds", - // value: 1, - // }, - // ], - // fillMode: ["none"], - // iterationCount: [ - // { - // type: "infinite", - // }, - // ], - // name: [ - // { - // type: "ident", - // value: "ping", - // }, - // ], - // playState: ["running"], - // timingFunction: [ - // { - // type: "linear", - // }, - // ], - // }, - // }, // }, // ], ); diff --git a/packages/nativewind/src/__tests__/typography.tsx b/packages/nativewind/src/__tests__/typography.tsx index d016ba9ae..dd8aaa9e3 100644 --- a/packages/nativewind/src/__tests__/typography.tsx +++ b/packages/nativewind/src/__tests__/typography.tsx @@ -79,62 +79,14 @@ describe("Typography - Font Weight", () => { describe("Typography - Font Variant Numeric", () => { testCases( ["normal-nums", invalidProperty("font-variant-numeric")], - [ - "ordinal", - { - ...invalidProperty("font-variant-numeric"), - meta: { variables: { "--tw-ordinal": "ordinal" } }, - }, - ], - [ - "slashed-zero", - { - ...invalidProperty("font-variant-numeric"), - meta: { variables: { "--tw-slashed-zero": "slashed-zero" } }, - }, - ], - [ - "lining-nums", - { - ...invalidProperty("font-variant-numeric"), - meta: { variables: { "--tw-numeric-figure": "lining-nums" } }, - }, - ], - [ - "oldstyle-nums", - { - ...invalidProperty("font-variant-numeric"), - meta: { variables: { "--tw-numeric-figure": "oldstyle-nums" } }, - }, - ], - [ - "proportional-nums", - { - ...invalidProperty("font-variant-numeric"), - meta: { variables: { "--tw-numeric-spacing": "proportional-nums" } }, - }, - ], - [ - "tabular-nums", - { - ...invalidProperty("font-variant-numeric"), - meta: { variables: { "--tw-numeric-spacing": "tabular-nums" } }, - }, - ], - [ - "diagonal-fractions", - { - ...invalidProperty("font-variant-numeric"), - meta: { variables: { "--tw-numeric-fraction": "diagonal-fractions" } }, - }, - ], - [ - "stacked-fractions", - { - ...invalidProperty("font-variant-numeric"), - meta: { variables: { "--tw-numeric-fraction": "stacked-fractions" } }, - }, - ], + ["ordinal", invalidProperty("font-variant-numeric")], + ["slashed-zero", invalidProperty("font-variant-numeric")], + ["lining-nums", invalidProperty("font-variant-numeric")], + ["oldstyle-nums", invalidProperty("font-variant-numeric")], + ["proportional-nums", invalidProperty("font-variant-numeric")], + ["tabular-nums", invalidProperty("font-variant-numeric")], + ["diagonal-fractions", invalidProperty("font-variant-numeric")], + ["stacked-fractions", invalidProperty("font-variant-numeric")], ); }); @@ -199,38 +151,13 @@ describe("Typography - Text Align", () => { describe("Typography - Text Color", () => { testCases( - [ - "text-black", - { - style: { color: "rgba(0, 0, 0, 1)" }, - meta: { variables: { "--tw-text-opacity": 1 } }, - }, - ], - [ - "text-white", - { - style: { color: "rgba(255, 255, 255, 1)" }, - meta: { variables: { "--tw-text-opacity": 1 } }, - }, - ], - [ - "text-transparent", - { - style: { color: "rgba(0, 0, 0, 0)" }, - }, - ], - [ - "text-slate-50", - { - style: { color: "rgba(248, 250, 252, 1)" }, - meta: { variables: { "--tw-text-opacity": 1 } }, - }, - ], + ["text-black", style({ color: "rgba(0, 0, 0, 1)" })], + ["text-white", style({ color: "rgba(255, 255, 255, 1)" })], + ["text-transparent", style({ color: "rgba(0, 0, 0, 0)" })], + ["text-slate-50", style({ color: "rgba(248, 250, 252, 1)" })], [ "text-white/50", - { - style: { color: "rgba(255, 255, 255, 0.501960813999176)" }, - }, + style({ color: "rgba(255, 255, 255, 0.501960813999176)" }), ], ["text-current", invalidValue("color", "currentcolor")], ["text-inherit", invalidValue("color", "inherit")], @@ -376,11 +303,5 @@ describe("Typography - Hyphens", () => { }); describe("Typography - Content", () => { - testCases([ - "content-none", - { - ...invalidProperty("content"), - meta: { variables: { "--tw-content": "none" } }, - }, - ]); + testCases(["content-none", invalidProperty("content")]); }); diff --git a/packages/nativewind/src/test-utils.tsx b/packages/nativewind/src/test-utils.tsx index c6e537d67..88de7d094 100644 --- a/packages/nativewind/src/test-utils.tsx +++ b/packages/nativewind/src/test-utils.tsx @@ -1,5 +1,5 @@ -import { ViewStyle, ImageStyle, TextStyle } from "react-native"; -import { RenderOptions, render } from "@testing-library/react-native"; +import { ViewStyle, ImageStyle, TextStyle, View } from "react-native"; +import { RenderOptions, render, screen } from "@testing-library/react-native"; import postcss from "postcss"; import { createMockComponent, @@ -7,13 +7,13 @@ import { } from "react-native-css-interop/testing-library"; import tailwind from "tailwindcss"; import { cssToReactNativeRuntimeOptions } from "./metro/with-tailwind-options"; -import { - ExtractionWarning, - StyleMeta, -} from "react-native-css-interop/dist/types"; +import { ExtractionWarning } from "react-native-css-interop/dist/types"; +import { warnings } from "react-native-css-interop"; export interface RenderTailwindOptions extends RenderOptions { css?: string; + testID?: string; + animated?: boolean; } export async function renderTailwind( @@ -41,7 +41,6 @@ type TestCase = [ { style?: ReturnType["style"]; warning?: (name: string) => Map; - meta?: StyleMeta; }, ]; @@ -70,26 +69,30 @@ export function testCases(...cases: TestCase[]) { } export function testCasesWithOptions( - options: RenderTailwindOptions, + { + testID = "react-native-css-interop", + animated = false, + ...options + }: RenderTailwindOptions, ...cases: TestCase[] ) { - const A = createMockComponent(); + const A = createMockComponent(View); test.each(cases)("%s", async (className, expected) => { - await renderTailwind(, options); + await renderTailwind(, options); - if (expected.style) { - expect(A).styleToEqual(expected.style); + const component = screen.getByTestId(testID); + + if (animated) { + expect(component).toHaveAnimatedStyle(expected.style ?? {}); } else { - expect(A).styleToEqual({}); + expect(component).toHaveStyle(expected.style ?? {}); } if (expected.warning) { - expect(A).toHaveStyleWarnings(expected.warning(className)); + expect(warnings).toEqual(expected.warning(className)); } else { - expect(A).toHaveStyleWarnings(new Map()); + expect(warnings).toEqual(new Map()); } - - expect(className).styleMetaToEqual(expected.meta); }); } diff --git a/packages/react-native-css-interop/src/__tests__/animations.test.tsx b/packages/react-native-css-interop/src/__tests__/animations.test.tsx index a2ae3f096..fc8e4b859 100644 --- a/packages/react-native-css-interop/src/__tests__/animations.test.tsx +++ b/packages/react-native-css-interop/src/__tests__/animations.test.tsx @@ -1,9 +1,11 @@ +import { View } from "react-native"; import { render } from "@testing-library/react-native"; import { StyleSheet } from "../runtime/native/stylesheet"; import { createMockComponent, registerCSS } from "../testing-library"; -const A = createMockComponent(); +const testID = "react-native-css-interop"; +const A = createMockComponent(View); jest.useFakeTimers(); @@ -29,23 +31,23 @@ test("basic animation", () => { } `); - const testComponent = render( - , - ).getByTestId("test"); + const component = render( + , + ).getByTestId(testID); - expect(testComponent).toHaveAnimatedStyle({ + expect(component).toHaveAnimatedStyle({ marginLeft: "100%", }); jest.advanceTimersByTime(1500); - expect(testComponent).toHaveAnimatedStyle({ + expect(component).toHaveAnimatedStyle({ marginLeft: "50%", }); jest.advanceTimersByTime(1500); - expect(testComponent).toHaveAnimatedStyle({ + expect(component).toHaveAnimatedStyle({ marginLeft: "0%", }); }); @@ -64,23 +66,23 @@ test("single frame", () => { } `); - const testComponent = render( - , - ).getByTestId("test"); + const component = render( + , + ).getByTestId(testID); - expect(testComponent).toHaveAnimatedStyle({ + expect(component).toHaveAnimatedStyle({ transform: [{ rotate: "0deg" }], }); jest.advanceTimersByTime(1500); - expect(testComponent).toHaveAnimatedStyle({ + expect(component).toHaveAnimatedStyle({ transform: [{ rotate: "180deg" }], }); jest.advanceTimersByTime(1500); - expect(testComponent).toHaveAnimatedStyle({ + expect(component).toHaveAnimatedStyle({ transform: [{ rotate: "360deg" }], }); }); @@ -100,30 +102,30 @@ test("transform - starting", () => { } `); - const testComponent = render( - , - ).getByTestId("test"); + const component = render( + , + ).getByTestId(testID); - expect(testComponent).toHaveAnimatedStyle({ + expect(component).toHaveAnimatedStyle({ transform: [{ rotate: "180deg" }], }); jest.advanceTimersByTime(1500); - expect(testComponent).toHaveAnimatedStyle({ + expect(component).toHaveAnimatedStyle({ transform: [{ rotate: "270deg" }], }); jest.advanceTimersByTime(1500); - expect(testComponent).toHaveAnimatedStyle({ + expect(component).toHaveAnimatedStyle({ transform: [{ rotate: "360deg" }], }); }); test("bounce", () => { registerCSS(` - .animate-bounce { + .my-class { animation: bounce 1s infinite; height: 100px; } @@ -141,11 +143,11 @@ test("bounce", () => { } `); - const testComponent = render( - , - ).getByTestId("test"); + const component = render( + , + ).getByTestId(testID); - expect(testComponent).toHaveAnimatedStyle({ + expect(component).toHaveAnimatedStyle({ height: 100, transform: [ { translateY: -25 }, @@ -165,7 +167,7 @@ test("bounce", () => { jest.advanceTimersByTime(500); - expect(testComponent).toHaveAnimatedStyle({ + expect(component).toHaveAnimatedStyle({ height: 100, transform: [ { translateY: 0 }, @@ -185,7 +187,7 @@ test("bounce", () => { jest.advanceTimersByTime(500); - expect(testComponent).toHaveAnimatedStyle({ + expect(component).toHaveAnimatedStyle({ height: 100, transform: [ { translateY: -25 }, diff --git a/packages/react-native-css-interop/src/__tests__/container-queries.test.tsx b/packages/react-native-css-interop/src/__tests__/container-queries.test.tsx index 96c701430..5fde49526 100644 --- a/packages/react-native-css-interop/src/__tests__/container-queries.test.tsx +++ b/packages/react-native-css-interop/src/__tests__/container-queries.test.tsx @@ -1,20 +1,21 @@ +import { View } from "react-native"; import { fireEvent, render, screen } from "@testing-library/react-native"; import { StyleSheet } from "../runtime/native/stylesheet"; import { createMockComponent, registerCSS } from "../testing-library"; -const Parent = createMockComponent(); -const Child = createMockComponent(); +const Parent = createMockComponent(View); +const Child = createMockComponent(View); beforeEach(() => { StyleSheet.__reset(); }); describe("size", () => { - test("width", async () => { + test("width", () => { registerCSS(` - .container { - container-name: test; + .container { + container-name: test; width: 200px; } @@ -31,17 +32,18 @@ describe("size", () => { const { rerender } = render( - + , ); - const parent = await screen.findByTestId("parent"); + const parent = screen.getByTestId("parent"); + const child = screen.getByTestId("child"); - expect(Parent).styleToEqual({ + expect(parent).toHaveStyle({ width: 200, }); - expect(Child).styleToEqual({ + expect(child).toHaveStyle({ color: "rgba(255, 0, 0, 1)", }); @@ -54,7 +56,7 @@ describe("size", () => { }, }); - expect(Child).styleToEqual({ + expect(child).toHaveStyle({ color: "rgba(255, 0, 0, 1)", }); @@ -73,11 +75,11 @@ describe("size", () => { }, }); - expect(Parent).styleToEqual({ + expect(parent).toHaveStyle({ width: 500, }); - expect(Child).styleToEqual({ + expect(child).toHaveStyle({ color: "rgba(0, 0, 255, 1)", }); }); diff --git a/packages/react-native-css-interop/src/__tests__/font.test.tsx b/packages/react-native-css-interop/src/__tests__/font.test.tsx index 47f9418df..c99cdac0e 100644 --- a/packages/react-native-css-interop/src/__tests__/font.test.tsx +++ b/packages/react-native-css-interop/src/__tests__/font.test.tsx @@ -2,22 +2,23 @@ import { render } from "@testing-library/react-native"; import { StyleSheet } from "../runtime/native/stylesheet"; import { createMockComponent, registerCSS } from "../testing-library"; +import { View } from "react-native"; -const A = createMockComponent(); +const testID = "react-native-css-interop"; +const A = createMockComponent(View); afterEach(() => { StyleSheet.__reset(); }); test("heading", () => { - registerCSS(`.my-class { -font-size: 3rem; -line-height: 1; -}`); + registerCSS(`.my-class { font-size: 3rem; line-height: 1; }`); - render(); + const component = render( + , + ).getByTestId(testID); - expect(A).styleToEqual({ + expect(component).toHaveStyle({ fontSize: 42, lineHeight: 42, }); diff --git a/packages/react-native-css-interop/src/__tests__/functions-test.ios.tsx b/packages/react-native-css-interop/src/__tests__/functions-test.ios.tsx index 22377a011..146e8a231 100644 --- a/packages/react-native-css-interop/src/__tests__/functions-test.ios.tsx +++ b/packages/react-native-css-interop/src/__tests__/functions-test.ios.tsx @@ -1,10 +1,11 @@ import { render } from "@testing-library/react-native"; -import { StyleSheet as RNStyleSheet } from "react-native"; +import { StyleSheet as RNStyleSheet, View } from "react-native"; import { StyleSheet } from "../runtime/native/stylesheet"; import { createMockComponent, registerCSS } from "../testing-library"; -const A = createMockComponent(); +const testID = "react-native-css-interop"; +const A = createMockComponent(View); afterEach(() => { StyleSheet.__reset(); @@ -20,9 +21,13 @@ describe("functions - ios", () => { }`, ); - render(); + const component = render( + , + ).getByTestId(testID); - expect(A).styleToEqual({ color: "black" }); + expect(component).toHaveStyle({ + color: "black", + }); }); test("hairlineWidth", () => { @@ -33,8 +38,12 @@ describe("functions - ios", () => { }`, ); - render(); + const component = render( + , + ).getByTestId(testID); - expect(A).styleToEqual({ width: RNStyleSheet.hairlineWidth }); + expect(component).toHaveStyle({ + width: RNStyleSheet.hairlineWidth, + }); }); }); diff --git a/packages/react-native-css-interop/src/__tests__/grouping.test.tsx b/packages/react-native-css-interop/src/__tests__/grouping.test.tsx index 757bf9253..49896e929 100644 --- a/packages/react-native-css-interop/src/__tests__/grouping.test.tsx +++ b/packages/react-native-css-interop/src/__tests__/grouping.test.tsx @@ -1,15 +1,18 @@ -import { render } from "@testing-library/react-native"; +import { render, screen } from "@testing-library/react-native"; import { StyleSheet } from "../runtime/native/stylesheet"; import { createMockComponent, registerCSS } from "../testing-library"; +import { View } from "react-native"; afterEach(() => { StyleSheet.__reset(); }); test("group", async () => { - const A = createMockComponent(); - const B = createMockComponent(); + const A = createMockComponent(View); + const B = createMockComponent(View); + + const testID = "a"; registerCSS( `.group\\/item .my-class { @@ -20,22 +23,28 @@ test("group", async () => { }, ); - const { rerender } = render(); + const { rerender, getByTestId } = render( + + + , + ); - expect(B).styleToEqual({}); + expect(getByTestId(testID)).toHaveStyle({}); rerender( - - + + , ); - expect(B).styleToEqual({ color: "rgba(255, 0, 0, 1)" }); + expect(getByTestId(testID)).toHaveStyle({ color: "rgba(255, 0, 0, 1)" }); }); -test.only("invalid group", async () => { - const A = createMockComponent(); - const B = createMockComponent(); +test("invalid group", async () => { + const A = createMockComponent(View); + const B = createMockComponent(View); + + const testID = "b"; registerCSS( `.invalid .my-class { @@ -46,15 +55,16 @@ test.only("invalid group", async () => { }, ); - const { rerender } = render(); + const { rerender } = render(); + const componentB = screen.findAllByTestId(testID); - expect(B).styleToEqual(undefined); + expect(componentB).toHaveStyle(undefined); rerender( - + , ); - expect(B).styleToEqual(undefined); + expect(componentB).toHaveStyle(undefined); }); diff --git a/packages/react-native-css-interop/src/__tests__/media-query.test.tsx b/packages/react-native-css-interop/src/__tests__/media-query.test.tsx index 5c18b634c..6efb877b2 100644 --- a/packages/react-native-css-interop/src/__tests__/media-query.test.tsx +++ b/packages/react-native-css-interop/src/__tests__/media-query.test.tsx @@ -8,8 +8,10 @@ import { } from "../runtime/native/globals"; import { StyleSheet } from "../runtime/native/stylesheet"; import { createMockComponent, registerCSS } from "../testing-library"; +import { View } from "react-native"; -const A = createMockComponent(); +const testID = "react-native-css-interop"; +const A = createMockComponent(View); beforeEach(() => { StyleSheet.__reset(); @@ -23,9 +25,11 @@ test("color scheme", () => { .my-class { color: red; } }`); - render(); + const component = render( + , + ).getByTestId(testID); - expect(A).styleToEqual({ + expect(component).toHaveStyle({ color: "rgba(0, 0, 255, 1)", }); @@ -33,7 +37,7 @@ test("color scheme", () => { colorScheme.set("dark"); }); - expect(A).styleToEqual({ + expect(component).toHaveStyle({ color: "rgba(255, 0, 0, 1)", }); }); @@ -47,9 +51,11 @@ test("prefers-reduced-motion", () => { } `); - render(); + const component = render( + , + ).getByTestId(testID); - expect(A).styleToEqual({ + expect(component).toHaveStyle({ color: "rgba(0, 0, 255, 1)", }); @@ -57,7 +63,7 @@ test("prefers-reduced-motion", () => { isReduceMotionEnabled.set(true); }); - expect(A).styleToEqual({ + expect(component).toHaveStyle({ color: "rgba(255, 0, 0, 1)", }); }); @@ -70,9 +76,11 @@ test("width (plain)", () => { .my-class { color: red; } }`); - render(); + const component = render( + , + ).getByTestId(testID); - expect(A).styleToEqual({ + expect(component).toHaveStyle({ color: "rgba(0, 0, 255, 1)", }); @@ -80,7 +88,7 @@ test("width (plain)", () => { vw[INTERNAL_SET](500); }); - expect(A).styleToEqual({ + expect(component).toHaveStyle({ color: "rgba(255, 0, 0, 1)", }); }); @@ -93,9 +101,11 @@ test("width (range)", () => { .my-class { color: red; } }`); - render(); + const component = render( + , + ).getByTestId(testID); - expect(A).styleToEqual({ + expect(component).toHaveStyle({ color: "rgba(0, 0, 255, 1)", }); @@ -103,7 +113,7 @@ test("width (range)", () => { vw[INTERNAL_SET](500); }); - expect(A).styleToEqual({ + expect(component).toHaveStyle({ color: "rgba(255, 0, 0, 1)", }); }); @@ -116,9 +126,11 @@ test("min-width", () => { .my-class { color: red; } }`); - render(); + const component = render( + , + ).getByTestId(testID); - expect(A).styleToEqual({ + expect(component).toHaveStyle({ color: "rgba(255, 0, 0, 1)", }); @@ -126,7 +138,7 @@ test("min-width", () => { vw[INTERNAL_SET](300); }); - expect(A).styleToEqual({ + expect(component).toHaveStyle({ color: "rgba(0, 0, 255, 1)", }); }); @@ -139,9 +151,11 @@ test("max-width", () => { .my-class { color: red; } }`); - render(); + const component = render( + , + ).getByTestId(testID); - expect(A).styleToEqual({ + expect(component).toHaveStyle({ color: "rgba(0, 0, 255, 1)", }); @@ -149,7 +163,7 @@ test("max-width", () => { vw[INTERNAL_SET](300); }); - expect(A).styleToEqual({ + expect(component).toHaveStyle({ color: "rgba(255, 0, 0, 1)", }); }); diff --git a/packages/react-native-css-interop/src/__tests__/pseudo-classes.tsx b/packages/react-native-css-interop/src/__tests__/pseudo-classes.tsx index 656484350..3fd6d89b4 100644 --- a/packages/react-native-css-interop/src/__tests__/pseudo-classes.tsx +++ b/packages/react-native-css-interop/src/__tests__/pseudo-classes.tsx @@ -1,9 +1,13 @@ -import { act, fireEvent, render, screen } from "@testing-library/react-native"; +import { fireEvent, render } from "@testing-library/react-native"; import { StyleSheet } from "../runtime/native/stylesheet"; import { createMockComponent, registerCSS } from "../testing-library"; +import { TextInput } from "react-native"; -const A = createMockComponent(); +const testID = "react-native-css-interop"; + +// View's do not have a onFocus listener on iOS/Android +const A = createMockComponent(TextInput); afterEach(() => { StyleSheet.__reset(); @@ -12,77 +16,69 @@ afterEach(() => { test("hover", () => { registerCSS(`.my-class:hover { width: 10px; }`); - render(); - - expect(A).styleToEqual({}); - - act(() => fireEvent(screen.getByTestId("a"), "hoverIn", {})); + const component = render( + , + ).getByTestId(testID); - expect(A).styleToEqual({ width: 10 }); + expect(component).toHaveStyle({}); - act(() => fireEvent(screen.getByTestId("a"), "hoverOut", {})); + fireEvent(component, "hoverIn"); + expect(component).toHaveStyle({ width: 10 }); - expect(A).styleToEqual({}); + fireEvent(component, "hoverOut"); + expect(component).toHaveStyle({}); }); test("active", () => { registerCSS(`.my-class:active { width: 10px; }`); - render(); + const component = render( + , + ).getByTestId(testID); - expect(A).styleToEqual({}); + expect(component).toHaveStyle({}); - act(() => fireEvent(screen.getByTestId("a"), "PressIn", {})); + fireEvent(component, "pressIn"); + expect(component).toHaveStyle({ width: 10 }); - expect(A).styleToEqual({ width: 10 }); - - act(() => fireEvent(screen.getByTestId("a"), "PressOut", {})); - - expect(A).styleToEqual({}); + fireEvent(component, "pressOut"); + expect(component).toHaveStyle({}); }); test("focus", () => { registerCSS(`.my-class:focus { width: 10px; }`); - render(); - - expect(A).styleToEqual({}); + const component = render( + , + ).getByTestId(testID); - act(() => fireEvent(screen.getByTestId("a"), "Focus", {})); + expect(component).toHaveStyle({}); - expect(A).styleToEqual({ width: 10 }); + fireEvent(component, "focus"); + expect(component).toHaveStyle({ width: 10 }); - act(() => fireEvent(screen.getByTestId("a"), "Blur", {})); - - expect(A).styleToEqual({}); + fireEvent(component, "blur"); + expect(component).toHaveStyle({}); }); test(":hover:active:focus", () => { registerCSS(`.my-class:hover:active:focus { width: 10px; }`); - render(); - - expect(A).styleToEqual({}); - - act(() => { - fireEvent(screen.getByTestId("a"), "hoverIn", {}); - }); - - expect(A).styleToEqual({}); - - act(() => { - fireEvent(screen.getByTestId("a"), "PressIn", {}); - }); + const component = render( + , + ).getByTestId(testID); - expect(A).styleToEqual({}); + expect(component).toHaveStyle({}); - act(() => { - fireEvent(screen.getByTestId("a"), "focus", {}); - }); + fireEvent(component, "hoverIn", {}); + expect(component).toHaveStyle({}); - expect(A).styleToEqual({ width: 10 }); + fireEvent(component, "pressIn", {}); + expect(component).toHaveStyle({}); - act(() => fireEvent(screen.getByTestId("a"), "hoverOut", {})); + fireEvent(component, "focus", {}); + expect(component).toHaveStyle({ width: 10 }); - expect(A).styleToEqual({}); + fireEvent(component, "hoverOut", {}); + expect(component).toHaveStyle({}); }); diff --git a/packages/react-native-css-interop/src/__tests__/selectors.test.tsx b/packages/react-native-css-interop/src/__tests__/selectors.test.tsx deleted file mode 100644 index dd4a02fdf..000000000 --- a/packages/react-native-css-interop/src/__tests__/selectors.test.tsx +++ /dev/null @@ -1,114 +0,0 @@ -import { fireEvent, render } from "@testing-library/react-native"; - -import { StyleSheet } from "../runtime/native/stylesheet"; -import { createMockComponent, registerCSS } from "../testing-library"; - -afterEach(() => { - StyleSheet.__reset(); -}); - -test("group", async () => { - const A = createMockComponent(); - const B = createMockComponent(); - - registerCSS( - `.group\\/item .my-class { - color: red; - }`, - { - grouping: ["^group\\/.*"], - }, - ); - - const { rerender } = render(); - - expect(B).styleToEqual({}); - - rerender( - - - , - ); - - expect(B).styleToEqual({ color: "rgba(255, 0, 0, 1)" }); -}); - -test("invalid group", async () => { - const A = createMockComponent(); - const B = createMockComponent(); - - registerCSS( - `.invalid .my-class { - color: red; - }`, - { - grouping: ["^group\\/.*"], - }, - ); - - const { rerender } = render(); - - expect(B).styleToEqual(undefined); - - rerender( - - - , - ); - - expect(B).styleToEqual(undefined); -}); - -test("multiple groups", async () => { - const A = createMockComponent(); - const B = createMockComponent(); - - registerCSS( - `.valid .my-class { - color: red; - }`, - { - grouping: ["^group\\/.*", "^valid"], - }, - ); - - const { rerender } = render(); - - expect(B).styleToEqual({}); - - rerender( - - - , - ); - - expect(B).styleToEqual({ color: "rgba(255, 0, 0, 1)" }); -}); - -test("groups - pseudo classes", async () => { - const A = createMockComponent(); - const B = createMockComponent(); - - registerCSS( - `.btn:active .btn-text { - color: red; - }`, - { - grouping: ["^btn$"], - }, - ); - - const { findByTestId } = render( - - - , - ); - - const aComponent = await findByTestId("A"); - - expect(B).styleToEqual({}); - - fireEvent(aComponent, "pressIn"); - - expect(B).styleToEqual({ color: "rgba(255, 0, 0, 1)" }); -}); diff --git a/packages/react-native-css-interop/src/__tests__/smoke.test.tsx b/packages/react-native-css-interop/src/__tests__/smoke.test.tsx deleted file mode 100644 index 192355e8b..000000000 --- a/packages/react-native-css-interop/src/__tests__/smoke.test.tsx +++ /dev/null @@ -1,49 +0,0 @@ -/* - * These tests simple smoke tests to ensure the core functionality is met. - * If you need to go into more detail, create a new test file - * - * https://en.wikipedia.org/wiki/Smoke_testing_(software) - */ -import { render } from "@testing-library/react-native"; - -import { StyleSheet } from "../runtime/native/stylesheet"; -import { createMockComponent, registerCSS } from "../testing-library"; - -type TestSuite = readonly [ - CSSStyleDeclaration[T], - Record, -]; - -type TestSuites = { - [K in string & - keyof CSSStyleDeclaration as CamelToKebabCase]: TestSuite; -}; - -type CamelToKebabCase< - T extends string, - A extends string = "", -> = T extends `${infer F}${infer R}` - ? CamelToKebabCase< - R, - `${A}${F extends Lowercase ? "" : "-"}${Lowercase}` - > - : A; - -const A = createMockComponent(); - -afterEach(() => { - StyleSheet.__reset(); -}); - -const cases: Partial = { - color: ["red", { color: "rgba(255, 0, 0, 1)" }], - // "background-color": ["purple", { backgroundColor: "rgba(128, 0, 128, 1)" }], -}; - -test.each(Object.entries(cases))("%s", (key, [css, expected]) => { - registerCSS(`.my-class { ${key}: ${css} }`); - - render(); - - expect(A).styleToEqual(expected); -}); diff --git a/packages/react-native-css-interop/src/__tests__/transform.test.tsx b/packages/react-native-css-interop/src/__tests__/transform.test.tsx index f0891da99..0b78fe186 100644 --- a/packages/react-native-css-interop/src/__tests__/transform.test.tsx +++ b/packages/react-native-css-interop/src/__tests__/transform.test.tsx @@ -2,8 +2,10 @@ import { render } from "@testing-library/react-native"; import { StyleSheet } from "../runtime/native/stylesheet"; import { createMockComponent, registerCSS } from "../testing-library"; +import { View } from "react-native"; -const A = createMockComponent(); +const testID = "react-native-css-interop"; +const A = createMockComponent(View); afterEach(() => { StyleSheet.__reset(); @@ -12,9 +14,11 @@ afterEach(() => { test("translateX percentage", () => { registerCSS(`.my-class { width: 120px; transform: translateX(10%); }`); - render(); + const component = render( + , + ).getByTestId(testID); - expect(A).styleToEqual({ + expect(component).toHaveStyle({ width: 120, transform: [{ translateX: 12 }], }); @@ -23,20 +27,24 @@ test("translateX percentage", () => { test("translateY percentage", () => { registerCSS(`.my-class { height: 120px; transform: translateY(10%); }`); - render(); + const component = render( + , + ).getByTestId(testID); - expect(A).styleToEqual({ + expect(component).toHaveStyle({ height: 120, transform: [{ translateY: 12 }], }); }); test("rotate-180", () => { - registerCSS(`.rotate-180 { transform: rotate(180deg); }`); + registerCSS(`.my-class { transform: rotate(180deg); }`); - render(); + const component = render( + , + ).getByTestId(testID); - expect(A).styleToEqual({ + expect(component).toHaveStyle({ transform: [{ rotate: "180deg" }], }); }); diff --git a/packages/react-native-css-interop/src/__tests__/transitions.test.tsx b/packages/react-native-css-interop/src/__tests__/transitions.test.tsx index 85dfb96ca..d77cd8222 100644 --- a/packages/react-native-css-interop/src/__tests__/transitions.test.tsx +++ b/packages/react-native-css-interop/src/__tests__/transitions.test.tsx @@ -4,6 +4,7 @@ import { View } from "react-native"; import { StyleSheet } from "../runtime/native/stylesheet"; import { createMockComponent, registerCSS } from "../testing-library"; +const testID = "react-native-css-interop"; const A = createMockComponent(View); jest.useFakeTimers(); @@ -28,42 +29,42 @@ test("numeric transition", () => { `); const { rerender, getByTestId } = render( - , + , ); - const testComponent = getByTestId("test"); + const component = getByTestId(testID); // Should have a static width, no matter the time - expect(testComponent).toHaveAnimatedStyle({ + expect(component).toHaveAnimatedStyle({ width: 100, }); jest.advanceTimersByTime(1000); - expect(testComponent).toHaveAnimatedStyle({ + expect(component).toHaveAnimatedStyle({ width: 100, }); - rerender(); + rerender(); // Directly after rerender, should still have the old width - expect(testComponent).toHaveAnimatedStyle({ + expect(component).toHaveAnimatedStyle({ width: 100, }); // Width should only change after we advance time jest.advanceTimersByTime(500); - expect(testComponent).toHaveAnimatedStyle({ + expect(component).toHaveAnimatedStyle({ width: 150, }); // At the end of the transition jest.advanceTimersByTime(500); - expect(testComponent).toHaveAnimatedStyle({ + expect(component).toHaveAnimatedStyle({ width: 200, }); // Width should not change after the transition is done jest.advanceTimersByTime(500); - expect(testComponent).toHaveAnimatedStyle({ + expect(component).toHaveAnimatedStyle({ width: 200, }); }); @@ -84,42 +85,42 @@ test("color transition", () => { `); const { rerender, getByTestId } = render( - , + , ); - const testComponent = getByTestId("test"); + const component = getByTestId(testID); // Should have a static width, no matter the time - expect(testComponent).toHaveAnimatedStyle({ + expect(component).toHaveAnimatedStyle({ color: "rgba(255, 0, 0, 1)", }); jest.advanceTimersByTime(1000); - expect(testComponent).toHaveAnimatedStyle({ + expect(component).toHaveAnimatedStyle({ color: "rgba(255, 0, 0, 1)", }); - rerender(); + rerender(); // Directly after rerender, should still have the old width - expect(testComponent).toHaveAnimatedStyle({ + expect(component).toHaveAnimatedStyle({ color: "rgba(255, 0, 0, 1)", }); // Width should only change after we advance time jest.advanceTimersByTime(500); - expect(testComponent).toHaveAnimatedStyle({ + expect(component).toHaveAnimatedStyle({ color: "rgba(186, 0, 186, 1)", }); // At the end of the transition jest.advanceTimersByTime(500); - expect(testComponent).toHaveAnimatedStyle({ + expect(component).toHaveAnimatedStyle({ color: "rgba(0, 0, 255, 1)", }); // Width should not change after the transition is done jest.advanceTimersByTime(500); - expect(testComponent).toHaveAnimatedStyle({ + expect(component).toHaveAnimatedStyle({ color: "rgba(0, 0, 255, 1)", }); }); diff --git a/packages/react-native-css-interop/src/__tests__/units.test.tsx b/packages/react-native-css-interop/src/__tests__/units.test.tsx index f370f3366..acfc28847 100644 --- a/packages/react-native-css-interop/src/__tests__/units.test.tsx +++ b/packages/react-native-css-interop/src/__tests__/units.test.tsx @@ -2,8 +2,10 @@ import { act, render } from "@testing-library/react-native"; import { INTERNAL_SET, rem, vh, vw } from "../runtime/native/globals"; import { StyleSheet } from "../runtime/native/stylesheet"; import { createMockComponent, registerCSS } from "../testing-library"; +import { View } from "react-native"; -const A = createMockComponent(); +const testID = "react-native-css-interop"; +const A = createMockComponent(View); afterEach(() => { StyleSheet.__reset(); @@ -12,9 +14,11 @@ afterEach(() => { test("px", () => { registerCSS(`.my-class { width: 10px; }`); - render(); + const component = render( + , + ).getByTestId(testID); - expect(A).styleToEqual({ + expect(component).toHaveStyle({ width: 10, }); }); @@ -22,9 +26,11 @@ test("px", () => { test("%", () => { registerCSS(`.my-class { width: 10%; }`); - render(); + const component = render( + , + ).getByTestId(testID); - expect(A).styleToEqual({ + expect(component).toHaveStyle({ width: "10%", }); }); @@ -32,43 +38,47 @@ test("%", () => { test("vw", () => { registerCSS(`.my-class { width: 10vw; }`); - render(); + const component = render( + , + ).getByTestId(testID); expect(vw.get()).toEqual(750); - expect(A).styleToEqual({ - width: 75, - }); + expect(component).toHaveStyle({ width: 75 }); act(() => { vw[INTERNAL_SET](100); }); expect(vw.get()).toEqual(100); - expect(A).styleToEqual({ width: 10 }); + expect(component).toHaveStyle({ width: 10 }); }); test("vh", () => { registerCSS(`.my-class { height: 10vh; }`); - render(); + const component = render( + , + ).getByTestId(testID); expect(vh.get()).toEqual(1334); - expect(A).styleToEqual({ height: 133.4 }); + expect(component).toHaveStyle({ height: 133.4 }); act(() => { vh[INTERNAL_SET](100); }); expect(vh.get()).toEqual(100); - expect(A).styleToEqual({ height: 10 }); + expect(component).toHaveStyle({ height: 10 }); }); test("rem - default", () => { registerCSS(`.my-class { font-size: 10rem; }`); - render(); + const component = render( + , + ).getByTestId(testID); - expect(A).styleToEqual({ fontSize: 140 }); + expect(component).toHaveStyle({ fontSize: 140 }); }); test("rem - override", () => { @@ -76,9 +86,11 @@ test("rem - override", () => { inlineRem: 10, }); - render(); + const component = render( + , + ).getByTestId(testID); - expect(A).styleToEqual({ fontSize: 100 }); + expect(component).toHaveStyle({ fontSize: 100 }); }); test("rem - dynamic", () => { @@ -86,15 +98,17 @@ test("rem - dynamic", () => { inlineRem: false, }); - render(); + const component = render( + , + ).getByTestId(testID); expect(rem.get()).toEqual(14); - expect(A).styleToEqual({ fontSize: 140 }); + expect(component).toHaveStyle({ fontSize: 140 }); act(() => { rem.set(10); }); expect(rem.get()).toEqual(10); - expect(A).styleToEqual({ fontSize: 100 }); + expect(component).toHaveStyle({ fontSize: 100 }); }); diff --git a/packages/react-native-css-interop/src/__tests__/variables.test.tsx b/packages/react-native-css-interop/src/__tests__/variables.test.tsx index de364a8d4..410752af0 100644 --- a/packages/react-native-css-interop/src/__tests__/variables.test.tsx +++ b/packages/react-native-css-interop/src/__tests__/variables.test.tsx @@ -2,8 +2,10 @@ import { render, screen } from "@testing-library/react-native"; import { StyleSheet } from "../runtime/native/stylesheet"; import { createMockComponent, registerCSS } from "../testing-library"; +import { View } from "react-native"; -const A = createMockComponent(); +const testID = "react-native-css-interop"; +const A = createMockComponent(View); afterEach(() => { StyleSheet.__reset(); @@ -12,9 +14,11 @@ afterEach(() => { test("inline variable", () => { registerCSS(`.my-class { width: var(--my-var); --my-var: 10px; }`); - render(); + const component = render( + , + ).getByTestId(testID); - expect(A).styleToEqual({ + expect(component).toHaveStyle({ width: 10, }); }); @@ -28,20 +32,24 @@ test("combined inline variable", () => { render(); - expect(A).styleToEqual({ + const component = render( + , + ).getByTestId(testID); + + expect(component).toHaveStyle({ width: 10, }); // Prove that the order doesn't matter screen.rerender(); - expect(A).styleToEqual({ + expect(component).toHaveStyle({ width: 20, }); }); test("inherit variables", () => { - const B = createMockComponent(); + const B = createMockComponent(View); registerCSS(` .my-class-1 { width: var(--my-var); } @@ -49,14 +57,17 @@ test("inherit variables", () => { .my-class-3 { --my-var: 20px; } `); - render( - - + const { getByTestId } = render( + + , ); - expect(A).styleToEqual({}); - expect(B).styleToEqual({ width: 10 }); + const a = getByTestId("a"); + const b = getByTestId("b"); + + expect(a).toHaveStyle({}); + expect(b).toHaveStyle({ width: 10 }); screen.rerender( @@ -64,8 +75,8 @@ test("inherit variables", () => { , ); - expect(A).styleToEqual({}); - expect(B).styleToEqual({ width: 20 }); + expect(a).toHaveStyle({}); + expect(b).toHaveStyle({ width: 20 }); }); test(":root variables", () => { @@ -74,7 +85,9 @@ test(":root variables", () => { .my-class { color: var(--my-var); } `); - render(); + const component = render( + , + ).getByTestId(testID); - expect(A).styleToEqual({ color: "red" }); + expect(component).toHaveStyle({ color: "red" }); }); diff --git a/packages/react-native-css-interop/src/index.native.ts b/packages/react-native-css-interop/src/index.native.ts index 46e794e09..4a69a572c 100644 --- a/packages/react-native-css-interop/src/index.native.ts +++ b/packages/react-native-css-interop/src/index.native.ts @@ -3,4 +3,6 @@ import React from "react"; export { StyleSheet } from "./runtime/native/stylesheet"; export { enableCSSInterop } from "./runtime/shared/enable-css-interop"; +export { globalStyles, styleMetaMap, warnings } from "./runtime/shared/globals"; + export const createElement = React.createElement; diff --git a/packages/react-native-css-interop/src/index.ts b/packages/react-native-css-interop/src/index.ts index 859788d13..80aa22737 100644 --- a/packages/react-native-css-interop/src/index.ts +++ b/packages/react-native-css-interop/src/index.ts @@ -4,6 +4,8 @@ export { StyleSheet } from "./runtime/web/stylesheet"; export { enableCSSInterop } from "./runtime/shared/enable-css-interop"; export { checkJsxPragma } from "./runtime/check-render"; +export { globalStyles, styleMetaMap, warnings } from "./runtime/shared/globals"; + /** * @deprecated This is an alias for React.createElement. Just use it directly */ diff --git a/packages/react-native-css-interop/src/runtime/native/animations.tsx b/packages/react-native-css-interop/src/runtime/native/animations.tsx index 0a4a581ce..8e71fb2c7 100644 --- a/packages/react-native-css-interop/src/runtime/native/animations.tsx +++ b/packages/react-native-css-interop/src/runtime/native/animations.tsx @@ -30,6 +30,10 @@ type AnimationInteropProps = Record & { __interopMeta: InteropMeta; }; +/** + * TODO: We could probably half the amount of code if this was rewritten to use useAnimatedProps + */ + /* * This component breaks the rules of hooks, however is it safe to do so as the animatedProps are static * If they do change, the key for this component will be regenerated forcing a remount (a reset of hooks) @@ -130,7 +134,7 @@ function useAnimationAndTransitions( isLayoutReady, ); - return useAnimatedStyle(() => { + const animatedStyle = useAnimatedStyle(() => { const transformProps = new Set(Object.keys(defaultTransform)); const result: Record = { ...style }; @@ -164,6 +168,11 @@ function useAnimationAndTransitions( doAnimation(animationProps, animationValues); return result; }, [...transitionValues, ...animationValues]); + + // This doesn't have a runtime purpose, it just makes the unit tests easier to write + styleMetaMap.set(animatedStyle, styleMetaMap.get(style)!); + + return animatedStyle; } function useTransitions( @@ -308,7 +317,8 @@ function useAnimations( const animationValues: SharedValue[] = []; for (const [prop, [first]] of animations.entries()) { // eslint-disable-next-line react-hooks/rules-of-hooks - animationValues.push(useSharedValue(getInitialValue(prop, first, style))); + const a = useSharedValue(getInitialValue(prop, first, style)); + animationValues.push(a); animationProps.push(prop); } diff --git a/packages/react-native-css-interop/src/runtime/native/interaction.ts b/packages/react-native-css-interop/src/runtime/native/interaction.ts index 0ebf23700..818daeda2 100644 --- a/packages/react-native-css-interop/src/runtime/native/interaction.ts +++ b/packages/react-native-css-interop/src/runtime/native/interaction.ts @@ -61,6 +61,7 @@ export function useInteractionHandlers( signals.hover.set(false); }, onFocus(event: NativeSyntheticEvent) { + debugger; propsRef.current.onFocus?.(event); signals.focus.set(true); }, diff --git a/packages/react-native-css-interop/src/testing-library/index.tsx b/packages/react-native-css-interop/src/testing-library/index.tsx index bcceb1fa9..d3cb668e7 100644 --- a/packages/react-native-css-interop/src/testing-library/index.tsx +++ b/packages/react-native-css-interop/src/testing-library/index.tsx @@ -1,72 +1,48 @@ -import { - forwardRef, - ComponentType, - ForwardRefExoticComponent, - RefAttributes, -} from "react"; -import { Platform, View, ViewProps } from "react-native"; +import { forwardRef } from "react"; +import * as JSX from "react/jsx-runtime"; +import { Platform } from "react-native"; -import { defaultCSSInterop } from "../runtime/css-interop"; +import { Style, StyleMeta } from "../types"; import { StyleSheet } from "../index"; +import { defaultCSSInterop } from "../runtime/css-interop"; +import { render } from "../runtime/render"; import { CssToReactNativeRuntimeOptions, cssToReactNativeRuntime, } from "../css-to-rn"; -import { ExtractionWarning, Style, StyleMeta } from "../types"; -import { render } from "../runtime/render"; declare global { namespace jest { interface Matchers { - styleToEqual(style?: Style): R; - styleMetaToEqual(meta?: StyleMeta): R; - toHaveStyleWarnings(warnings?: Map): R; + toHaveStyle(style?: Style): R; + toHaveStyleMeta(meta?: StyleMeta): R; toHaveAnimatedStyle(style?: Style): R; } } } -type MockComponentProps = ViewProps & { className?: string }; -type MockComponent = ForwardRefExoticComponent< - MockComponentProps & RefAttributes -> & - jest.Mock; - /* * Creates a mocked component that renders with the defaultCSSInterop WITHOUT needing * set the jsxImportSource. */ export function createMockComponent( - Component: React.ComponentType = View, - mapping = { className: "style" }, -): MockComponent { - const spy = jest.fn((props, ref) => ); - - // We need to forward the ref through the mock that Jest creates - const spyWithRef = forwardRef(spy); - + Component: React.ComponentType, + { mapping = { className: "style" } } = {}, +): typeof Component { const mappingMap = new Map(Object.entries(mapping)); - return Object.assign( - // Create a wrapper that manually calls our jsxImportSource without changing the default jsxImportSource - forwardRef((props: Record, ref) => { - return render( - // Create a fake `jsx` function. This will render the component called the real jsxImportSource - (ComponentType: ComponentType, props: object, key?: string) => { - return ; - }, - spyWithRef, - props, - props.key?.toString(), - undefined, - (jsx, type, props, key) => { - return defaultCSSInterop(jsx, type, props, key, mappingMap); - }, - ); - }), - // Append the mock so we can access it - spy, - ); + return forwardRef((props, ref) => { + return render( + (JSX as any).jsx, + Component, + props as any, + "", + undefined, + (jsx, type, props, key) => { + return defaultCSSInterop(jsx, type, { ...props, ref }, key, mappingMap); + }, + ); + }); } export function resetStyles() { diff --git a/packages/react-native-css-interop/src/testing-library/setupAfterEnv.ts b/packages/react-native-css-interop/src/testing-library/setupAfterEnv.ts index c146af081..02564e2bd 100644 --- a/packages/react-native-css-interop/src/testing-library/setupAfterEnv.ts +++ b/packages/react-native-css-interop/src/testing-library/setupAfterEnv.ts @@ -1,24 +1,15 @@ import { expect } from "@jest/globals"; import matchers from "expect/build/matchers"; -import { - warnings, - styleMetaMap, - globalStyles, -} from "../runtime/shared/globals"; +import { styleMetaMap } from "../runtime/shared/globals"; // I do not know why this is needed matchers.customTesters = []; expect.extend({ - styleToEqual(received, style) { - const lastCall = received.mock.calls[received.mock.calls.length - 1][0]; - return matchers.toEqual(lastCall?.style, style); + toHaveStyle(received, style) { + return matchers.toEqual(received?.props?.style, style); }, - styleMetaToEqual(received, expected) { - const style = globalStyles.get(received)!; - return matchers.toEqual(styleMetaMap.get(style), expected); - }, - toHaveStyleWarnings(_received, expected) { - return matchers.toEqual(warnings, expected); + toHaveStyleMeta(received, expected) { + return matchers.toEqual(styleMetaMap.get(received?.props?.style), expected); }, });