Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(testing): Move to Vitest #151

Merged
merged 1 commit into from
Jul 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 0 additions & 13 deletions package/.mocharc.json

This file was deleted.

12 changes: 5 additions & 7 deletions package/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@
},
"scripts": {
"build": "tsc -p tsconfig.prod.json",
"check": "yarn compile && yarn test",
"check": "yarn compile && yarn test --run",
"compile": "tsc",
"docs": "typedoc",
"release": "semantic-release",
"test": "NODE_ENV=test mocha"
"test": "vitest"
},
"packageManager": "[email protected]",
"dependencies": {
Expand All @@ -47,13 +47,11 @@
"devDependencies": {
"@assertive-ts/core": "^2.1.0",
"@assertive-ts/sinon": "^1.0.0",
"@testing-library/react-native": "~12.4.5",
"@types/mocha": "^10.0.7",
"@testing-library/react-native": "^12.5.1",
"@types/node": "^20.14.10",
"@types/react-test-renderer": "^18.3.0",
"@types/sinon": "^17.0.3",
"expect-type": "^0.19.0",
"mocha": "^10.6.0",
"react": "^18.3.1",
"react-is": "^18.3.1",
"react-native": "0.74.3",
Expand All @@ -63,11 +61,11 @@
"semantic-release": "^24.0.0",
"semantic-release-yarn": "^3.0.2",
"sinon": "^18.0.0",
"ts-node": "^10.9.2",
"typedoc": "^0.26.4",
"typedoc-plugin-markdown": "^4.2.1",
"typedoc-plugin-merge-modules": "^6.0.0",
"typescript": "^5.5.3"
"typescript": "^5.5.3",
"vitest": "^2.0.2"
},
"peerDependencies": {
"react": ">=16.8.0",
Expand Down
7 changes: 4 additions & 3 deletions package/src/lib/SpotlightTour.provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -131,14 +131,15 @@ export const SpotlightTourProvider = forwardRef<SpotlightTour, SpotlightTourProv
hideTooltip: () => Promise.resolve({ finished: false }),
});

