Skip to content

Commit

Permalink
chore: Enable code coverage for cypress tests (#10602)
Browse files Browse the repository at this point in the history
  • Loading branch information
pskelin authored Jan 22, 2025
1 parent bebd1cf commit a1aaa74
Show file tree
Hide file tree
Showing 8 changed files with 588 additions and 45 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ dist
**/test/test-elements/generated
.dev-server-port

# Code coverage
coverage
.nyc_output

# scoping feature generated entry points for vite consumption
packages/compat/test/pages/scoped
packages/main/test/pages/scoped
Expand Down
65 changes: 39 additions & 26 deletions docs/4-development/10-testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
The test framework of choice for UI5 Web Components is [WebdriverIO](https://webdriver.io/) or WDIO for short.
It has a straightforward API - [https://webdriver.io/docs/api.html](https://webdriver.io/docs/api.html), and has excellent support for Web Components.

The browser of choice for test execution is [Google Chrome](https://www.google.com/chrome/), respectively the WebDriver used is [ChromeDriver](https://chromedriver.chromium.org/).
The browser of choice for test execution is [Google Chrome](https://www.google.com/chrome/), respectively the WebDriver used is [ChromeDriver](https://chromedriver.chromium.org/).

### Prerequisites

Expand All @@ -16,24 +16,24 @@ You can install it with `npm`:
- `npm i --save-dev chromedriver`

or with `yarn`:
- `yarn add -D chromedriver`
- `yarn add -D chromedriver`

**Note:** Google Chrome and ChromeDriver need to be the same version to work together. Whenever you update Google Chrome on
your system (or it updates automatically, if allowed), you are expected to also update ChromeDriver to the respective version.

### Running the tests

#### 1. Test configuration
#### 1. Test configuration

The configuration for WDIO can be found in the `config/` directory under `wdio.conf.js`.

As explained [here](./01-package.md) in the section about the `config/` directory, you can
As explained [here](./01-package.md) in the section about the `config/` directory, you can
customize, or even completely replace the default configuration.

However, before doing so, please note the following two benefits of working with the default configuration, provided by UI5 Web Components:
- Hooks, synchronizing the execution of all relevant WDIO commands (e.g. `click`, `url`, `$`, `$$`) with the rendering of the framework to
- Hooks, synchronizing the execution of all relevant WDIO commands (e.g. `click`, `url`, `$`, `$$`) with the rendering of the framework to
ensure consistency when reading or changing the state of the components.
- Additional API methods: `setProperty`, `setAttribute`, `removeAttribute`, `hasClass`.
- Additional API methods: `setProperty`, `setAttribute`, `removeAttribute`, `hasClass`.

So our recommendation would be to modify it, if necessary, but not completely replace it.

Expand Down Expand Up @@ -74,7 +74,7 @@ describe("ui5-demo rendering", async () => {
assert.ok(innerContent, "content rendered");
});
});
```
```

Key points:
- Load the test page with the `browser.url` command. You can do this once for each test suite or for each individual test.
Expand All @@ -87,7 +87,7 @@ Key points:

For WDIO capabilities, see:
- Official API: [https://webdriver.io/docs/api.html](https://webdriver.io/docs/api.html).
- Additional commands provided in our standard WDIO configuration: `setProperty`, `setAttribute`, `removeAttribute`, `hasClass`.
- Additional commands provided in our standard WDIO configuration: `setProperty`, `setAttribute`, `removeAttribute`, `hasClass`.

**Note:** The standard WDIO configuration we provide automatically synchronizes all test commands' execution with the framework rendering cycle.
Therefore, in the example above, the `shadow$` command will internally wait for all rendering to be over before being executed. The
Expand All @@ -100,19 +100,19 @@ Debugging with WDIO is really simple. Just follow these 3 steps:
1. Change the WDIO configuration file `config/wdio.conf.js` to disable `headless` mode for Google Chrome as follows:

From:

```js
module.exports = require("@ui5/webcomponents-tools/components-package/wdio.js");
```

to:

```js
const result = require("@ui5/webcomponents-tools/components-package/wdio.js");
result.config.capabilities[0]["goog:chromeOptions"].args = ['--disable-gpu']; // From: ['--disable-gpu', '--headless']
module.exports = result;
```

If you happen to debug often, it's recommended to keep the file in this format and just comment out the middle line when you're done debugging.

2. Set a breakpoint with `browser.debug` somewhere in your test:
Expand All @@ -124,29 +124,29 @@ Debugging with WDIO is really simple. Just follow these 3 steps:
assert.ok(innerContent, "content rendered");
});
```

For more on `debug`, see [https://webdriver.io/docs/api/browser/debug.html](https://webdriver.io/docs/api/browser/debug.html).

3. Run the single test spec and wait for the browser to open and pause on your breakpoint:

- Run the dev server, if you haven't already:
`yarn start`
or

`yarn start`

or

`npm run start`.

- Run the single test spec:
`yarn test test/specs/Demo.spec.js`
or

`yarn test test/specs/Demo.spec.js`

or

`npm run test test/specs/Demo.spec.js`.
Google Chrome will then open in a new window, controlled by WDIO via the ChromeDriver, and your test will pause on your
breakpoint of choice. Proceed to debug normally.

Google Chrome will then open in a new window, controlled by WDIO via the ChromeDriver, and your test will pause on your
breakpoint of choice. Proceed to debug normally.

### Best practices for writing tests

Expand Down Expand Up @@ -174,7 +174,7 @@ Use:
Preferred:
```js
assert.ok(await browser.$(<SELECTOR>).isExisting())
```
```

instead of:

Expand Down Expand Up @@ -433,3 +433,16 @@ describe("My Component Tests", () => {
});
```


### Code coverage

Cypress tests automatically run with instrumentation switched on. To see the code coverage report, run the following commands:
```sh
# build the project
yarn build
# run the tests for a pacakge
cd packages/main
yarn test:cypress
# start a static server in the `coverage` folder and inspect the results in the browser
http-server coverage
```
5 changes: 5 additions & 0 deletions packages/tools/components-package/cypress.config.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
const { defineConfig } = require('cypress')
const path = require("path");
const coverageTask = require('@cypress/code-coverage/task');

module.exports = defineConfig({
component: {
setupNodeEvents(on, config) {
coverageTask(on, config)
return config
},
supportFile: path.join(__dirname, "cypress/support/component.js"),
indexHtmlFile: path.join(__dirname, "cypress/support/component-index.html"),
specPattern: ["**/specs/*.cy.{js,ts}", "**/specs/**/*.cy.{js,ts}"],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import '@cypress/code-coverage/support'
import { setupHooks } from '@cypress/mount-utils';
import { unsafeHTML } from 'lit-html/directives/unsafe-html.js';
import { mount } from 'cypress-ct-lit'
Expand Down
4 changes: 2 additions & 2 deletions packages/tools/components-package/nps.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,8 @@ const getScripts = (options) => {
},
start: "nps prepare watch.devServer",
test: `node "${LIB}/test-runner/test-runner.js"`,
"test-cy-ci": `yarn cypress run --component --browser chrome`,
"test-cy-open": `yarn cypress open --component --browser chrome`,
"test-cy-ci": `CYPRESS_COVERAGE=true yarn cypress run --component --browser chrome`,
"test-cy-open": `CYPRESS_COVERAGE=true yarn cypress open --component --browser chrome`,
"test-suite-1": `node "${LIB}/test-runner/test-runner.js" --suite suite1`,
"test-suite-2": `node "${LIB}/test-runner/test-runner.js" --suite suite2`,
startWithScope: "nps scope.prepare scope.watchWithBundle",
Expand Down
2 changes: 2 additions & 0 deletions packages/tools/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
},
"dependencies": {
"@custom-elements-manifest/analyzer": "^0.8.4",
"@cypress/code-coverage": "^3.13.10",
"@typescript-eslint/eslint-plugin": "^6.9.0",
"@typescript-eslint/parser": "^6.9.0",
"@wdio/cli": "^7.19.7",
Expand Down Expand Up @@ -70,6 +71,7 @@
"rimraf": "^3.0.2",
"slash": "3.0.0",
"vite": "^5.4.8",
"vite-plugin-istanbul": "^6.0.2",
"wdio-chromedriver-service": "^7.3.2"
},
"peerDependencies": {
Expand Down
11 changes: 9 additions & 2 deletions vite.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import customHotUpdate from "@ui5/webcomponents-tools/lib/dev-server/custom-hot-
import path, { dirname, join, resolve } from 'path';
import tsconfigPaths from 'vite-tsconfig-paths';
import { checker } from 'vite-plugin-checker';
import istanbul from 'vite-plugin-istanbul';

// use after path.join and path.resolve as they turn paths to windows separators and comparisons and replacements stop working
const toPosixPath = (pathStr) => {
Expand Down Expand Up @@ -98,7 +99,6 @@ const customResolver = (id, source, options) => {
return resolved;
}
}

export default defineConfig(async () => {
return {
build: {
Expand All @@ -114,7 +114,14 @@ export default defineConfig(async () => {
tsconfigPath: "packages/fiori/tsconfig.json",
buildMode: true,
}
})
}),
istanbul({
include: ['packages/**/src/*','src/*'],
exclude: ['node_modules', 'test/'],
extension: ['.js', '.ts', '.tsx'],
requireEnv: true,
cypress: true,
}),
],
resolve: {
alias: [
Expand Down
Loading

0 comments on commit a1aaa74

Please sign in to comment.