|
1 | | -# Quasar App Extension quasar-playwright |
| 1 | +# Quasar App Extension for Playwright Testing |
2 | 2 |
|
3 | | -_Be sure to change this readme as appropriate for your app extension._ |
| 3 | +This Quasar App Extension integrates [Playwright](https://playwright.dev) with Quasar Framework, providing a seamless testing experience for both end-to-end (E2E) and component testing. |
4 | 4 |
|
5 | | -_Think about the organization of this file and how the information will be beneficial to the user._ |
| 5 | +## Installation |
6 | 6 |
|
7 | | -> Add a short description of your App Extension. What does it do? How is it beneficial? Why would someone want to use it? |
| 7 | +```bash |
| 8 | +# any other package manager can be used |
| 9 | +yarn quasar ext add @quasar/testing-e2e-playwright |
| 10 | +``` |
| 11 | + |
| 12 | +## ESLint Configuration |
| 13 | + |
| 14 | +- We higly recommend that you set up ESLint in your project, and use it to lint your code. Apart from helping you catch potential bugs in your code, it will also catch some potential issues with your tests. For example, you might forget to `await` a test when you are supposed to and end up with a flaky test suite. |
| 15 | + |
| 16 | +### ESLint v9+ (Flat Config) |
| 17 | + |
| 18 | +For ESLint v9 and newer, add this to your `eslint.config.js`: |
| 19 | + |
| 20 | +```js |
| 21 | +import playwright from 'eslint-plugin-playwright'; |
| 22 | + |
| 23 | +export default [ |
| 24 | + // ... |
| 25 | + { |
| 26 | + ...playwright.configs['flat/recommended'], |
| 27 | + files: ['src/components/**/*.spec.ts', 'test/**/*.spec.ts'], |
| 28 | + rules: { |
| 29 | + ...playwright.configs['flat/recommended'].rules, |
| 30 | + // you might need to disable this rule if it's turned on to avoid `mount` being reported as unbound |
| 31 | + // '@typescript-eslint/unbound-method': 'off', |
| 32 | + }, |
| 33 | + }, |
| 34 | +]; |
| 35 | +``` |
| 36 | + |
| 37 | +### ESLint v8 and Earlier (Legacy Config) |
| 38 | + |
| 39 | +For ESLint versions earlier than v9, add this to your `.eslintrc.js` or `.eslintrc.json`: |
| 40 | + |
| 41 | +```js |
| 42 | +{ |
| 43 | + "overrides": [ |
| 44 | + { |
| 45 | + "files": ["src/components/**/*.spec.{js,ts}", "test/**/*.spec.{js,ts}"], |
| 46 | + "extends": "plugin:playwright/recommended", |
| 47 | + "rules": { |
| 48 | + // you might need to disable this rule if it's turned on to avoid `mount` being reported as unbound |
| 49 | + // "@typescript-eslint/unbound-method": "off" |
| 50 | + } |
| 51 | + } |
| 52 | + ] |
| 53 | +} |
| 54 | +``` |
| 55 | + |
| 56 | +For TypeScript projects using ESLint v8, you might also need to add the following to your `tsconfig.json`: |
| 57 | + |
| 58 | +```json |
| 59 | +{ |
| 60 | + "compilerOptions": { |
| 61 | + "types": ["node", "playwright", "@playwright/test"] |
| 62 | + } |
| 63 | +} |
| 64 | +``` |
| 65 | + |
| 66 | +--- |
| 67 | + |
| 68 | +This App Extension (AE) manages Quasar and Playwright integration for you, supporting both JavaScript and TypeScript projects. It provides specialized utilities for testing Quasar components and a simplified setup for both end-to-end (E2E) and component testing. |
| 69 | + |
| 70 | +## Included Utilities |
| 71 | + |
| 72 | +The extension comes with several custom utilities to simplify testing Quasar components: |
| 73 | + |
| 74 | +| Utility | Description | |
| 75 | +| ------------------------ | -------------------------------------------------------- | |
| 76 | +| `selectDate` | Selects a date in a QDate component | |
| 77 | +| `selectQSelectOption` | Selects options from a QSelect component | |
| 78 | +| `checkQuasarComponent` | Checks Quasar checkboxes, toggles, and radio buttons | |
| 79 | +| `uncheckQuasarComponent` | Unchecks Quasar checkboxes and toggles | |
| 80 | +| `expectQuasarChecked` | Asserts that a Quasar component is checked/unchecked | |
| 81 | +| `withinDialog` | Interacts with elements within a QDialog | |
| 82 | +| `withinMenu` | Interacts with elements within a QMenu | |
| 83 | +| `withinSelectMenu` | Interacts with options within a QSelect dropdown | |
| 84 | +| `expectColor` | Asserts the text color of an element | |
| 85 | +| `expectBackgroundColor` | Asserts the background color of an element | |
| 86 | +| `test` and `expect` | Custom test fixtures with enhanced coverage capabilities | |
8 | 87 |
|
9 | | -A Quasar playwright app extension |
| 88 | +See example usage in the test files created during installation. |
10 | 89 |
|
11 | | -# Install |
| 90 | +## Usage |
| 91 | + |
| 92 | +After installation, these scripts are added to your `package.json`: |
12 | 93 |
|
13 | 94 | ```bash |
14 | | -quasar ext add quasar-playwright |
| 95 | +# Run all tests |
| 96 | +npm run test |
| 97 | + |
| 98 | +# Run E2E tests with UI |
| 99 | +npm run test:e2e |
| 100 | + |
| 101 | +# Run E2E tests in CI mode |
| 102 | +npm run test:e2e:ci |
| 103 | + |
| 104 | +# Run component tests with UI (Vite only) |
| 105 | +npm run test:component |
| 106 | + |
| 107 | +# Run component tests in CI mode (Vite only) |
| 108 | +npm run test:component:ci |
| 109 | + |
| 110 | +# Show test report |
| 111 | +npm run test:report |
| 112 | + |
| 113 | +# Clear test artifacts |
| 114 | +npm run test:clear |
| 115 | + |
| 116 | +# Generate coverage report (when enabled) |
| 117 | +npm run coverage-report |
| 118 | +``` |
| 119 | + |
| 120 | +## Examples |
| 121 | + |
| 122 | +### Testing Quasar Button |
| 123 | + |
| 124 | +```ts |
| 125 | +import { |
| 126 | + test, |
| 127 | + expect, |
| 128 | +} from '@quasar/quasar-app-extension-testing-e2e-playwright'; |
| 129 | + |
| 130 | +test('clicks a button', async ({ page }) => { |
| 131 | + await page.goto('/'); |
| 132 | + await page.getByRole('button', { name: 'Click me' }).click(); |
| 133 | + await expect(page.locator('.result')).toContainText('Clicked!'); |
| 134 | +}); |
| 135 | +``` |
| 136 | + |
| 137 | +### Testing Date Picker |
| 138 | + |
| 139 | +```ts |
| 140 | +import { |
| 141 | + test, |
| 142 | + expect, |
| 143 | + selectDate, |
| 144 | +} from '@quasar/quasar-app-extension-testing-e2e-playwright'; |
| 145 | + |
| 146 | +test('selects a date', async ({ page }) => { |
| 147 | + await page.goto('/datepicker'); |
| 148 | + const datePicker = page.locator('.q-date'); |
| 149 | + await selectDate(datePicker, '2023/07/15'); |
| 150 | + await expect(page.locator('.selected-date')).toContainText('Jul 15, 2023'); |
| 151 | +}); |
| 152 | +``` |
| 153 | + |
| 154 | +### Testing Dialog |
| 155 | + |
| 156 | +```ts |
| 157 | +import { |
| 158 | + test, |
| 159 | + expect, |
| 160 | + withinDialog, |
| 161 | +} from '@quasar/quasar-app-extension-testing-e2e-playwright'; |
| 162 | + |
| 163 | +test('interacts with dialog', async ({ page }) => { |
| 164 | + await page.goto('/dialog'); |
| 165 | + await page.getByRole('button', { name: 'Open Dialog' }).click(); |
| 166 | + |
| 167 | + await withinDialog(page, async (dialog) => { |
| 168 | + await expect(dialog).toContainText('Confirm Action'); |
| 169 | + await dialog.getByRole('button', { name: 'OK' }).click(); |
| 170 | + }); |
| 171 | + |
| 172 | + await expect(page.locator('.result')).toBeVisible(); |
| 173 | +}); |
| 174 | +``` |
| 175 | + |
| 176 | +### Testing Form Controls |
| 177 | + |
| 178 | +```ts |
| 179 | +import { |
| 180 | + test, |
| 181 | + expect, |
| 182 | + checkQuasarComponent, |
| 183 | + uncheckQuasarComponent, |
| 184 | + expectQuasarChecked, |
| 185 | +} from '@quasar/quasar-app-extension-testing-e2e-playwright'; |
| 186 | + |
| 187 | +test('interacts with form controls', async ({ page }) => { |
| 188 | + await page.goto('/form'); |
| 189 | + |
| 190 | + const checkbox = page.locator('.q-checkbox'); |
| 191 | + await checkQuasarComponent(checkbox); |
| 192 | + await expectQuasarChecked(checkbox, true); |
| 193 | + |
| 194 | + await uncheckQuasarComponent(checkbox); |
| 195 | + await expectQuasarChecked(checkbox, false); |
| 196 | +}); |
| 197 | +``` |
| 198 | + |
| 199 | +## Component Testing |
| 200 | + |
| 201 | +Component testing is supported for Vite-based Quasar projects, allowing you to test Vue components in isolation. At the moment, we are not supporting component testing for Webpack-based projects. |
| 202 | + |
| 203 | +```ts |
| 204 | +import { |
| 205 | + test, |
| 206 | + expect, |
| 207 | +} from '@quasar/quasar-app-extension-testing-e2e-playwright/ct'; |
| 208 | +import MyButton from '../MyButton.vue'; |
| 209 | + |
| 210 | +test('renders button with label', async ({ mount }) => { |
| 211 | + const component = await mount(MyButton, { |
| 212 | + props: { label: 'Click Me' }, |
| 213 | + }); |
| 214 | + |
| 215 | + await expect(component).toContainText('Click Me'); |
| 216 | + await component.click(); |
| 217 | + // Test component behavior... |
| 218 | +}); |
| 219 | +``` |
| 220 | + |
| 221 | +For Quasar-specific components in component testing mode: |
| 222 | + |
| 223 | +```ts |
| 224 | +import { |
| 225 | + test, |
| 226 | + expect, |
| 227 | + selectQSelectOption, |
| 228 | +} from '@quasar/quasar-app-extension-testing-e2e-playwright/ct'; |
| 229 | +import QSelectWrapper from '../QSelectWrapper.vue'; |
| 230 | + |
| 231 | +test('selects an option', async ({ mount }) => { |
| 232 | + const component = await mount(QSelectWrapper); |
| 233 | + await selectQSelectOption(component, 'Option 1'); |
| 234 | + // Test component behavior... |
| 235 | +}); |
15 | 236 | ``` |
16 | 237 |
|
17 | | -Quasar CLI will retrieve it from the NPM registry and install the extension to your project. |
| 238 | +## Code Coverage |
| 239 | + |
| 240 | +When enabled during installation, code coverage is automatically configured for Vite-based projects using Istanbul. The implementation: |
| 241 | + |
| 242 | +- Instruments your code automatically during development/testing |
| 243 | +- Collects coverage data during test execution |
| 244 | +- Works with both E2E and component tests |
| 245 | +- Combines results from different test types for unified reporting |
| 246 | + |
| 247 | +### Running with Coverage |
18 | 248 |
|
19 | | -## Prompts |
| 249 | +Coverage data is collected automatically when running tests with the CI commands: |
20 | 250 |
|
21 | | -> Explain the prompts here |
| 251 | +```bash |
| 252 | +# Run E2E tests with coverage |
| 253 | +npm run test:e2e:ci |
| 254 | + |
| 255 | +# Run component tests with coverage |
| 256 | +npm run test:component:ci |
| 257 | + |
| 258 | +# Run both for combined coverage |
| 259 | +npm run test |
| 260 | +``` |
22 | 261 |
|
23 | | -# Uninstall |
| 262 | +After test execution, generate a comprehensive report with: |
24 | 263 |
|
25 | 264 | ```bash |
26 | | -quasar ext remove quasar-playwright |
| 265 | +npm run coverage-report |
27 | 266 | ``` |
28 | 267 |
|
29 | | -# Info |
| 268 | +### Coverage Reports |
30 | 269 |
|
31 | | -> Add longer information here that will help the user of your app extension. |
| 270 | +The generated reports will be available in the `coverage` directory in multiple formats: |
32 | 271 |
|
33 | | -# Other Info |
| 272 | +- **HTML**: Interactive browser-based report (`coverage/index.html`) |
| 273 | +- **Text**: Command-line summary |
| 274 | +- **LCOV**: Standard format for CI integrations |
34 | 275 |
|
35 | | -> Add other information that's not as important to know |
| 276 | +### Customization |
36 | 277 |
|
37 | | -# Donate |
| 278 | +The extension provides a sensible default configuration that extends the Istanbul preset. You can customize coverage settings by: |
38 | 279 |
|
39 | | -If you appreciate the work that went into this App Extension, please consider [donating to Quasar](https://donate.quasar.dev). |
| 280 | +1. Modifying the `.nycrc` file in your project root |
| 281 | +2. Adjusting the environment variables in your `package.json` scripts |
| 282 | +3. Creating a custom NYC configuration |
40 | 283 |
|
41 | | -# Dialog |
| 284 | +## Configuration Options |
42 | 285 |
|
43 | | -Require `nextTick` |
| 286 | +During installation, you'll be prompted to configure: |
44 | 287 |
|
45 | | -# Eslint |
| 288 | +- **Port**: The port to use for serving the app during tests (default: 8080) |
| 289 | +- **GitHub Workflow**: Add a GitHub workflow configuration for CI |
| 290 | +- **Install Browsers**: Install Playwright browsers automatically. On Linux, it works only on Debian-based distros. You might still be able to install browsers on other Linux distros with some tweaking which is out of the scope of this documentation. |
| 291 | +- **Code Coverage**: Enable code coverage reporting (Vite only) |
46 | 292 |
|
47 | | -```js |
48 | | - { |
49 | | - ...playwright.configs['flat/recommended'], |
50 | | - files: ['src/components/**/*.spec.ts', 'test/**/*.spec.ts'], |
51 | | - rules: { |
52 | | - ...playwright.configs['flat/recommended'].rules, |
53 | | - '@typescript-eslint/unbound-method': 'off', |
54 | | - }, |
55 | | - }, |
| 293 | +## Tips |
| 294 | + |
| 295 | +- When testing QDialog components in component tests, you might notice a random error about navigation context being changed during component mount. Here's an explanation and workaround for that: |
| 296 | + |
| 297 | +```ts |
| 298 | +onMounted(async () => { |
| 299 | + // When rendering a dialog immediately when the component is mounted, we need to wait for the next tick, otherwise it will break the test. Apparently, rendering the dialog immediately |
| 300 | + // interfers with component mount context. This mostly occurs when running individual tests that immediately render a dialog and rarely when running all tests at once. |
| 301 | + // It throws: "Error: page._wrapApiCall: Execution context was destroyed, most likely because of a navigation." |
| 302 | + // This is only needed to make Playwright tests that display the dialog immediately after mounting the component pass. If a dialog is not displayed immediately the component renders then you don't need this. |
| 303 | + await nextTick(); |
| 304 | + |
| 305 | + Dialog.create({ |
| 306 | + component: props.component, |
| 307 | + }); |
| 308 | +}); |
| 309 | +``` |
| 310 | + |
| 311 | +## Uninstallation |
| 312 | + |
| 313 | +```bash |
| 314 | +quasar ext remove @quasar/testing-e2e-playwright |
56 | 315 | ``` |
| 316 | + |
| 317 | +## Documentation |
| 318 | + |
| 319 | +For more details: |
| 320 | + |
| 321 | +- [Playwright Documentation](https://playwright.dev/docs/intro) |
| 322 | +- [Quasar Framework](https://quasar.dev) |
| 323 | + |
| 324 | +## Donate |
| 325 | + |
| 326 | +If you appreciate this extension, please consider [donating to Quasar](https://donate.quasar.dev). |
0 commit comments