const renderStep = useCallback((index: number): void | Promise<void> => {
const renderStep = useCallback((index: number): void => {
const step = steps[index];

if (step !== undefined) {
return Promise.all([
Promise.all([
overlay.current.hideTooltip(),
Promise.resolve().then(step.before),
]).then(() => setCurrent(index));
])
.then(() => setCurrent(index));
}
}, [steps]);

Expand Down
15 changes: 0 additions & 15 deletions package/test/hooks.ts

This file was deleted.

7 changes: 4 additions & 3 deletions package/test/integration/lib/AttachStep.component.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { expect } from "@assertive-ts/core";
import { render, waitFor, within } from "@testing-library/react-native";
import React, { ReactElement, forwardRef } from "react";
import { Text } from "react-native";
import { describe, it, suite } from "vitest";

import { SpotlightTourProvider } from "../../../src/lib/SpotlightTour.provider";
import { AttachStep } from "../../../src/lib/components/attach-step/AttachStep.component";
Expand All @@ -23,8 +24,8 @@ function CustomText(): ReactElement {
);
}

describe("[Integration] AttachStep.component.test.tsx", () => {
context("when a native component is passed as child", () => {
suite("[Integration] AttachStep.component.test.tsx", () => {
describe("when a native component is passed as child", () => {
it("renders the child without wrapping it on a native View", async () => {
const { getByText, queryByTestId } = render(
<SpotlightTourProvider steps={[]}>
Expand All @@ -40,7 +41,7 @@ describe("[Integration] AttachStep.component.test.tsx", () => {
});
});

context("when a function component is passed as child", () => {
describe("when a function component is passed as child", () => {
it("renders the child wrapped on a native View", async () => {
const { getByTestId } = render(
<SpotlightTourProvider steps={[]}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { render, userEvent, waitFor } from "@testing-library/react-native";
import React, { useEffect } from "react";
import { Text, View } from "react-native";
import Sinon from "sinon";
import { describe, it, suite } from "vitest";

import { SpotlightTour, StopParams, TourStep, useSpotlightTour } from "../../../../src/lib/SpotlightTour.context";
import { SpotlightTourProvider } from "../../../../src/lib/SpotlightTour.provider";
Expand Down Expand Up @@ -35,8 +36,8 @@ function TestScreen(): React.ReactElement {
);
}

describe("[Integration] TourOverlay.component.test.tsx", () => {
context("when the spot is in the first step", () => {
suite("[Integration] TourOverlay.component.test.tsx", () => {
describe("when the spot is in the first step", () => {
it("renders the first step", async () => {
const { getByText } = render(
<SpotlightTourProvider steps={STEPS}>
Expand All @@ -48,7 +49,7 @@ describe("[Integration] TourOverlay.component.test.tsx", () => {
});
});

context("when the next action is called", () => {
describe("when the next action is called", () => {
it("removes the previous step and renders the next step", async () => {
const { getByText, queryByText } = render(
<SpotlightTourProvider steps={STEPS}>
Expand All @@ -66,7 +67,7 @@ describe("[Integration] TourOverlay.component.test.tsx", () => {
});
});

context("when previous action is called", () => {
describe("when previous action is called", () => {
it("removes the current step and renders the previous step", async () => {
const { getByText, queryByText } = render(
<SpotlightTourProvider steps={STEPS}>
Expand All @@ -90,7 +91,7 @@ describe("[Integration] TourOverlay.component.test.tsx", () => {
});
});

context("when the backdrop behavior is set to continue", () => {
describe("when the backdrop behavior is set to continue", () => {
it("goes to the next step when the backdrop is pressed", async () => {
const { getByText, findByTestId, queryByText } = render(
<SpotlightTourProvider steps={STEPS} onBackdropPress="continue">
Expand All @@ -110,7 +111,7 @@ describe("[Integration] TourOverlay.component.test.tsx", () => {
});
});

context("when the backdrop behavior is set to stop", () => {
describe("when the backdrop behavior is set to stop", () => {
it("stops the tour when the backdrop is pressed", async () => {
const { getByText, findByTestId, queryByText } = render(
<SpotlightTourProvider steps={STEPS} onBackdropPress="stop">
Expand All @@ -130,7 +131,7 @@ describe("[Integration] TourOverlay.component.test.tsx", () => {
});
});

context("when the backdrop behavior is present in the step", () => {
describe("when the backdrop behavior is present in the step", () => {
it("overrides the backdrop press default behavior", async () => {
const steps = STEPS.map<TourStep>((step, i) => {
return i === 1
Expand Down Expand Up @@ -162,7 +163,7 @@ describe("[Integration] TourOverlay.component.test.tsx", () => {
});
});

context("when a function is passed to the backdrop press behavior", () => {
describe("when a function is passed to the backdrop press behavior", () => {
it("injects the SpotlightTour object in the options", async () => {
const spy = Sinon.spy<(options: SpotlightTour) => void>(() => undefined);

Expand All @@ -189,7 +190,7 @@ describe("[Integration] TourOverlay.component.test.tsx", () => {
});
});

context("when a function is passed to the onStop prop in the tour provider", () => {
describe("when a function is passed to the onStop prop in the tour provider", () => {
it("invokes the function and injects the OnStopBehavior object in the values", async () => {
const spy = Sinon.spy<(values: StopParams) => void>(() => undefined);

Expand All @@ -209,8 +210,8 @@ describe("[Integration] TourOverlay.component.test.tsx", () => {
});
});

context("and the tour is stopped in the second step", () => {
context("and the step is NOT the last one", () => {
describe("and the tour is stopped in the second step", () => {
describe("and the step is NOT the last one", () => {
it("returns step index 1 and is last equals false", async () => {
const spy = Sinon.spy<(values: StopParams) => void>(() => undefined);

Expand All @@ -236,8 +237,8 @@ describe("[Integration] TourOverlay.component.test.tsx", () => {
});
});

context("and the tour is stopped in the third step", () => {
context("and the step is the last one", () => {
describe("and the tour is stopped in the third step", () => {
describe("and the step is the last one", () => {
it("returns step index 2 and is last equals true", async () => {
const spy = Sinon.spy<(values: StopParams) => void>(() => undefined);

Expand Down
28 changes: 22 additions & 6 deletions package/test/integration/main.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ import React from "react";
import { CircleProps } from "react-native-svg";
import { mockNative, restoreNativeMocks } from "react-native-testing-mocks";
import Sinon from "sinon";
import { afterEach, describe, it, suite } from "vitest";

import { TourStep } from "../../src/lib/SpotlightTour.context";
import { BASE_STEP, TestScreen } from "../helpers/TestTour";
import { checkValidIntersection, findPropsOnTestInstance } from "../helpers/helper";
import { buttonMockMeasureData, viewMockMeasureData } from "../helpers/measures";

describe("[Integration] main.test.tsx", () => {
suite("[Integration] main.test.tsx", () => {
describe("when the tour is not running", () => {
it("the overlay is not shown", async () => {
const { getByText, queryByTestId } = render(<TestScreen />);
Expand Down Expand Up @@ -210,7 +211,22 @@ describe("[Integration] main.test.tsx", () => {

describe("and the promise is rejected", () => {
it("does NOT move to the next step", async () => {
const spy = Sinon.spy(() => Promise.reject(new Error("Fail!")));
const error = new Error("Fail!");
const promiseRejected = new Promise<void>((resolve, reject) => {
const handler = (reason: unknown): void => {
process.off("unhandledRejection", handler);

try {
expect(reason).toBeEqual(error);
resolve();
} catch (err) {
reject(err);
}
};

process.on("unhandledRejection", handler);
});
const spy = Sinon.spy(() => Promise.reject(error));
const steps: TourStep[] = [
BASE_STEP,
{ ...BASE_STEP, before: spy },
Expand All @@ -228,10 +244,10 @@ describe("[Integration] main.test.tsx", () => {

await userEvent.press(getByText("Next"));

await waitFor(() => {
expect(spy).toBeCalledOnce();
expect(queryByText("Step 2")).toBeNull();
});
await expect(promiseRejected).toBeResolved();

expect(spy).toBeCalledOnce();
expect(queryByText("Step 2")).toBeNull();
});
});
});
Expand Down
15 changes: 14 additions & 1 deletion package/test/setup.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { usePlugin } from "@assertive-ts/core";
import { SinonPlugin } from "@assertive-ts/sinon";
import { userEvent } from "@testing-library/react-native";
import { cleanup, userEvent } from "@testing-library/react-native";
import Sinon from "sinon";
import { afterEach, beforeEach } from "vitest";

usePlugin(SinonPlugin);

Expand All @@ -13,3 +14,15 @@ const newUserEvent = userEvent.setup({
});

Object.assign(userEvent, newUserEvent);

beforeEach(() => {
Sinon.useFakeTimers({
advanceTimeDelta: 0,
shouldAdvanceTime: true,
});
});

afterEach(() => {
Sinon.restore();
cleanup();
});
6 changes: 1 addition & 5 deletions package/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,5 @@
"exclude": [
"build/*",
"dist/*"
],
"ts-node": {
"transpileOnly": true,
"files": true
}
]
}
10 changes: 10 additions & 0 deletions package/vitest.config.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { reactNativeVitestPlugin } from "react-native-testing-mocks/vitest";
import { defineConfig } from "vitest/config";

export default defineConfig({
plugins: [reactNativeVitestPlugin()],
test: {
include: ["test/**/*.test.ts?(x)"],
setupFiles: "./test/setup.ts",
},
});
Loading
Loading