Skip to content

[Tech Debt] Update tests to be able to run against live staging/production environments #146

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
FROM nginx
COPY test_site Universal-Federated-Analytics-Min.js Federated.js.map /usr/share/nginx/html/
ARG DAP_ENV='dev'
ENV DAP_ENV=${DAP_ENV}
COPY test_site Universal-Federated-Analytics-Min.js Federated.js.map /usr/share/nginx/html/
COPY nginx-test.conf.template /etc/nginx/conf.d/
RUN envsubst '${DAP_ENV}' < /etc/nginx/conf.d/nginx-test.conf.template > /etc/nginx/conf.d/default.conf
14 changes: 12 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,18 @@ npm run lint
```

#### Run integration tests
Start up the test site at http://localhost:8080/:

Start up the test site at http://localhost:8080/ with one of the following:

```bash
npm run test-site
# Using the local version of the DAP code
npm run test-site-dev

# Using the staging environment version of the DAP code
npm run test-site-stg

# Using the production environment version of the DAP code
npm run test-site-prd
```

Then run the tests against the test site:
Expand All @@ -142,4 +150,6 @@ Then run the tests against the test site:
npm run cucumber
```

See more details in the [testing docs](features/README.md).

**All members of the digital-analytics-program GitHub organization are required to have two-factor authentication enabled.**
53 changes: 53 additions & 0 deletions features/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# DAP automated testing docs

