2021-02-03 09:17:13 +03:00
# End-to-End Testing
2020-02-12 02:16:48 +03:00
2021-02-03 09:17:13 +03:00
## e2e-test-app project structure
2020-02-12 02:16:48 +03:00
2021-02-03 09:17:13 +03:00
A test app, test library and test cases are in [`/packages/e2e-test-app/` ](../packages/e2e-test-app ), and are organized as below.
2020-02-12 02:16:48 +03:00
2021-02-02 07:16:49 +03:00
- `test` – includes Jest tests using webdriverio
- `windows` – the UWP native app
- `jest.config.js` – configuration for Jest and WebDriverIO
2020-02-12 02:16:48 +03:00
2021-02-02 07:16:49 +03:00
## Running Tests
2020-02-12 02:16:48 +03:00
2021-02-02 07:16:49 +03:00
**Install [WinAppDriver v1.2.1 ](https://github.com/microsoft/WinAppDriver/releases/download/v1.2.1/WindowsApplicationDriver_1.2.1.msi )**
2020-02-12 02:16:48 +03:00
2021-02-02 07:16:49 +03:00
This will be automatically done for you if you use the [RNW dependency script ](https://microsoft.github.io/react-native-windows/docs/rnw-dependencies ) with `rnwDev` as an argument.
2020-02-12 02:16:48 +03:00
2021-02-26 02:31:55 +03:00
The E2E tests assume it is installed in the default location under `C:\Program Files (x86)\Windows Application Driver\WinAppDriver.exe` . If you choose a different path, you will need to specify it in [`/packages/e2e-test-app/jest.config.js` ](../packages/e2e-test-app/jest.config.js ).
```js
module.exports = {
...
testEnvironmentOptions: {
...
winAppDriverBin: 'D:\\Program Files (x86)\\Windows Application Driver\\WinAppDriver.exe',
},
};
```
2020-02-12 02:16:48 +03:00
2021-02-02 07:16:49 +03:00
**Build the native test app**
2020-02-12 02:16:48 +03:00
2021-02-03 09:17:13 +03:00
> C:\repo\react-native-windows> `cd packages\e2e-test-app`
2021-02-02 07:16:49 +03:00
>
2021-02-03 09:17:13 +03:00
> C:\repo\react-native-windows\packages\e2e-test-app> `yarn windows --no-launch`
2020-02-12 02:16:48 +03:00
2021-02-02 07:16:49 +03:00
**Running all tests**
2020-02-12 02:16:48 +03:00
2022-04-01 01:07:43 +03:00
> C:\repo\react-native-windows\packages\e2e-test-app> `yarn start`
>
2021-02-03 09:17:13 +03:00
> C:\repo\react-native-windows\packages\e2e-test-app> `yarn e2etest`
2020-02-12 02:16:48 +03:00
2021-03-05 01:46:29 +03:00
2021-02-02 07:16:49 +03:00
**Running a specific test**
2020-02-12 02:16:48 +03:00
2022-04-01 01:07:43 +03:00
> C:\repo\react-native-windows\packages\e2e-test-app> `yarn start`
>
2021-07-20 20:14:36 +03:00
⚠ Only the test filename (without the rest of the path) should be included.
> C:\repo\react-native-windows\packages\e2e-test-app> `yarn e2etest visitAllPages.test.ts`
2020-02-12 02:16:48 +03:00
2021-11-08 22:59:37 +03:00
**Break on app start**
2022-04-01 01:07:43 +03:00
> C:\repo\react-native-windows\packages\e2e-test-app> `yarn start`
>
2021-11-08 22:59:37 +03:00
> C:\repo\react-native-windows\packages\e2e-test-app> `yarn e2etest:debug visitAllPages.test.ts`
2021-02-02 07:16:49 +03:00
## Debugging E2E Tests in CI
### Increasing verbosity
2021-02-03 09:17:13 +03:00
By default the only messages printed during tests are related to errors returned by WinAppDriver or assertion failures. It is possible to increase verbosity to show individual WebDriver wire commands by editing [`/packages/e2e-test-app/jest.config.js` ](../packages/e2e-test-app/jest.config.js ).
2020-02-12 02:16:48 +03:00
2021-02-02 07:16:49 +03:00
```js
module.exports = {
...
testEnvironmentOptions: {
...
webdriverOptions: {
// Level of logging verbosity: trace | debug | info | warn | error
logLevel: 'error',
...
},
},
};
```
2020-02-12 02:16:48 +03:00
2021-02-02 07:16:49 +03:00
### Test Artifacts
2020-02-12 02:16:48 +03:00
2021-02-02 07:16:49 +03:00
If you have access to the AzureDevOps pipeline you'll be able to see test failures and debug crashes.
Here are the artifacts that are produced during the build:
- error screenshots of the app when a test failed
- test run XML - this contains some information like the name of the wdio test that failed and the JS stack
2021-05-25 00:40:26 +03:00
- tree dump outputs - you can compare these to the output of the main branch to see if there is a the difference responsible for the test failing.
2021-09-03 21:37:34 +03:00
- crash dumps of the e2e test app (RNTesterApp)
2020-02-12 02:16:48 +03:00
2021-02-02 07:16:49 +03:00
You can access these by going to the AzureDevOps run for your PR and clicking on the artifacts link:
2020-02-12 02:16:48 +03:00
2021-02-02 07:16:49 +03:00
![Artifacts ](img/e2e-artifacts.png )
2020-02-12 02:16:48 +03:00
2021-02-02 07:16:49 +03:00
## Architecture
2020-02-12 02:16:48 +03:00
2021-02-02 07:16:49 +03:00
### WinAppDriver
2020-02-12 02:16:48 +03:00
2021-02-02 07:16:49 +03:00
WinAppDriver uses [UIA ](https://docs.microsoft.com/en-us/windows/uwp/design/accessibility/accessibility-testing ) to
inspect and manipulate a test application, allowing clients to connect to it using the w3c WebDriver protocol.
2020-02-12 02:16:48 +03:00
2021-02-02 07:16:49 +03:00
### WebDriverIO
2020-02-12 02:16:48 +03:00
2022-04-01 01:07:43 +03:00
WebDriverIO is a JavaScript library which connects to WinAppDriver using the WebDriver protocol. It provides [global
APIs](https://webdriver.io/docs/api) for querying the application UI tree such as selectors (see below) and a global `browser` object to manipulate the
2021-02-02 07:16:49 +03:00
test application.
2020-02-12 02:16:48 +03:00
2021-02-02 07:16:49 +03:00
### Jest
2020-02-12 02:16:48 +03:00
2021-02-03 09:17:13 +03:00
Jest is the test runner used for end-to-end testing, including assertsion libraries, test selection, etc. WebDriverIO setup is
2021-09-03 01:49:45 +03:00
provided by a custom environment [`@react-native-windows/automation` ](../packages/@react-native-windows/automation ).
2021-02-02 07:16:49 +03:00
## Authoring Tests
Tests are written using Jest and WebDriverIO (see more below) against a test app running `RNTester` . `RNTester` example
2021-02-03 09:17:13 +03:00
pages are used as Test UI, which is examined via Jest tests. Tests should attempt to target an existing `RNTester` page, but "Legacy" tests exist as custom pages only used by e2e-test-app
2020-02-12 02:16:48 +03:00
2021-02-02 07:16:49 +03:00
### Writing a test against an RNTester example page
2020-02-12 02:16:48 +03:00
2021-01-26 07:26:59 +03:00
```ts
2021-02-02 07:16:49 +03:00
// LegacyControlStyleTestPage.test.ts
2020-02-12 02:16:48 +03:00
2021-02-02 07:16:49 +03:00
describe('FancyWidget', () => {
2020-02-12 02:16:48 +03:00
2021-01-26 07:26:59 +03:00
beforeAll(async () => {
2021-02-02 07:16:49 +03:00
await goToComponentExample('FancyWidget');
2021-01-26 07:26:59 +03:00
});
2020-02-12 02:16:48 +03:00
2021-02-02 07:16:49 +03:00
test('FancyWidget is populated with placeholder', async () => {
// Query for an element with accessibilityId of "foo" (see "locators" below)
2021-09-02 08:24:18 +03:00
const field = await app.findElementByTestID('foo');
2021-02-02 07:16:49 +03:00
expect(await field.getText()).toBe('placeholder');
2021-01-26 07:26:59 +03:00
});
2020-02-12 02:16:48 +03:00
});
2020-07-08 04:08:08 +03:00
```
2019-09-14 17:07:30 +03:00
2021-02-02 07:16:49 +03:00
### Adding a custom RNTester page
2019-09-14 17:07:30 +03:00
2021-02-02 07:16:49 +03:00
Before adding a custom page, consider whether the change can be made to an existing RNTester page and upstreamed. If needed, new examples may be integrated into the Windows fork of RNTester, [`@react-native-windows/tester` ](../packages/@react-native-windows/tester ).
2019-09-14 17:07:30 +03:00
2021-10-19 23:22:40 +03:00
Hooks are recommended to author the test page. (see [https://reactjs.org/docs/hooks-intro.html ](https://reactjs.org/docs/hooks-intro.html ) and this [Pluralsight course ](https://www.pluralsight.com/courses/using-react-hooks ) to learn more about Hooks)
2019-09-14 17:07:30 +03:00
2021-02-02 07:16:49 +03:00
```js
// ControlStyleTestPage.tsx
export const title = 'LegacyControlStyleTest';
export const description = 'Legacy e2e test for Control Styles';
export const examples = [
2019-09-14 17:07:30 +03:00
{
2021-02-02 07:16:49 +03:00
render: function(): JSX.Element {
return < ControlStyleTestPage / > ;
2019-09-14 17:07:30 +03:00
},
2021-02-02 07:16:49 +03:00
},
];
2019-09-14 17:07:30 +03:00
```
2021-02-02 07:16:49 +03:00
```js
// RNTesterList.windows.js
...
{
key: 'LegacyControlStyleTest',
module: require('../examples-win/LegacyTests/ControlStyleTestPage'),
},
...
2019-09-14 17:07:30 +03:00
```
2021-02-13 01:22:16 +03:00
## Snapshot tests
2020-05-14 17:50:01 +03:00
2021-02-13 01:22:16 +03:00
E2ETests uses [snapshot tests ](https://jestjs.io/docs/en/snapshot-testing ) to detect unintended visual changes. Instead
of testing againt the react tree, e2e-test-app compares the fully rendered XAML tree. This allows testing the
correctness of ViewManagers.
2020-05-14 17:50:01 +03:00
2021-02-13 01:22:16 +03:00
```ts
2021-09-03 01:49:45 +03:00
import {dumpVisualTree} from '@react-native-windows/automation-commands';
2020-05-14 17:50:01 +03:00
2021-02-13 01:22:16 +03:00
test('Example test', async () => {
const dump = await dumpVisualTree('test-id-here');
expect(dump).toMatchSnapshot();
});
2020-05-14 17:50:01 +03:00
```
2021-02-13 01:22:16 +03:00
Snapshots can be updated by either:
1. Locally running `jest --updateSnapshot` .
2. Copying from the "shapshots" artifact uploaded from a failing PR
2020-05-14 17:50:01 +03:00
2020-05-14 01:42:03 +03:00
2020-10-31 01:34:13 +03:00