Skip to content

Commit 081531f

Browse files
authored
Merge pull request #146 from digital-analytics-program/feature/add_staging_tests
[Tech Debt] Update tests to be able to run against live staging/production environments
2 parents 0966123 + 4ce308e commit 081531f

11 files changed

Lines changed: 192 additions & 52 deletions

File tree

Dockerfile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
11
FROM nginx
2-
COPY test_site Universal-Federated-Analytics-Min.js Federated.js.map /usr/share/nginx/html/
2+
ARG DAP_ENV='dev'
3+
ENV DAP_ENV=${DAP_ENV}
4+
COPY test_site Universal-Federated-Analytics-Min.js Federated.js.map /usr/share/nginx/html/
5+
COPY nginx-test.conf.template /etc/nginx/conf.d/
6+
RUN envsubst '${DAP_ENV}' < /etc/nginx/conf.d/nginx-test.conf.template > /etc/nginx/conf.d/default.conf

README.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,10 +130,18 @@ npm run lint
130130
```
131131

132132
#### Run integration tests
133-
Start up the test site at http://localhost:8080/:
133+
134+
Start up the test site at http://localhost:8080/ with one of the following:
134135

135136
```bash
136-
npm run test-site
137+
# Using the local version of the DAP code
138+
npm run test-site-dev
139+
140+
# Using the staging environment version of the DAP code
141+
npm run test-site-stg
142+
143+
# Using the production environment version of the DAP code
144+
npm run test-site-prd
137145
```
138146

139147
Then run the tests against the test site:
@@ -142,4 +150,6 @@ Then run the tests against the test site:
142150
npm run cucumber
143151
```
144152

153+
See more details in the [testing docs](features/README.md).
154+
145155
**All members of the digital-analytics-program GitHub organization are required to have two-factor authentication enabled.**