The automated tests for the DAP code are implemented using [cucumber-js](https://github.com/cucumber/cucumber-js)
and [puppeteer](https://pptr.dev/).

By default the tests use the local version of the DAP javascript files. Loading
the code into a test HTML page, performing various user actions, and testing
the behavior of the code in response to the user actions.

Use the `DAP_ENV` environment variable to insert live versions of the code into
the test HTML page instead of the local version as described below.

## Running the tests

Start up the test site at http://localhost:8080/:

```bash
npm run test-site
```

Then run the tests against the test site:

```bash
npm run cucumber
```

## Running the tests with a debugger attached

```bash
npm run cucumber:debug
```

## Configuring with environment variables

### Verbose mode

Print debugging information to stdout while running the tests:

```bash
VERBOSE=true npm run cucumber
```

### Run tests against the live staging environment

```bash
DAP_ENV=staging npm run cucumber
```

### Run tests against the live production environment

```bash
DAP_ENV=production npm run cucumber
```
6 changes: 3 additions & 3 deletions features/autotracker_download.feature
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@ Feature: Downloads are reported to DAP when autotracking is enabled
Given DAP is configured with autotracking enabled
When I load the test site
And I click on a file to download it
Then the file download is reported to DAP with interaction type "mouse click"
Then the file download is reported to DAP with interaction type "Mouse Click"

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

Scenario: User clicks to download file with autotracker off
Given DAP is configured with autotracking disabled
When I load the test site
And I click on a file to download it
Then the file download is not reported to DAP
Then the file download is not reported to DAP
31 changes: 27 additions & 4 deletions features/support/step_definitions/browser_steps.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,18 @@ function delay(milliseconds) {
Given("I load an empty browser", async function () {
this.browser = await puppeteer.launch();
this.page = await this.browser.newPage();

if (process.env.VERBOSE == 'true') {
// Log page events to the node console
this.page
.on('console', message =>
console.log(`${message.type().substr(0, 3).toUpperCase()} ${message.text()}`))
.on('pageerror', ({ message }) => console.log(message))
.on('response', response =>
console.log(`${response.status()} ${response.url()}`))
.on('requestfailed', request =>
console.log(`${request.failure().errorText} ${request.url()}`))
}
});

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

Then("there is a GA4 request", function() {
Then("there is a GA4 request", function () {
const ga4Request = this.requests.find(request => {
try {
const url = new URL(request.url);
Expand All @@ -46,8 +58,19 @@ Then("there is a GA4 request", function() {
});

Then("there are no unexpected requests", function () {
const requestUrls = this.requests.map((request) => {
const requestURLs = this.requests.map((request) => {
return (new URL(request.url)).host;
});
expect(["localhost:8080", "www.googletagmanager.com", "www.google-analytics.com"]).to.include.members(requestUrls);
})

const allowedURLs = [
"localhost:8080",
"d3vtlq0ztv2u27.cloudfront.net",
"dap.digitalgov.gov",
"www.googletagmanager.com",
"www.google-analytics.com"
];

requestURLs.forEach((requestURL) => {
expect(allowedURLs).to.include(requestURL);
})
})
4 changes: 2 additions & 2 deletions features/support/step_definitions/dataLayer_steps.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Then("the file download is reported to DAP with interaction type {string}", asyn
"file_extension": "zip",
"file_name": "/about.zip",
"link_domain": "localhost",
"link_id": "internaldownload",
"link_id": "internalDownload",
"link_text": "/about.zip",
"link_url": "http://localhost:8080/about.zip",
}
Expand All @@ -39,4 +39,4 @@ Then("the file download is not reported to DAP", async function () {
return window.dataLayer.find(item => item[0] === 'event' && item[1] === 'file_download');
});
expect(event).to.be.undefined;
});
});
2 changes: 1 addition & 1 deletion features/support/step_definitions/loading_steps.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@ Given("DAP is configured with autotracking disabled", function () {

When("I load the test site", async function () {
await this.page.goto(`http://localhost:8080?${this.dapConfig.toQueryParams()}`);
});
});
71 changes: 71 additions & 0 deletions nginx-test.conf.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
server {
listen 80;
listen [::]:80;
server_name localhost;

#access_log /var/log/nginx/host.access.log main;

location / {
ssi on;
set $dap_code_env '${DAP_ENV}';
set $dap_code_location 'Universal-Federated-Analytics-Min.js';

if ($dap_code_env = 'stg') {
set $dap_code_location 'https://d3vtlq0ztv2u27.cloudfront.net/Universal-Federated-Analytics-Min.js';
}
if ($dap_code_env = 'prd') {
set $dap_code_location 'https://dap.digitalgov.gov/Universal-Federated-Analytics-Min.js';
}

# Create the script tag to include in each page's header using the
# dap_code_location which is defined above
set $header_script_tag '
<script>
(function() {
const queryParams = new URLSearchParams(window.location.search);
const dapScriptTag = document.createElement("script");
const dapCodeLocation = ""
dapScriptTag.id = "_fed_an_ua_tag";
dapScriptTag.async = true;
dapScriptTag.src = "${dap_code_location}" + "?dapdev=true&" + queryParams.toString();
document.head.appendChild(dapScriptTag);
})();
</script>
';

root /usr/share/nginx/html;
index index.html index.htm;
}

#error_page 404 /404.html;

# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}

# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}

# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}

# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
"clean": "rm ./Universal-Federated-Analytics-Min.js",
"lint": "eslint Universal-Federated-Analytics.js",
"cucumber": "cucumber-js",
"cucumber:debug": "node --inspect-brk cucumber-js",
"test-site": "docker build -t dap-test-site . && docker run --rm -p 8080:80 --name dap-test-site dap-test-site"
"cucumber:debug": "VERBOSE=true node --inspect-brk node_modules/@cucumber/cucumber/bin/cucumber-js",
"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",
"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",
"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"
},
"repository": {
"type": "git",
Expand Down
28 changes: 9 additions & 19 deletions test_site/index.html
Original file line number Diff line number Diff line change
@@ -1,21 +1,11 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />


<title>DAP test site</title>
<script>
(function() {
const queryParams = new URLSearchParams(window.location.search);
const dapScriptTag = document.createElement("script");
dapScriptTag.id = "_fed_an_ua_tag";
dapScriptTag.async = true;
dapScriptTag.src = `Universal-Federated-Analytics-Min.js?dapdev=true&${queryParams.toString()}`;
document.head.appendChild(dapScriptTag);
})();

</script>
<title>DAP test site</title>
<!-- This is populated by NGINX SSI -->
<!--#echo var="header_script_tag" encoding="none"-->
</head>

<body>
Expand Down Expand Up @@ -269,8 +259,8 @@ <h4>Incorrect Event Name</h4>
<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>
</div>
</div>



</section>

Expand Down Expand Up @@ -300,8 +290,8 @@ <h4>Incorrect Event Name</h4>
<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>
</div>
</div>



</section>

Expand Down Expand Up @@ -458,7 +448,7 @@ <h2>gas4() - Call to Action Click </h2>
}

.active, .accordion:hover {
background-color: #ccc;
background-color: #ccc;
}

.panel {
Expand Down
23 changes: 5 additions & 18 deletions test_site/youtube.html
Original file line number Diff line number Diff line change
@@ -1,24 +1,11 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />


<title>DAP test site - YouTube tracking</title>
<script>
(function() {
const queryParams = new URLSearchParams(window.location.search);
if (!queryParams.has("agency")) {
queryParams.set("agency", "GSA");
}
const dapScriptTag = document.createElement("script");
dapScriptTag.id = "_fed_an_ua_tag";
dapScriptTag.async = true;
dapScriptTag.src = `Universal-Federated-Analytics-Min.js?dapdev=true&${queryParams.toString()}`;
document.head.appendChild(dapScriptTag);
})();

</script>
<title>DAP test site - YouTube tracking</title>
<!-- This is populated by NGINX SSI -->
<!--#echo var="header_script_tag" encoding="none"-->
</head>

<body>
Expand All @@ -34,4 +21,4 @@
title="YouTube video player" frameborder="0" allowfullscreen></iframe>
</section>
</body>
</html>
</html>
Loading