Skip to content
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

Initial commit adding integration tests. #1557

Merged
merged 48 commits into from
Apr 3, 2020

Conversation

jrbenny35
Copy link
Collaborator

Works on #1539 #1556

Adds a total of 6 tests. 3 are visual regression tests that use a base image screenshot, The others are using selenium to validate the page loads the correct data

  1. should load correct number of breaches from an email input: Checks the number of breaches shown matches the number.
  2. should allow secondary email to be added: Flow that logs in and adds an email from the user dashboard.
  3. should load the latest breach card: Checks breach card loads on home page

Copy link
Collaborator

@pdehaan pdehaan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Q: Do we need "tests/integration/results/allure-results/wdio-0-0-allure-reporter.log"?

LOL at all the floating headers in the screenshots.

I'm not sure the Breaches_Page baselines will really work in the long run. It seems like any recent breach will cause the items to reorder and we'll need to regen the baselines after each freshly added breach. Possibly multiple times after we upload a new breach logo to the CDN.

Even the Home_Page baseline has a recent breach card. Not sure how viable it would be to hide that DOM element before taking/comparing images, or if that would defeat the purpose and reduce confidence (less brittle test that doesn't test a core thing). 🤷‍♂

package.json Outdated Show resolved Hide resolved
@@ -0,0 +1,22 @@
/* global $ */
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this just to appease the ESLint gods, or was this needed for something else?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For eslint. The $ is needed for wdio though

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, OK. You can also define [per-glob] globals in the ESLint config file (.eslintrc.js in root of project) instead of needing to define in each template.

For example, in the .eslintrc.js overrides: section, you can tweak the tests/**/*.js glob (around L32) and inject your $, $$, and browser globals there — if that is easier.

    {
      files: [
        'tests/**/*.js',
      ],
      env: {
        jest: true,
      },
+     globals: {
+       "$": "readonly",
+       "$$": "readonly",
+       "browser": "readonly",
+     },
    },

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well that's pretty neat!

get breachCard() { return new BreachCard(); }
get breachEmailAddress() { return $("#scan-email"); }
get checkBreachesButton() {
$(".input-group-button > input:nth-child(1)").click();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

n-th child!
Not sure if we want to put a more convenient class/handle on that submit button to make this any easier on you.
Or not sure if we can abuse the system with something like:

$(".input-group-button > input[type='submit']).click(); // if this even works

I'd be reluctant to bend it too far and try reading the button's label, since that will change with different locales (ie: input[value='Check for Breaches'] feels a bit risky risky).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Classes on everything would make it easier but I know that is boring so..this works, and if it gets updated it's an easy change

}

get numberOfBreaches() {
return $(".headline > span:nth-child(1)").getText();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

tests/integration/tests/test-create-baseline.js Outdated Show resolved Hide resolved
$(".email").click();
$(".email").setValue(global.primaryEmail);
$("#submit-btn").click();
} catch (error) {

This comment was marked as resolved.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sometimes the email doesn't show as monitor passes the email you used for checking breaches into the fxa sign in

Copy link
Collaborator

@pdehaan pdehaan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great, @jrbenny35!
Thanks for all your hard work on this!

tests/integration/regions/navbar.region.js Show resolved Hide resolved
tests/integration/wdio.conf.js Outdated Show resolved Hide resolved
tests/integration/tests/test-breaches-page.js Outdated Show resolved Hide resolved
tests/integration/tests/test-create-baseline.js Outdated Show resolved Hide resolved
const UserDashboardPage = require("../pages/desktop/dashboard.page");

describe("Firefox Monitor homepage", function() {
//this.retries(2);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be uncommented (like in L7 of previous file)?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am thinking retries aren't so bad, as there are multiple things that could go wrong. What do you think @pdehaan

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 on retries, and 2 is a good number.

.circleci/config.yml Outdated Show resolved Hide resolved
@@ -0,0 +1,182 @@
#!/usr/bin/env bash
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm always nervous about adding shell scripts to repos. Can we add this WITHOUT executable permission, and then have the docker file change it to executable?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, after marinating on this overnight and giving it a few Bing searches, what about something like this: https://www.npmjs.com/package/wait-on

wait-on is a cross-platform command line utility which will wait for files, ports, sockets, and http(s) resources to become available (or not available using reverse mode). Functionality is also available via a Node.js API. Cross-platform - runs everywhere Node.js runs (linux, unix, mac OS X, windows)

I've never used it in a project yet, but 🤷‍♂.

Our current implementation looks something like this:

command: ["./scripts/wait-for-it.sh", "postgres:5432", "--", "npm", "run", "db:migrate"]

Not sure if that would be similar to:

command: ["wait-on", "tcp:5432", "&&", "npm", "run", "db:migrate"]

Or if we just add another npm script in package.json which does "ci:db:migrate" so the command looks less scary.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what would be best here. I am open to suggestions.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jrbenny35 and I were noodling on this a bit, and we might be able to remove the +x flag on the .sh file and just invoke this script using bash ./wait-for-it.sh. Testing locally, that seems to still work in a simple test case even though the file is non-executable.


global.baseUrl = "http://localhost:6060";
global.primaryEmail = "test@mailinator.com";
global.secondaryEmail = "test" + Math.random() + "@mailinator.com";

This comment was marked as resolved.


global.baseUrl = "http://localhost:6060";
global.primaryEmail = "test@mailinator.com";
global.secondaryEmail = "test" + Math.random() + "@mailinator.com";

This comment was marked as resolved.

tests/integration/tests/test-home-page.js Outdated Show resolved Hide resolved
global.primaryEmail = "test@mailinator.com";
global.secondaryEmail = "test" + Math.random() + "@mailinator.com";
global.mailinatorPassword = process.env.MAILINATOR_PASSWORD || "a_secure_password";
browser.setWindowSize(1920, 1080);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for a future enhancement, we might want to run tests with mobile-dimension window sizes. or do we use another mechanism for testing mobile browsers/dimensions?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For mobile I'll have to set a screensize as well. We could maybe have another *.conf.js for mobile that has that set differently.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@groovecoder did you have a specific device/viewport in mind?
Somewhere between an Alcatel Go Flip 2 and a Samsung Galaxy S20 Ultra 5G Turbo: Hyper Fighting edition?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I usually use an iPhone 'Plus' model

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like the latest iPhone [11 Pro Max], has the following viewport:

    'viewport': {
      'width': 414,
      'height': 896,
      'deviceScaleFactor': 3,
      'isMobile': true
    }

— per the playwright deviceDescriptors file.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For mobile I'll have to set a screensize as well. We could maybe have another *.conf.js for mobile that has that set differently.

I think all that would need to change is the browser.setWindowSize(w, h) dimensions, correct?
Wondering if we could convert that into ENV vars (maybe with a desktop fallback). That way we wouldn't need any new config files and we could possibly hack something like this:

"test:integration:mobile": "BROWSER_WIDTH=414 BROWSER_HEIGHT=896 wdio tests/integration/wdio.conf.js",

Then, above we'd just need to change to this psesudo-code mess:

// NOTE: Env vars come in as strings, iirc, so we cast them to numbers here.
browser.setWindowSize(
    Number(process.env.BROWSER_WIDTH) || 1920,
    Number(process.env.BROWSER_HEIGHT) || 1080
);

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is good thinking. @groovecoder thoughts on this?

@jrbenny35
Copy link
Collaborator Author

I'm not sure the Breaches_Page baselines will really work in the long run. It seems like any recent breach will cause the items to reorder and we'll need to regen the baselines after each freshly added breach. Possibly multiple times after we upload a new breach logo to the CDN.

Even the Home_Page baseline has a recent breach card. Not sure how viable it would be to hide that DOM element before taking/comparing images, or if that would defeat the purpose and reduce confidence (less brittle test that doesn't test a core thing). man_shrugging

I wonder how exact it is. I think it is worth having but if it comparing words, then yeah, that will be a problem. That is why I wanted to use a range. It calculates a percentage based on how "off" the page is.

@pdehaan
Copy link
Collaborator

pdehaan commented Feb 19, 2020

It calculates a percentage based on how "off" the page is.

AAAHHHH... OK, my misunderstanding. The tool we used at a different company measured by pixels so we could only have 0-5 pixels different from a baseline, not 0-5%. I say we run with it for a bit and see how it works in the long run.

@jrbenny35
Copy link
Collaborator Author

It calculates a percentage based on how "off" the page is.

AAAHHHH... OK, my misunderstanding. The tool we used at a different company measured by pixels so we could only have 0-5 pixels different from a baseline, not 0-5%. I say we run with it for a bit and see how it works in the long run.

I agree. If the words make up for 10% or less, I think we are still good (as we discussed on slack).

@pdehaan
Copy link
Collaborator

pdehaan commented Feb 24, 2020

From @jrbenny35 in a Slack channel:

there is a new breach added to monitor, the visual tests failed with 6.55% diff

@jrbenny35
Copy link
Collaborator Author

jrbenny35 commented Feb 24, 2020

From @jrbenny35 in a Slack channel:

there is a new breach added to monitor, the visual tests failed with 6.55% diff

The homepage failed with a 5.8ish% diff and the "Breaches" page failed with 6.55%. If this keeps gets worse with more breaches, we will have to revist this and maybe create a better baseline.

@pdehaan
Copy link
Collaborator

pdehaan commented Feb 25, 2020

If this keeps gets worse with more breaches, we will have to revisit this and maybe create a better baseline.

Yeah, I can imagine the /breaches/ endpoint will be a hot mess(tm). Currently the breaches are sorted by the breach date (which isn't a displayed field, making the ordering appear completely random). So if a breach is new added to the site, it could be displayed first (invalidating the order of all 15 items), or could appear 8th in the list (invalidating only 7-8 of the 15 displayed items), or could be displayed as the 200th most recent breach, which is then hidden behind the "Show All" button, and may not even appear in the image diff (depending on whether you baseline before or after hitting the "Show All" button).

So the fact the "Slickwraps" breach is currently the lastest breach date and date added (putting it in the first slot of the /breaches/ page), seems to be our worst case scenario -- image-diff-wise speaking.

@jrbenny35 jrbenny35 requested a review from pdehaan March 3, 2020 19:47
@jrbenny35
Copy link
Collaborator Author

jrbenny35 commented Mar 4, 2020

If you want to try these locally you will need to follow these instructions:

  1. Copy .env-dist to .env.
  2. Set the following env variables: FXA_ENABLED=1, HIBP_KANON_API_TOKEN=token123, HIBP_API_TOKEN=token123, MONITOR_FXA_PASSWORD=password. Replace the values in "token123" and "password" with the correct ones.
  3. In the same shell instance, start the server and build the docker image docker-compose -f tests/integration/docker-compose.yml up --build -d.
  4. Run the tests: npm run test:integration.

I can provide the MONITOR_FXA_PASSWORD on slack if needed. @groovecoder has it too.

tests/integration/README.md Outdated Show resolved Hide resolved
3. Run the tests: ```npm run test:integration```.
They can also be run headlessly: ```npm run test:integration-headless```, and inside docker: ```npm run test:integration-docker```.

[geckodriver]: https://github.com/mozilla/geckodriver/releases
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, interesting! looks like geckodriver is on npm too: https://www.npmjs.com/package/geckodriver (by our very own vladikoff!)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should I link that instead?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, sorry, that was just me thinking out loud and bookmarking it for future reference. It'd only make sense to switch if we added it as a project dependency in package.json and got rid of the explicit dependency of having it preinstalled. But I'd have to audit the npm install to see how big that bundle is. In fact, I can do that right now.

Looks like running npm i geckodriver -D in a fresh directory adds about 9.7 MB of node_modules goodness, including the following files in ./node_modules/geckodriver/:

-rwxr-xr-x   5.0M 10 Oct 15:53 geckodriver
-rw-r--r--   1.9M  5 Mar 10:26 geckodriver.tar.gz

But let's just leave this as-is for now and can refactor in the future after this lands.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good info to have though!

tests/integration/wdio.docker.js Outdated Show resolved Hide resolved
@jrbenny35
Copy link
Collaborator Author

@groovecoder @lesleyjanenorton would love to land this this week

@jrbenny35
Copy link
Collaborator Author

@groovecoder @lesleyjanenorton any updates?

@jrbenny35 jrbenny35 force-pushed the add-initial-integration-tests branch from 9d5edb1 to eaad988 Compare March 24, 2020 19:19
@pdehaan
Copy link
Collaborator

pdehaan commented Mar 24, 2020

@groovecoder @lesleyjanenorton Do either of you have any bandwidth to assist with this? We've rebased and are still seeing the test failure on Travis-CI (https://travis-ci.org/github/mozilla/blurts-server/jobs/666489293?utm_medium=notification&utm_source=github_status) but I'm still unclear if it's related to our PR since it doesn't look like we've touched any of the failing code. Although @jrbenny35 rebased and it looks like we should be in sync w/ latest changes to master branch.

I'm at a bit of a loss.

Copy link
Member

@groovecoder groovecoder left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One last change requested. I can't speak much to how we should write all the page tests, so I'm assuming @pdehaan is making the thorough review of that code.

.eslintrc.js Show resolved Hide resolved
OAUTH_CLIENT_ID=cb1bef9d06bb9bc9
OAUTH_CLIENT_SECRET=f5fb99de6e0af18ab17e013ac1d439903179a97a1c510fc10bc3bd50bbce089b
OAUTH_CLIENT_ID=edd29a80019d61a1
OAUTH_CLIENT_SECRET=a80feaad77c847275d39ac989ee12a873ef6b54cbc184128f86f2afecdf003b5
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume these are OK to change? (I know it's just a dist file, but wanted to confirm these aren't critical creds that need to be regenerated now).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, these are the values I have on my local file and it's working.

HIBP_KANON_API_TOKEN=""
HIBP_KANON_API_TOKEN=
HIBP_API_ROOT="https://haveibeenpwned.com/api/v2"
HIBP_API_TOKEN=
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these OK to be "naked", or should they be empty strings, a la =""?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -16,18 +16,40 @@ services:
- LOGOS_ORIGIN=null
- BREACH_RESOLUTION_ENABLED=false
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious, should this be "true"? I think breach resolutions are enabled in production. Curious what effect this would have, apart from the logged in admin being slightly different.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The breach detail pages will also be different for logged-in users.

tests/integration/docker-compose.yml Show resolved Hide resolved
tests/integration/pages/desktop/scanResults.page.js Outdated Show resolved Hide resolved
tests/integration/wdio.docker.js Outdated Show resolved Hide resolved
@pdehaan pdehaan requested a review from groovecoder April 2, 2020 15:18
@pdehaan
Copy link
Collaborator

pdehaan commented Apr 2, 2020

Awesome work @jrbenny35, as always!
Re-reviewed the latest changes and left a few random thoughts and comments.
@groovecoder Can you give this one last 👀 before we merge this into the big code repo in the sky?

@jrbenny35 jrbenny35 force-pushed the add-initial-integration-tests branch from f595c7a to 953c541 Compare April 2, 2020 20:01
Copy link
Member

@groovecoder groovecoder left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update to eslintrc looks good. Thanks.

@jrbenny35 jrbenny35 merged commit b19eff6 into mozilla:master Apr 3, 2020
@jrbenny35 jrbenny35 mentioned this pull request Apr 3, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants