Skip to content

Commit 1f30fca

Browse files
committed
Merge branch 'main' into pr-new-styled-components
2 parents 7cccb4e + 114f38b commit 1f30fca

27 files changed

+1163
-392
lines changed

.changeset/few-numbers-cross.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@qwik-ui/headless': patch
3+
---
4+
5+
Added a new contributing guide in the docs! /docs/headless/contributing

.github/actions/test/action.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,9 @@ runs:
5959
# - name: Codecov upload
6060
# uses: codecov/codecov-action@v2
6161

62-
- name: Lint PR
63-
if: github.event_name == 'pull_request'
64-
shell: bash
65-
run: pnpm danger ci --use-github-checks --failOnErrors -d .dangerfile.ts
66-
env:
67-
DANGER_GITHUB_API_TOKEN: ${{ inputs.github_token }}
62+
# - name: Lint PR
63+
# if: github.event_name == 'pull_request'
64+
# shell: bash
65+
# run: pnpm danger ci --use-github-checks --failOnErrors -d .dangerfile.ts
66+
# env:
67+
# DANGER_GITHUB_API_TOKEN: ${{ inputs.github_token }}

apps/website/e2e/example.spec.ts

Lines changed: 0 additions & 8 deletions
This file was deleted.

apps/website/playwright.config.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const baseURL = process.env['BASE_URL'] || 'http://localhost:5173';
1616
* See https://playwright.dev/docs/test-configuration.
1717
*/
1818
export default defineConfig({
19-
...nxE2EPreset(__filename, { testDir: './e2e' }),
19+
...nxE2EPreset(__filename, { testDir: './src' }),
2020
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
2121
use: {
2222
baseURL,
@@ -37,15 +37,15 @@ export default defineConfig({
3737
use: { ...devices['Desktop Chrome'] },
3838
},
3939

40-
{
41-
name: 'firefox',
42-
use: { ...devices['Desktop Firefox'] },
43-
},
40+
// {
41+
// name: 'firefox',
42+
// use: { ...devices['Desktop Firefox'] },
43+
// },
4444

45-
{
46-
name: 'webkit',
47-
use: { ...devices['Desktop Safari'] },
48-
},
45+
// {
46+
// name: 'webkit',
47+
// use: { ...devices['Desktop Safari'] },
48+
// },
4949

5050
// Uncomment for mobile browsers support
5151
/* {

apps/website/src/routes/docs/headless/contributing/index.mdx

Lines changed: 91 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,11 +104,99 @@ Tests ensure we can sleep sound at night and know that our component behavior is
104104
- get the test passing by adding said feature!
105105
- enjoy life when refactoring 🏝️
106106

107-
We currently use [playwright](https://playwright.dev/docs/intro) for testing.
107+
We strongly recommend TDD development for the headless library, and we are currently in the process of a playwright integration.
108108

109-
> We also currently have a few cypress tests that we are migrating over to playwright.
109+
Currently, the component testing integration for Qwik & Playwright is in development, and we are using e2e tests for the time being. That said, most tests should be very easy to migrate later on.
110110

111-
Shai also has a testing course that Qwik UI contributors get access to for the price of **FREE**! Don't hesitate to reach out.
111+
#### Getting started w/ testing
112+
113+
Here's an example way of getting a testid of the `Hero` select docs example in `index.mdx`, without affecting any visible markup.
114+
115+
```tsx
116+
<div data-testid="select-hero-test">
117+
<Showcase name="hero" />
118+
</div>
119+
```
120+
121+
Then, we get our testDriver, you can think of it as reusable code we use throughout the test. For example, in the Select component we constantly grab the listbox, trigger, etc.
122+
123+
```tsx
124+
import { Locator, Page } from '@playwright/test';
125+
126+
export type DriverLocator = Locator | Page;
127+
128+
export function selectTestDriver<T extends DriverLocator>(locator: T) {
129+
const getRoot = () => {
130+
return locator.getByRole('combobox');
131+
};
132+
133+
return {
134+
...locator,
135+
locator,
136+
getRoot,
137+
getListbox() {
138+
return getRoot().getByRole('listbox');
139+
},
140+
getTrigger() {
141+
return getRoot().getByRole('button');
142+
},
143+
// get all options
144+
getOptions() {
145+
return getRoot().getByRole('option').all();
146+
},
147+
};
148+
}
149+
```
150+
151+
Now we can write some tests:
152+
153+
```tsx
154+
import { test, expect } from '@playwright/test';
155+
import { selectTestDriver } from './select.driver';
156+
157+
test.beforeEach(async ({ page }) => {
158+
await page.goto('/docs/headless/select');
159+
});
160+
161+
test.describe('critical functionality', () => {
162+
test(`GIVEN a basic select
163+
WHEN clicking on the trigger
164+
THEN open up the listbox
165+
AND aria-expanded should be true`, async ({ page }) => {
166+
const testDriver = selectTestDriver(page.getByTestId('select-hero-test'));
167+
168+
const { getListbox, getTrigger } = testDriver;
169+
170+
await getTrigger().click();
171+
172+
await expect(getListbox()).toBeVisible();
173+
await expect(getTrigger()).toHaveAttribute('aria-expanded', 'true');
174+
});
175+
176+
test(`GIVEN a basic select
177+
WHEN focusing the trigger and hitting enter
178+
THEN open up the listbox
179+
AND aria-expanded should be true`, async ({ page }) => {
180+
const testDriver = selectTestDriver(page.getByTestId('select-hero-test'));
181+
182+
const { getListbox, getTrigger } = testDriver;
183+
184+
await getTrigger().focus();
185+
await page.keyboard.press('Enter');
186+
187+
await expect(getListbox()).toBeVisible();
188+
await expect(getTrigger()).toHaveAttribute('aria-expanded', 'true');
189+
});
190+
});
191+
```
192+
193+
To run the tests, use the `pnpm playwright` (only in my branch) command, or the `nx e2e website` longform. You can also do `--ui` to open the UI mode (which is pretty awesome!)
194+
195+
> This example is in `spec.select.tsx` in the `src/components/select` folder of the website.
196+
197+
Once we've added a failing test with what we expect, we can now go ahead and implement the feature for that!
198+
199+
Heads up, I (Jack) am also relatively new to playwright myself 😅. I'm guessing there is a way to not need the testDriver to be consumed on each test. Feel free to experiment!
112200

113201
## Docs
114202

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { component$, useSignal } from '@builder.io/qwik';
2+
import {
3+
Select,
4+
SelectListbox,
5+
SelectOption,
6+
SelectTrigger,
7+
SelectValue,
8+
} from '@qwik-ui/headless';
9+
10+
export default component$(() => {
11+
const usersSig = useSignal<string[]>(['Tim', 'Ryan', 'Jim', 'Jessie', 'Abby']);
12+
13+
return (
14+
<Select class="relative min-w-40">
15+
<p>This one is the disabled</p>
16+
<SelectTrigger class="w-full border-2 border-dashed border-red-400">
17+
<SelectValue placeholder="Select an option" />
18+
</SelectTrigger>
19+
<SelectListbox class="absolute w-full border-2 border-dashed border-green-400 bg-slate-900 p-2">
20+
{usersSig.value.map((user, index) => (
21+
<SelectOption
22+
class="border-dashed border-blue-400 data-[highlighted]:border-2 data-[disabled]:bg-slate-600 data-[disabled]:opacity-30"
23+
key={user}
24+
disabled={index === 0 || index === usersSig.value.length - 1 ? true : false}
25+
>
26+
{user}
27+
</SelectOption>
28+
))}
29+
</SelectListbox>
30+
</Select>
31+
);
32+
});
Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,30 @@
1-
import { $, component$, useSignal, useTask$ } from '@builder.io/qwik';
2-
import { Select, SelectListbox, SelectOption, SelectTrigger } from '@qwik-ui/headless';
1+
import { component$, useSignal } from '@builder.io/qwik';
2+
import {
3+
Select,
4+
SelectListbox,
5+
SelectOption,
6+
SelectTrigger,
7+
SelectValue,
8+
} from '@qwik-ui/headless';
39

410
export default component$(() => {
5-
const mockUsers = ['Tim', 'Ryan', 'Jim'];
6-
const moreUsers = ['Carla', 'Rachel', 'Monica', 'Jessie', 'Abby'];
7-
8-
const usersSig = useSignal<string[]>([]);
9-
10-
useTask$(async () => {
11-
usersSig.value = mockUsers;
12-
});
13-
14-
const handleClick$ = $(() => {
15-
usersSig.value = [...usersSig.value, ...moreUsers];
16-
});
11+
const usersSig = useSignal<string[]>(['Tim', 'Ryan', 'Jim', 'Jessie', 'Abby']);
1712

1813
return (
19-
<div>
20-
<Select>
21-
<SelectTrigger>Trigger</SelectTrigger>
22-
<SelectListbox style={{ padding: '0px', margin: '0px', listStyle: 'none' }}>
23-
<SelectOption disabled>My option</SelectOption>
24-
{usersSig.value.map((user) => (
25-
<SelectOption key={user}>{user}</SelectOption>
26-
))}
27-
</SelectListbox>
28-
</Select>
29-
{/* somehow this adds more js on page load? / wakes up the framework? */}
30-
<button onClick$={handleClick$}>Add more!</button>
31-
</div>
14+
<Select class="relative min-w-40">
15+
<SelectTrigger class="w-full border-2 border-dashed border-red-400">
16+
<SelectValue placeholder="Select an option" />
17+
</SelectTrigger>
18+
<SelectListbox class="absolute w-full border-2 border-dashed border-green-400 bg-slate-900 p-2">
19+
{usersSig.value.map((user) => (
20+
<SelectOption
21+
class="border-dashed border-blue-400 data-[highlighted]:border-2"
22+
key={user}
23+
>
24+
{user}
25+
</SelectOption>
26+
))}
27+
</SelectListbox>
28+
</Select>
3229
);
3330
});
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { component$, useSignal } from '@builder.io/qwik';
2+
import {
3+
Select,
4+
SelectListbox,
5+
SelectOption,
6+
SelectTrigger,
7+
SelectValue,
8+
} from '@qwik-ui/headless';
9+
10+
export default component$(() => {
11+
const usersSig = useSignal<string[]>(['Tim', 'Ryan', 'Jim', 'Jessie', 'Abby']);
12+
13+
return (
14+
<Select value="Jessie" class="relative min-w-40">
15+
<SelectTrigger class="w-full border-2 border-dashed border-red-400">
16+
<SelectValue placeholder="Select an option" />
17+
</SelectTrigger>
18+
<SelectListbox class="absolute w-full border-2 border-dashed border-green-400 bg-slate-900 p-2">
19+
{usersSig.value.map((user) => (
20+
<SelectOption
21+
class="border-dashed border-blue-400 data-[highlighted]:border-2"
22+
key={user}
23+
>
24+
{user}
25+
</SelectOption>
26+
))}
27+
</SelectListbox>
28+
</Select>
29+
);
30+
});
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { component$, useSignal } from '@builder.io/qwik';
2+
import {
3+
Select,
4+
SelectListbox,
5+
SelectOption,
6+
SelectTrigger,
7+
SelectValue,
8+
} from '@qwik-ui/headless';
9+
10+
export default component$(() => {
11+
const usersSig = useSignal<string[]>(['Tim', 'Ryan', 'Jim', 'Jessie', 'Abby']);
12+
13+
return (
14+
<>
15+
<Select value="Jessi" class="relative min-w-40">
16+
<SelectTrigger class="w-full border-2 border-dashed border-red-400">
17+
<SelectValue placeholder="wrong value placeholder" />
18+
</SelectTrigger>
19+
<SelectListbox class="absolute w-full border-2 border-dashed border-green-400 bg-slate-900 p-2">
20+
{usersSig.value.map((user) => (
21+
<SelectOption
22+
class="border-dashed border-blue-400 data-[highlighted]:border-2"
23+
key={user}
24+
>
25+
{user}
26+
</SelectOption>
27+
))}
28+
</SelectListbox>
29+
</Select>
30+
</>
31+
);
32+
});

apps/website/src/routes/docs/headless/select/index.mdx

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,29 @@ import { statusByComponent } from '~/_state/component-statuses';
1010

1111
This element is used to create a drop-down list, it's often used in a form, to collect user input.
1212

13-
<Showcase name="hero" />
13+
## Hero
14+
15+
<div data-testid="select-hero-test">
16+
<Showcase name="hero" />
17+
</div>
18+
19+
## Disabled
20+
21+
<div data-testid="select-disabled-test">
22+
<Showcase name="disabled" />
23+
</div>
24+
25+
## Uncontrolled
26+
27+
<div data-testid="select-uncontrolled-test">
28+
<Showcase name="uncontrolled" />
29+
</div>
30+
31+
## Wrong Value
32+
33+
<div data-testid="select-wrong-value-test">
34+
<Showcase name="wrong-value" />
35+
</div>
1436

1537
## Building blocks
1638

0 commit comments

Comments
 (0)