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

feat(starter): add qwik testing library #6924

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
7 changes: 7 additions & 0 deletions .changeset/good-ladybugs-worry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'create-qwik': patch
'@builder.io/qwik': patch
---

starter: add qwik-testing-library starter
docs: document integration qwik-testing-library
294 changes: 294 additions & 0 deletions packages/docs/public/ecosystem/testing-library.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions packages/docs/src/routes/(ecosystem)/ecosystem.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@
"href": "/docs/integrations/tailwind/",
"imgSrc": "/ecosystem/tailwind.svg"
},
{
"title": "Testing Library",
"href": "/docs/integrations/testing-library/",
"imgSrc": "/ecosystem/testing-library.svg"
},
{
"title": "Vitest",
"href": "/docs/integrations/vitest/",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
---
title: Qwik Testing Library | Integrations
keywords: 'testing, unit test, jest'
contributors:
- ianlet
updated_at: '2024-09-29T12:27:45Z'
created_at: '2024-09-29T12:27:45Z'
---

import PackageManagerTabs from '~/components/package-manager-tabs/index.tsx';

# Qwik Testing Library

⚡ Simple and complete Qwik DOM testing utilities that encourage good testing practices.

[Qwik Testing Library][qwik-testing-library] is a lightweight library for testing Qwik
components. It provides functions on top of [Qwik][qwik] and
[DOM Testing Library][dom-testing-library] so you can mount Qwik components and query their
rendered output in the DOM. Its primary guiding principle is:

> [The more your tests resemble the way your software is used, the more
> confidence they can give you.][guiding-principle]

Note that because [Vite](https://vitejs.dev/) is used by default for Qwik projects, the Qwik Testing Library
integration was configured to run tests with [Vitest][vitest].

[qwik]: https://qwik.dev
[dom-testing-library]: https://github.com/testing-library/dom-testing-library
[qwik-testing-library]: https://github.com/ianlet/qwik-testing-library
[guiding-principle]: https://twitter.com/kentcdodds/status/977018512689455106
[vite]: https://vitejs.dev
[vitest]: https://vitest.dev

## Usage

You can add Qwik Testing Library easily by using the following Qwik starter script:

<PackageManagerTabs>
<span q:slot="pnpm">
```shell
pnpm run qwik add testing-library
```
</span>
<span q:slot="npm">
```shell
npm run qwik add testing-library
```
</span>
<span q:slot="yarn">
```shell
yarn run qwik add testing-library
```
</span>
<span q:slot="bun">
```shell
bun run qwik add testing-library
```
</span>
</PackageManagerTabs>

After running the command, qwik-testing-library will be installed, configured, and a new component will be added to
your project.

The component will be added to the `src/components/example` directory along with a new unit test
named `example. spec.tsx`.

```tsx title="example.spec.tsx"
// import qwik-testing methods
import { screen, render, waitFor } from "@noma.to/qwik-testing-library";
// import the userEvent methods to interact with the DOM
import { userEvent } from "@testing-library/user-event";
// import the component to be tested
import { ExampleTest } from "./example";

// describe the test suite
describe("<ExampleTest />", () => {
// describe the test case
it("should increment the counter", async () => {
// setup user event
const user = userEvent.setup();
// render the component into the DOM
await render(<ExampleTest />);

// retrieve the 'increment count' button
const incrementBtn = screen.getByRole("button", {
name: /increment counter/i,
});
// click the button twice
await user.click(incrementBtn);
await user.click(incrementBtn);

// assert that the counter is now 2
expect(await screen.findByText(/count:2/i)).toBeInTheDocument();
});
});
```
1 change: 1 addition & 0 deletions packages/docs/src/routes/docs/menu.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
- [Supabase](integrations/supabase/index.mdx)
- [Tailwind](integrations/tailwind/index.mdx)
- [Tauri](integrations/tauri/index.mdx)
- [Testing Library](integrations/testing-library/index.mdx)
- [Turso](integrations/turso/index.mdx)
- [Vitest](integrations/vitest/index.mdx)

Expand Down
35 changes: 35 additions & 0 deletions starters/features/testing-library/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"description": "Use Qwik Testing Library into your Qwik app",
"__qwik__": {
"displayName": "Integration: Qwik Testing Library (Unit Test)",
"priority": -15,
"viteConfig": {},
"docs": [
"https://github.com/ianlet/qwik-testing-library",
"https://qwik.dev/integrations/integration/testing-library/",
"https://testing-library.com/docs/"
],
"nextSteps": {
"title": "Next Steps",
"lines": [
"⚡ Happy Testing!",
"",
"Have a look at the example component in 'src/components/example'",
"There you will see a '.spec.tsx' file which is the component test"
]
}
},
"devDependencies": {
"@noma.to/qwik-testing-library": "^1.2.0",
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.5.0",
"@testing-library/user-event": "^14.5.2",
"@vitest/ui": "^2.1.1",
"jsdom": "^25.0.1",
"vitest": "^2.1.1"
},
"scripts": {
"test.unit": "vitest run components",
"test.unit.ui": "vitest --ui components"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// import qwik-testing methods
import { screen, render, waitFor } from "@noma.to/qwik-testing-library";
// import the userEvent methods to interact with the DOM
import { userEvent } from "@testing-library/user-event";
// import the component to be tested
import { ExampleTest } from "./example";

// describe the test suite
describe("<ExampleTest />", () => {
// describe the test case
it("should increment the counter", async () => {
// setup user event
const user = userEvent.setup();
// render the component into the DOM
await render(<ExampleTest />);

// retrieve the 'increment count' button
const incrementBtn = screen.getByRole("button", {
name: /increment counter/i,
});
// click the button twice
await user.click(incrementBtn);
await user.click(incrementBtn);

// assert that the counter is now 2
expect(await screen.findByText(/count:2/i)).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { component$, useStore } from "@builder.io/qwik";

export const ExampleTest = component$((props: { flag: boolean }) => {
const state = useStore({
counter: 0,
});

return (
<>
<span>Count:{state.counter}</span>
<div class="icon">Flag: {props.flag ? "⭐" : "💣"}</div>
<button class="btn-counter" onClick$={() => state.counter++}>
Increment counter
</button>
</>
);
});
5 changes: 5 additions & 0 deletions starters/features/testing-library/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/**
* DO NOT DELETE THIS FILE
*
* This entrypoint is needed by @noma.to/qwik-testing-library to run your tests
*/
6 changes: 6 additions & 0 deletions starters/features/testing-library/tsconfig.test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"types": ["vitest/globals", "@testing-library/jest-dom/vitest"]
}
}
27 changes: 27 additions & 0 deletions starters/features/testing-library/vitest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { defineConfig, mergeConfig } from "vitest/config";
import viteConfig from "./vite.config";

export default defineConfig((configEnv) =>
mergeConfig(
viteConfig(configEnv),
defineConfig({
// qwik-testing-library needs to consider your project as a Qwik lib
// if it's already a Qwik lib, you can remove this section
build: {
target: "es2020",
lib: {
entry: "./src/index.ts",
formats: ["es", "cjs"],
fileName: (format, entryName) =>
`${entryName}.qwik.${format === "es" ? "mjs" : "cjs"}`,
},
},
// configure your test environment
test: {
environment: "jsdom",
setupFiles: ["./vitest.setup.ts"],
globals: true,
},
}),
),
);
8 changes: 8 additions & 0 deletions starters/features/testing-library/vitest.setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Configure DOM matchers to work in Vitest
import "@testing-library/jest-dom/vitest";

// This has to run before qdev.ts loads. `beforeAll` is too late
globalThis.qTest = false; // Forces Qwik to run as if it was in a Browser
globalThis.qRuntimeQrl = true;
globalThis.qDev = true;
globalThis.qInspector = false;