|
1 | 1 | # Acceptance Tests
|
| 2 | +This folder contains the acceptance test project for the Slurry Infrastructure Grant web app. |
2 | 3 |
|
3 |
| -> Future Farming and Countryside Programme - Grants Frontend Acceptance Tests |
4 |
| -
|
5 |
| -This folder contains the acceptance tests for the FFC Grants service components. |
6 |
| - |
7 |
| -The framework is (Cucumber)[https://cucumber.io/] and (webdriver.io)[https://webdriver.io/] based, containerised, expandable and based on the actively maintained webdriver.io Cucumber boilerplate project. |
8 |
| - |
| 4 | +The framework used is WebdriverIO with Cucumber and the tests are containerised by default, running against a single browser (Chrome) |
| 5 | +. |
9 | 6 | ## Requirements
|
| 7 | +- Docker |
| 8 | +- Node |
| 9 | +- npm |
10 | 10 |
|
11 |
| -- Docker Desktop 2.2.0.3 (42716) or higher |
12 |
| -- Node version 12 (not compatible with v13) |
13 |
| - - if you have multiple versions of node, run `nvm use 12` to use version 12 for this alone |
14 |
| - |
15 |
| -# Quick start |
16 |
| - |
17 |
| -Docker is used to create a container for each of selenium-hub, chrome-browser and webdriver-cuke. |
18 |
| -* Selenium Hub allows concurrent execution of test cases |
19 |
| -* Chrome Browser is the browser specified in the configuration file `wdio.conf.js` by default |
20 |
| -* Webdriver.io along with Cucumber is this framework that defines the tests. |
21 |
| - |
22 |
| -## How to run the tests |
23 |
| - |
24 |
| -1. Set the root URL for the environment in the environment variable `TEST_ENVIRONMENT_ROOT_URL` |
25 |
| - |
26 |
| -2. If running against localhost, then no need to set `TEST_ENVIRONMENT_ROOT_URL` as it will default to `docker.host.internal:3000`. Instead make sure the application container is running with `docker-compose up --build` in the root folder of this repository |
27 |
| - |
28 |
| -3. From the directory containing the dockerfile run `docker-compose run --rm wdio-cucumber`. This will run an acceptance test against the FFC-Demo web service. |
29 |
| - |
30 |
| -4. The test reports will be output to `./html-reports`. Note that WSL users need to run `mkdir -m 777 html-reports`. Read more about report configuration in the [rpii/wdio-hmtl-reporter docs](https://github.com/rpii/wdio-html-reporter) |
31 |
| - |
32 |
| -5. Now you are ready to maintain, extend or write your own features in the `./acceptance/features` directory |
33 |
| - |
34 |
| -## How to write a test |
35 |
| - |
36 |
| -Tests are written in [Gherkin syntax](https://cucumber.io/docs/reference) |
37 |
| -that means that you write down what's supposed to happen in a real language. All test files are located in |
38 |
| -`./acceptance/features/*` and have the file ending `.feature`. You will already find some test files in that |
39 |
| -directory. They should demonstrate, how tests could look like. Just create a new file and write your first |
40 |
| -test. |
41 |
| - |
42 |
| -__myFirstTest.feature__ |
43 |
| -```gherkin |
44 |
| -Feature: |
45 |
| - In order to keep my product stable |
46 |
| - As a developer or product manager |
47 |
| - I want to make sure that everything works as expected |
| 11 | +## Running tests inside a container (default) |
| 12 | +Docker is used to create containers for both the tests themselves (`wdio-cucumber`) and the Selenium instance of Chrome (`chrome-browser`). |
48 | 13 |
|
49 |
| -Scenario: Check title of website after search |
50 |
| - Given I open the url "http://google.com" |
51 |
| - When I set "WebdriverIO" to the inputfield "#lst-ib" |
52 |
| - And I press "Enter" |
53 |
| - Then I expect that the title is "WebdriverIO - Google Search" |
54 |
| -
|
55 |
| -Scenario: Another test |
56 |
| - Given ... |
| 14 | +1. Provide the following environment variables in a `.env` file in this directory: |
57 | 15 |
|
58 | 16 | ```
|
59 |
| - |
60 |
| -This test opens the browser and navigates them to google.com to check if the title contains the search |
61 |
| -query after doing a search. As you can see, it is pretty simple and understandable for everyone. |
62 |
| - |
63 |
| -# Using tags |
64 |
| - |
65 |
| -If you want to run only specific tests you can mark your features with tags. These tags will be placed before each feature like so: |
66 |
| - |
67 |
| -```gherkin |
68 |
| -@Tag |
69 |
| -Feature: ... |
| 17 | +TEST_ENVIRONMENT_ROOT_URL |
| 18 | +
|
| 19 | +LOGIN_USERNAME |
| 20 | +LOGIN_PASSWORD |
| 21 | +
|
| 22 | +SHAREPOINT_TENANT_ID |
| 23 | +SHAREPOINT_CLIENT_ID |
| 24 | +SHAREPOINT_CLIENT_SECRET |
| 25 | +SHAREPOINT_HOSTNAME |
| 26 | +SHAREPOINT_SITE_PATH |
| 27 | +SHAREPOINT_DOCUMENT_LIBRARY |
| 28 | +SHAREPOINT_UPLOAD_FOLDER |
| 29 | +SHAREPOINT_WORKSHEET |
70 | 30 | ```
|
71 | 31 |
|
72 |
| -To run only the tests with specific tag(s) use the `--cucumberOpts.tagExpression=` parameter like so: |
| 32 | +2. For ARM architectures, change the image used for Chrome in `docker-compose.yaml`: |
73 | 33 |
|
74 |
| -```sh |
75 |
| -$ npx wdio wdio.conf.js --cucumberOpts.tagExpression='@Tag or @AnotherTag' |
76 | 34 | ```
|
| 35 | + selenium: |
| 36 | + image: selenium/standalone-chrome |
77 | 37 |
|
78 |
| -For more tag options please see the [Cucumber.js documentation](https://docs.cucumber.io/tag-expressions/) |
79 |
| - |
80 |
| -# Pending test |
| 38 | +CHANGES TO.. |
81 | 39 |
|
82 |
| -If you have failing or unimplemented tests you can mark them as "Pending" so they will get skipped. |
| 40 | + selenium: |
| 41 | + image: seleniarm/standalone-chromium |
| 42 | +``` |
83 | 43 |
|
84 |
| -```gherkin |
85 |
| -// skip whole feature file |
86 |
| -@Pending |
87 |
| -Feature: ... |
| 44 | +3. If running against `localhost` ensure the application container is running with `docker-compose up --build` from the root folder of this repository. |
88 | 45 |
|
89 |
| -// only skip a single scenario |
90 |
| -@Pending |
91 |
| -Scenario: ... |
92 |
| -``` |
| 46 | +4. From the `/test/acceptance` directory run `docker-compose run --build --rm wdio-cucumber`. This will run all acceptance tests. |
93 | 47 |
|
94 |
| -# Adding new steps and snippets |
| 48 | +5. HTML reports will be output to `./reports`. |
95 | 49 |
|
96 |
| -The predefined snippets allow you to do a lot of common things but you might need extra snippets which |
97 |
| -are better aligned with your aims. To do so you will find all step definitions in `./acceptance/steps`. They |
98 |
| -are separated in `given`, `when` and `then`. |
| 50 | +## Running tests outside a container |
| 51 | +To run the tests outside a container: |
99 | 52 |
|
100 |
| -You define your snippet using regular expressions. This is pretty powerful as it allows you to create complex |
101 |
| -sentences with multiple options. Everything that's within `"([^"]*)?"` gets captured and appended to the |
102 |
| -callback. The last argument is always a callback function that you need to call when your step is done. |
103 |
| -You can access the browser and your WebdriverIO instance with `browser`. |
104 |
| - |
105 |
| -To assert values this boilerplate project comes with a [Chai](http://chaijs.com/) integration. |
106 |
| - |
107 |
| -# Comments |
108 |
| - |
109 |
| -You can add additional descriptive comments in your feature files. |
| 53 | +1. Comment out `hostname` and `port` in `wdio.conf.js`, i.e.: |
| 54 | +```js |
| 55 | +exports.config = { |
| 56 | + //hostname: 'selenium', |
| 57 | + //port: 4444,``` |
| 58 | +``` |
| 59 | +2. Run `npm run test`, this will execute the following script defined in `package.json`: |
| 60 | +```pwsh |
| 61 | +npx wdio run ./wdio.conf.js |
| 62 | +``` |
110 | 63 |
|
111 |
| -```gherkin |
112 |
| -### |
113 |
| - This is a |
114 |
| - block comment |
115 |
| -### |
116 |
| -Feature: As a bystander |
117 |
| - I can watch bottles falling from a wall |
118 |
| - So that I can be mildly amused |
| 64 | +3. Run a specific test or tests with a tag: |
| 65 | +```pwsh |
| 66 | +npx wdio run ./wdio.conf.js --cucumberOpts.tags=@tag |
| 67 | +``` |
119 | 68 |
|
120 |
| -# This is a single line comment |
121 |
| -Scenario: check if username is present |
122 |
| - Given I login as "roboter" with password "test123" |
123 |
| - Then the username "roboter" should be present in the header |
| 69 | +## Running tests in parallel |
| 70 | +Tests can be run in parallel at feature file level by increasing the number of instances available to WebdriverIO in `wdio.conf.js', e.g.: |
| 71 | +```js |
| 72 | +maxInstances: 3, |
124 | 73 | ```
|
125 | 74 |
|
126 |
| -# List of predefined steps |
127 |
| - |
128 |
| -Check out all predefined snippets. You can see examples of how these can be used in [the webdriver.io cucumber-boilerplate `sampleSnippets.feature`](https://github.com/webdriverio/cucumber-boilerplate/blob/master/src/features/sampleSnippets.feature). |
129 |
| - |
130 |
| -## Given steps |
131 |
| - |
132 |
| -- `I open the (url|site) "([^"]*)?"` <br>Open a site in the current browser window/tab |
133 |
| -- `the element "([^"]*)?" is( not)* visible` <br>Check the (in)visibility of an element |
134 |
| -- `the element "([^"]*)?" is( not)* enabled` <br>Check if an element is (not) enabled |
135 |
| -- `the element "([^"]*)?" is( not)* selected` <br>Check if an element is (not) selected |
136 |
| -- `the checkbox "([^"]*)?" is( not)* checked` <br>Check if a checkbox is (not) checked |
137 |
| -- `there is (an|no) element "([^"]*)?" on the page` <br>Check if an element (does not) exist |
138 |
| -- `the title is( not)* "([^"]*)?"` <br>Check the title of the current browser window/tab |
139 |
| -- `the element "([^"]*)?" contains( not)* the same text as element "([^"]*)?"` <br>Compare the text of two elements |
140 |
| -- `the (button|element) "([^"]*)?"( not)* contains the text "([^"]*)?"` <br>Check if an element contains the given text |
141 |
| -- `the (button|element) "([^"]*)?"( not)* contains any text` <br>Check if an element does not contain any text |
142 |
| -- `the (button|element) "([^"]*)?" is( not)* empty` <br>Check if an element is empty |
143 |
| -- `the page url is( not)* "([^"]*)?"` <br>Check the url of the current browser window/tab |
144 |
| -- `the( css)* attribute "([^"]*)?" from element "([^"]*)?" is( not)* "([^"]*)?"` <br>Check the value of an element's (css) attribute |
145 |
| -- `the cookie "([^"]*)?" contains( not)* the value "([^"]*)?"` <br>Check the value of a cookie |
146 |
| -- `the cookie "([^"]*)?" does( not)* exist` <br>Check the existence of a cookie |
147 |
| -- `the element "([^"]*)?" is( not)* ([\d]+)px (broad|tall)` <br>Check the width/height of an element |
148 |
| -- `the element "([^"]*)?" is( not)* positioned at ([\d]+)px on the (x|y) axis` <br>Check the position of an element |
149 |
| -- `I have a screen that is ([\d]+) by ([\d]+) pixels` <br>Set the browser size to a given size |
150 |
| -- `I have closed all but the first (window|tab)` <br>Close all but the first browser window/tab |
151 |
| -- `a (alertbox|confirmbox|prompt) is( not)* opened` <br>Check if a modal is opened |
152 |
| - |
153 |
| -## Then steps |
154 |
| - |
155 |
| -- `I expect that the title is( not)* "([^"]*)?"` <br>Check the title of the current browser window/tab |
156 |
| -- `I expect that element "([^"]*)?" does( not)* appear exactly "([^"]*)?" times` <br>Checks that the element is on the page a specific number of times |
157 |
| -- `I expect that element "([^"]*)?" is( not)* visible` <br>Check if a certain element is visible |
158 |
| -- `I expect that element "([^"]*)?" becomes( not)* visible` <br>Check if a certain element becomes visible |
159 |
| -- `I expect that element "([^"]*)?" is( not)* within the viewport` <br>Check if a certain element is within the current viewport |
160 |
| -- `I expect that element "([^"]*)?" does( not)* exist` <br>Check if a certain element exists |
161 |
| -- `I expect that element "([^"]*)?"( not)* contains the same text as element "([^"]*)?"` <br>Compare the text of two elements |
162 |
| -- `I expect that (button|element) "([^"]*)?"( not)* contains the text "([^"]*)?"` <br>Check if an element or input field contains the given text |
163 |
| -- `I expect that (button|element) "([^"]*)?"( not)* contains any text` <br>Check if an element or input field contains any text |
164 |
| -- `I expect that (button|elementelement) "([^"]*)?" is( not)* empty` <br>Check if an element or input field is empty |
165 |
| -- `I expect that the url ( not)* contains "([^"]*)?"` <br>Check if the the URL of the current browser window/tab contains a certain string |
166 |
| -- `I expect that the url is( not)* "([^"]*)?"` <br>Check if the the URL of the current browser window/tab is a certain string |
167 |
| -- `I expect that the path is( not)* "([^"]*)?"` <br>Check if the path of the URL of the current browser window/tab is a certain string |
168 |
| -- `I expect the url to( not)* contain "([^"]*)?"` <br>Check if the URL of the current browser window/tab contains a certain string |
169 |
| -- `I expect that the( css)* attribute "([^"]*)?" from element "([^"]*)?" is( not)* "([^"]*)?"` <br>Check the value of an element's (css) attribute |
170 |
| -- `I expect that checkbox "([^"]*)?" is( not)* checked` <br>Check if a check-box is (not) checked |
171 |
| -- `I expect that element "([^"]*)?" is( not)* selected` <br>Check if an element is (not) selected |
172 |
| -- `I expect that element "([^"]*)?" is( not)* enabled` <br>Check if an element is (not) enabled |
173 |
| -- `I expect that cookie "([^"]*)?"( not)* contains "([^"]*)?"` <br>Check if a cookie with a certain name contains a certain value |
174 |
| -- `I expect that cookie "([^"]*)?"( not)* exists` <br>Check if a cookie with a certain name exist |
175 |
| -- `I expect that element "([^"]*)?" is( not)* ([\d]+)px (broad|tall)` <br>Check the width/height of an element |
176 |
| -- `I expect that element "([^"]*)?" is( not)* positioned at ([\d]+)px on the (x|y) axis` <br>Check the position of an element |
177 |
| -- `I expect that element "([^"]*)?" (has|does not have) the class "([^"]*)?"` <br>Check if an element has a certain class |
178 |
| -- `I expect a new (window|tab) has( not)* been opened` <br>Check if a new window/tab has been opened |
179 |
| -- `I expect the url "([^"]*)?" is opened in a new (tab|window)` <br>Check if a URL is opened in a new browser window/tab |
180 |
| -- `I expect that element "([^"]*)?" is( not)* focused` <br>Check if an element has the focus |
181 |
| -- `I wait on element "([^"]*)?"( for (\d+)ms)*( to( not)* (be checked|be enabled|be selected|be visible|contain a text|contain a value|exist))*` <br>Wait for an element to be checked, enabled, selected, visible, contain a certain value or text or to exist |
182 |
| -- `I expect that a (alertbox|confirmbox|prompt) is( not)* opened` <br>Check if a modal is opened |
183 |
| -- `I expect that a (alertbox|confirmbox|prompt)( not)* contains the text "$text"` <br>Check the text of a modal |
184 |
| - |
185 |
| -## When steps |
186 |
| - |
187 |
| -- `I (click|doubleclick) on the (link|button|element) "([^"]*)?"` <br>(Double)click a link, button or element |
188 |
| -- `I (add|set) "([^"]*)?" to the inputfield "([^"]*)?"` <br>Add or set the content of an input field |
189 |
| -- `I clear the inputfield "([^"]*)?"` <br>Clear an input field |
190 |
| -- `I drag element "([^"]*)?" to element "([^"]*)?"` <br>Drag an element to another element |
191 |
| -- `I submit the form "([^"]*)?"` <br>Submit a form |
192 |
| -- `I pause for (\d+)ms` <br>Pause for a certain number of milliseconds |
193 |
| -- `I set a cookie "([^"]*)?" with the content "([^"]*)?"` <br>Set the content of a cookie with the given name to the given string |
194 |
| -- `I delete the cookie "([^"]*)?"` <br>Delete the cookie with the given name |
195 |
| -- `I press "([^"]*)?"` <br>Press a given key. You’ll find all supported characters [here](https://w3c.github.io/webdriver/webdriver-spec.html#keyboard-actions). To do that, the value has to correspond to a key from the table. |
196 |
| -- `I (accept|dismiss) the (alertbox|confirmbox|prompt)` <br>Accept or dismiss a modal window |
197 |
| -- `I enter "([^"]*)?" into the prompt` <br>Enter a given text into a modal prompt |
198 |
| -- `I scroll to element "([^"]*)?"` <br>Scroll to a given element |
199 |
| -- `I close the last opened (window|tab)` <br>Close the last opened browser window/tab |
200 |
| -- `I focus the last opened (window|tab)` <br>Focus the last opened browser window/tab |
201 |
| -- `I log in to site with username "([^"]*)?" and password "([^"]*)?"` <br>Login to a site with the given username and password |
202 |
| -- `I select the (\d+)(st|nd|rd|th) option for element "([^"]*)?"` <br>Select an option based on it's index |
203 |
| -- `I select the option with the (name|value|text) "([^"]*)?" for element "([^"]*)?"` <br>Select an option based on its name, value or visible text |
204 |
| -- `I move to element "([^"]*)?"( with an offset of (\d+),(\d+))` <br>Move the mouse by an (optional) offset of the specified element |
| 75 | +## Running tests against multiple browsers |
| 76 | +Tests can be run against multiple browsers, currently only when running outside a container, by specifying additional capabilities together with more instances in `wdio.conf.js`: |
| 77 | +```js |
| 78 | +maxInstances: 10, |
| 79 | +capabilities: [ |
| 80 | + { acceptInsecureCerts: true, browserName: 'chrome' }, |
| 81 | + { acceptInsecureCerts: true, browserName: 'firefox' }, |
| 82 | + { acceptInsecureCerts: true, browserName: 'edge' } |
| 83 | +], |
| 84 | +``` |
0 commit comments