features/README.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# DAP automated testing docs
2+
3+
The automated tests for the DAP code are implemented using [cucumber-js](https://github.com/cucumber/cucumber-js)
4+
and [puppeteer](https://pptr.dev/).
5+
6+
By default the tests use the local version of the DAP javascript files. Loading
7+
the code into a test HTML page, performing various user actions, and testing
8+
the behavior of the code in response to the user actions.
9+
10+
Use the `DAP_ENV` environment variable to insert live versions of the code into
11+
the test HTML page instead of the local version as described below.
12+
13+
## Running the tests
14+
15+
Start up the test site at http://localhost:8080/:
16+
17+
```bash
18+
npm run test-site
19+
```
20+
21+
Then run the tests against the test site:
22+
23+
```bash
24+
npm run cucumber
25+
```
26+
27+
## Running the tests with a debugger attached
28+
29+
```bash
30+
npm run cucumber:debug
31+
```
32+
33+
## Configuring with environment variables
34+
35+
### Verbose mode
36+
37+
Print debugging information to stdout while running the tests:
38+
39+
```bash
40+
VERBOSE=true npm run cucumber
41+
```
42+
43+
### Run tests against the live staging environment
44+
45+
```bash
46+
DAP_ENV=staging npm run cucumber
47+
```
48+
49+
### Run tests against the live production environment
50+
51+
```bash
52+
DAP_ENV=production npm run cucumber
53+
```

features/autotracker_download.feature

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,16 @@ Feature: Downloads are reported to DAP when autotracking is enabled
88
Given DAP is configured with autotracking enabled
99
When I load the test site
1010
And I click on a file to download it
11-
Then the file download is reported to DAP with interaction type "mouse click"
11+
Then the file download is reported to DAP with interaction type "Mouse Click"
1212

1313
Scenario: User presses Enter to download file with autotracker on
1414
Given DAP is configured with autotracking enabled
1515
When I load the test site
1616
And I highlight and press Enter on a file to download it
17-
Then the file download is reported to DAP with interaction type "enter key keystroke"
17+
Then the file download is reported to DAP with interaction type "Enter Key Keystroke"
1818

1919
Scenario: User clicks to download file with autotracker off
2020
Given DAP is configured with autotracking disabled
2121
When I load the test site
2222
And I click on a file to download it
23-
Then the file download is not reported to DAP
23+
Then the file download is not reported to DAP

features/support/step_definitions/browser_steps.js

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,18 @@ function delay(milliseconds) {
1212
Given("I load an empty browser", async function () {
1313
this.browser = await puppeteer.launch();
1414
this.page = await this.browser.newPage();
15+
16+
if (process.env.VERBOSE == 'true') {
17+
// Log page events to the node console
18+
this.page
19+
.on('console', message =>
20+
console.log(`${message.type().substr(0, 3).toUpperCase()} ${message.text()}`))
21+
.on('pageerror', ({ message }) => console.log(message))
22+
.on('response', response =>
23+
console.log(`${response.status()} ${response.url()}`))
24+
.on('requestfailed', request =>
25+
console.log(`${request.failure().errorText} ${request.url()}`))
26+
}
1527
});
1628

1729
Given("I set the browser to intercept outbound requests", async function () {
@@ -33,7 +45,7 @@ When("I wait {int} seconds", async function (delaySeconds) {
3345
await delay(delaySeconds * 1000);
3446
});
3547

36-
Then("there is a GA4 request", function() {
48+
Then("there is a GA4 request", function () {
3749
const ga4Request = this.requests.find(request => {
3850
try {
3951
const url = new URL(request.url);
@@ -46,8 +58,19 @@ Then("there is a GA4 request", function() {
4658
});
4759

4860
Then("there are no unexpected requests", function () {
49-
const requestUrls = this.requests.map((request) => {
61+
const requestURLs = this.requests.map((request) => {
5062
return (new URL(request.url)).host;
5163
});
52-
expect(["localhost:8080", "www.googletagmanager.com", "www.google-analytics.com"]).to.include.members(requestUrls);
53-
})
64+
65+
const allowedURLs = [
66+
"localhost:8080",
67+
"d3vtlq0ztv2u27.cloudfront.net",
68+
"dap.digitalgov.gov",
69+
"www.googletagmanager.com",
70+
"www.google-analytics.com"
71+
];
72+
73+
requestURLs.forEach((requestURL) => {
74+
expect(allowedURLs).to.include(requestURL);
75+
})
76+
})

features/support/step_definitions/dataLayer_steps.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ Then("the file download is reported to DAP with interaction type {string}", asyn
2626
"file_extension": "zip",
2727
"file_name": "/about.zip",
2828
"link_domain": "localhost",
29-
"link_id": "internaldownload",
29+
"link_id": "internalDownload",
3030
"link_text": "/about.zip",
3131
"link_url": "http://localhost:8080/about.zip",
3232
}
@@ -39,4 +39,4 @@ Then("the file download is not reported to DAP", async function () {
3939
return window.dataLayer.find(item => item[0] === 'event' && item[1] === 'file_download');
4040
});
4141
expect(event).to.be.undefined;
42-
});
42+
});

features/support/step_definitions/loading_steps.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,4 @@ Given("DAP is configured with autotracking disabled", function () {
2828

2929
When("I load the test site", async function () {
3030
await this.page.goto(`http://localhost:8080?${this.dapConfig.toQueryParams()}`);
31-
});
31+
});

nginx-test.conf.template

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
server {
2+
listen 80;
3+
listen [::]:80;
4+
server_name localhost;
5+
6+
#access_log /var/log/nginx/host.access.log main;
7+
8+
location / {
9+
ssi on;
10+
set $dap_code_env '${DAP_ENV}';
11+
set $dap_code_location 'Universal-Federated-Analytics-Min.js';
12+
13+
if ($dap_code_env = 'stg') {
14+
set $dap_code_location 'https://d3vtlq0ztv2u27.cloudfront.net/Universal-Federated-Analytics-Min.js';
15+
}
16+
if ($dap_code_env = 'prd') {
17+
set $dap_code_location 'https://dap.digitalgov.gov/Universal-Federated-Analytics-Min.js';
18+
}
19+
20+
# Create the script tag to include in each page's header using the
21+
# dap_code_location which is defined above
22+
set $header_script_tag '
23+
<script>
24+
(function() {
25+
const queryParams = new URLSearchParams(window.location.search);
26+
const dapScriptTag = document.createElement("script");
27+
const dapCodeLocation = ""
28+
dapScriptTag.id = "_fed_an_ua_tag";
29+
dapScriptTag.async = true;
30+
dapScriptTag.src = "${dap_code_location}" + "?dapdev=true&" + queryParams.toString();
31+
document.head.appendChild(dapScriptTag);
32+
})();
33+
</script>
34+
';
35+
36+
root /usr/share/nginx/html;
37+
index index.html index.htm;
38+
}
39+
40+
#error_page 404 /404.html;
41+
42+
# redirect server error pages to the static page /50x.html
43+
#
44+
error_page 500 502 503 504 /50x.html;
45+
location = /50x.html {
46+
root /usr/share/nginx/html;
47+
}
48+
49+
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
50+
#
51+
#location ~ \.php$ {
52+
# proxy_pass http://127.0.0.1;
53+
#}
54+
55+
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
56+
#
57+
#location ~ \.php$ {
58+
# root html;
59+
# fastcgi_pass 127.0.0.1:9000;
60+
# fastcgi_index index.php;
61+
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
62+
# include fastcgi_params;
63+
#}
64+
65+
# deny access to .htaccess files, if Apache's document root
66+
# concurs with nginx's one
67+
#
68+
#location ~ /\.ht {
69+
# deny all;
70+
#}
71+
}

package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88
"clean": "rm ./Universal-Federated-Analytics-Min.js",
99
"lint": "eslint Universal-Federated-Analytics.js",
1010
"cucumber": "cucumber-js",
11-
"cucumber:debug": "node --inspect-brk cucumber-js",
12-
"test-site": "docker build -t dap-test-site . && docker run --rm -p 8080:80 --name dap-test-site dap-test-site"
11+
"cucumber:debug": "VERBOSE=true node --inspect-brk node_modules/@cucumber/cucumber/bin/cucumber-js",
12+
"test-site-dev": "docker build --no-cache --build-arg DAP_ENV='dev' -t dap-test-site-dev . && docker run --rm -p 8080:80 --name dap-test-site-dev dap-test-site-dev",
13+
"test-site-stg": "docker build --no-cache --build-arg DAP_ENV='stg' -t dap-test-site-stg . && docker run --rm -p 8080:80 --name dap-test-site-stg dap-test-site-stg",
14+
"test-site-prd": "docker build --no-cache --build-arg DAP_ENV='prd' -t dap-test-site-prd . && docker run --rm -p 8080:80 --name dap-test-site-prd dap-test-site-prd"
1315
},
1416
"repository": {
1517
"type": "git",

test_site/index.html

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,11 @@
11
<!DOCTYPE html>
22
<html lang="en">
33
<head>
4-
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
4+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
55

6-
7-
<title>DAP test site</title>
8-
<script>
9-
(function() {
10-
const queryParams = new URLSearchParams(window.location.search);
11-
const dapScriptTag = document.createElement("script");
12-
dapScriptTag.id = "_fed_an_ua_tag";
13-
dapScriptTag.async = true;
14-
dapScriptTag.src = `Universal-Federated-Analytics-Min.js?dapdev=true&${queryParams.toString()}`;
15-
document.head.appendChild(dapScriptTag);
16-
})();
17-
18-
</script>
6+
<title>DAP test site</title>
7+
<!-- This is populated by NGINX SSI -->
8+
<!--#echo var="header_script_tag" encoding="none"-->
199
</head>
2010

2111
<body>
@@ -269,8 +259,8 @@ <h4>Incorrect Event Name</h4>
269259
<a href="https://ca.linkedin.com/" class="fa fa-linkedin" onclick="gas4('social',{'link_text':'<link_text>','link_domain':'<link_domain>','link_url':'<link_url>','link_id':'<link_id>','link_classes':'<link_classes>','social_network':'<social_network>','content_type':'<content_type>','section':'<section>'});"></a>
270260
</div>
271261
</div>
272-
273-
262+
263+
274264

275265
</section>
276266

@@ -300,8 +290,8 @@ <h4>Incorrect Event Name</h4>
300290
<a href="https://ca.linkedin.com/" class="fa fa-linkedin" onclick="gas4('social',{'link_text':'<link_text>','link_domain':'<link_domain>','link_url':'<link_url>','link_id':'<link_id>','link_classes':'<link_classes>','social_network':'<social_network>','content_type':'<content_type>','section':'<section>'});"></a>
301291
</div>
302292
</div>
303-
304-
293+
294+
305295

306296
</section>
307297

@@ -458,7 +448,7 @@ <h2>gas4() - Call to Action Click </h2>
458448
}
459449

460450
.active, .accordion:hover {
461-
background-color: #ccc;
451+
background-color: #ccc;
462452
}
463453

464454
.panel {

0 commit comments

Comments
 (0)