cleaned up integration test flow

This commit is contained in:
Danny Coates 2018-10-03 17:39:39 -07:00
parent 23d629b80b
commit 76de2b29a5
No known key found for this signature in database
GPG Key ID: 4C442633C62E00CB
20 changed files with 123 additions and 1798 deletions

View File

@ -1,9 +0,0 @@
{
"presets": [
["env", {
"targets": {
"node": "current"
}
}]
]
}

View File

@ -2,5 +2,3 @@ dist
assets assets
firefox firefox
coverage coverage
test/integration
test/wdio.*

1
.gitignore vendored
View File

@ -12,3 +12,4 @@ ios/send-ios/assets/ios.js
ios/send-ios/assets/vendor.js ios/send-ios/assets/vendor.js
ios/send-ios.xcodeproj/project.xcworkspace/xcuserdata/* ios/send-ios.xcodeproj/project.xcworkspace/xcuserdata/*
ios/send-ios.xcodeproj/xcuserdata/* ios/send-ios.xcodeproj/xcuserdata/*
test/integration/downloads

View File

@ -6,27 +6,27 @@ jobs:
steps: steps:
- checkout - checkout
- restore_cache: - restore_cache:
key: send-{{ checksum "package-lock.json" }} key: send-build-{{ checksum "package-lock.json" }}
- run: npm install - run: npm install
- save_cache: - save_cache:
key: send-{{ checksum "package-lock.json" }} key: send-build-{{ checksum "package-lock.json" }}
paths: paths:
- node_modules - node_modules
- run: npm run build - run: npm run build
- persist_to_workspace: - persist_to_workspace:
root: . root: .
paths: paths:
- ./* - ./dist
test: test:
docker: docker:
- image: circleci/node:10-browsers - image: circleci/node:10-browsers
steps: steps:
- checkout - checkout
- restore_cache: - restore_cache:
key: send-{{ checksum "package-lock.json" }} key: send-test-{{ checksum "package-lock.json" }}
- run: npm install - run: npm install
- save_cache: - save_cache:
key: send-{{ checksum "package-lock.json" }} key: send-test-{{ checksum "package-lock.json" }}
paths: paths:
- node_modules - node_modules
- run: npm run lint - run: npm run lint
@ -34,30 +34,19 @@ jobs:
- store_artifacts: - store_artifacts:
path: coverage path: coverage
integration_tests: integration_tests:
machine: true docker:
- image: circleci/node:10
- image: selenium/standalone-firefox
steps: steps:
- checkout - checkout
- attach_workspace: - restore_cache:
at: . key: send-int-{{ checksum "package-lock.json" }}
- run: - run: npm install
name: Install Docker Compose - save_cache:
command: | key: send-int-{{ checksum "package-lock.json" }}
set -x paths:
pip install docker-compose>=1.18 - node_modules
docker-compose --version - run: npm run circleci-test-integration
- run:
name: Setup
command: |
set -x
docker-compose pull
- run:
name: Run Integration tests
command: |
set -x
docker-compose up -d selenium-firefox
sleep 10
docker-compose ps
docker-compose exec selenium-firefox npm run test-circle:selenium
deploy_dev: deploy_dev:
machine: true machine: true
steps: steps:
@ -101,12 +90,12 @@ workflows:
ignore: ignore:
- master - master
- vnext - vnext
# - integration_tests: - integration_tests:
# filters: filters:
# branches: branches:
# ignore: master ignore: master
# requires: requires:
# - build - build
build_and_deploy_dev: build_and_deploy_dev:
jobs: jobs:
- build: - build:

1679
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -25,8 +25,8 @@
"test:backend": "nyc --reporter=lcovonly mocha --reporter=min test/backend", "test:backend": "nyc --reporter=lcovonly mocha --reporter=min test/backend",
"test:frontend": "cross-env NODE_ENV=development node test/frontend/runner.js", "test:frontend": "cross-env NODE_ENV=development node test/frontend/runner.js",
"test:report": "nyc report --reporter=html", "test:report": "nyc report --reporter=html",
"test-circle": "npm-run-all test:backend test-circle:selenium test:report", "test-integration": "cross-env NODE_ENV=development wdio test/wdio.docker.conf.js",
"test-circle:selenium": "cross-env NODE_ENV=development wdio test/wdio.local.conf.js ", "circleci-test-integration": "cross-env NODE_ENV=development wdio test/wdio.circleci.conf.js",
"start": "npm run clean && cross-env NODE_ENV=development FXA_CLIENT_ID=fced6b5e3f4c66b9 BASE_URL=http://localhost:8080 webpack-dev-server --mode=development", "start": "npm run clean && cross-env NODE_ENV=development FXA_CLIENT_ID=fced6b5e3f4c66b9 BASE_URL=http://localhost:8080 webpack-dev-server --mode=development",
"android": "cross-env ANDROID=1 npm start", "android": "cross-env ANDROID=1 npm start",
"prod": "node server/bin/prod.js" "prod": "node server/bin/prod.js"
@ -69,8 +69,6 @@
"babel-loader": "^8.0.4", "babel-loader": "^8.0.4",
"babel-plugin-istanbul": "^5.0.1", "babel-plugin-istanbul": "^5.0.1",
"babel-plugin-yo-yoify": "^2.0.0", "babel-plugin-yo-yoify": "^2.0.0",
"babel-preset-env": "^1.7.0",
"babel-register": "^6.26.0",
"base64-js": "^1.3.0", "base64-js": "^1.3.0",
"content-disposition": "^0.5.2", "content-disposition": "^0.5.2",
"copy-webpack-plugin": "^4.5.2", "copy-webpack-plugin": "^4.5.2",
@ -117,10 +115,7 @@
"svgo": "^1.1.1", "svgo": "^1.1.1",
"svgo-loader": "^2.2.0", "svgo-loader": "^2.2.0",
"testpilot-ga": "^0.3.0", "testpilot-ga": "^0.3.0",
"tmp": "0.0.33",
"val-loader": "^1.1.1", "val-loader": "^1.1.1",
"webpack": "^4.20.2",
"webpack-cli": "^3.1.2",
"wdio-docker-service": "^1.4.2", "wdio-docker-service": "^1.4.2",
"wdio-dot-reporter": "0.0.10", "wdio-dot-reporter": "0.0.10",
"wdio-firefox-profile-service": "^0.1.3", "wdio-firefox-profile-service": "^0.1.3",
@ -128,9 +123,10 @@
"wdio-sauce-service": "^0.4.11", "wdio-sauce-service": "^0.4.11",
"wdio-spec-reporter": "^0.1.5", "wdio-spec-reporter": "^0.1.5",
"webdriverio": "^4.13.2", "webdriverio": "^4.13.2",
"webpack": "^4.20.2",
"webpack-cli": "^3.1.2",
"webpack-dev-middleware": "^3.4.0", "webpack-dev-middleware": "^3.4.0",
"webpack-manifest-plugin": "^2.0.4", "webpack-manifest-plugin": "^2.0.4",
"webpack-dev-server": "2.9.1",
"webpack-unassert-loader": "^1.2.0" "webpack-unassert-loader": "^1.2.0"
}, },
"dependencies": { "dependencies": {

View File

@ -1,13 +1,13 @@
import DownloadPage from './pages/desktop/download_page'; /* global browser document */
import HomePage from './pages/desktop/home_page';
import SharePage from './pages/desktop/share_page';
const assert = require('assert'); const assert = require('assert');
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
describe('Firefox Send', () => { const DownloadPage = require('./pages/desktop/download_page');
const baseUrl = browser.options['baseUrl']; const HomePage = require('./pages/desktop/home_page');
const SharePage = require('./pages/desktop/share_page');
describe('Firefox Send', function() {
const downloadDir = const downloadDir =
browser.desiredCapabilities['moz:firefoxOptions']['prefs'][ browser.desiredCapabilities['moz:firefoxOptions']['prefs'][
'browser.download.dir' 'browser.download.dir'
@ -15,7 +15,7 @@ describe('Firefox Send', () => {
const testFilesPath = path.join(__dirname, 'fixtures'); const testFilesPath = path.join(__dirname, 'fixtures');
const testFiles = fs.readdirSync(testFilesPath); const testFiles = fs.readdirSync(testFilesPath);
beforeEach(() => { beforeEach(function() {
browser.url('/'); browser.url('/');
browser.execute(() => { browser.execute(() => {
document.getElementById('file-upload').style.display = 'block'; document.getElementById('file-upload').style.display = 'block';
@ -24,18 +24,18 @@ describe('Firefox Send', () => {
}); });
testFiles.forEach(file => { testFiles.forEach(file => {
it(`should upload and download files, file: ${file}`, () => { it(`should upload and download files, file: ${file}`, function() {
browser.execute(() => { browser.execute(() => {
document.getElementById('file-upload').style.display = 'block'; document.getElementById('file-upload').style.display = 'block';
}); });
browser.waitForExist('#file-upload'); browser.waitForExist('#file-upload');
let homePage = new HomePage(); const homePage = new HomePage();
browser.chooseFile('#file-upload', `${testFilesPath}/${file}`); browser.chooseFile('#file-upload', `${testFilesPath}/${file}`);
browser.click(homePage.readyToSend); browser.click(homePage.readyToSend);
let sharePage = new SharePage(); const sharePage = new SharePage();
browser.waitForExist(sharePage.fileUrl); browser.waitForExist(sharePage.fileUrl);
browser.url(browser.getValue(sharePage.fileUrl)); browser.url(browser.getValue(sharePage.fileUrl));
let downloadPage = new DownloadPage(); const downloadPage = new DownloadPage();
downloadPage.waitForPageToLoad(); downloadPage.waitForPageToLoad();
downloadPage.downloadBtn(); downloadPage.downloadBtn();
// Wait for download to complete // Wait for download to complete
@ -45,7 +45,7 @@ describe('Firefox Send', () => {
browser.getText(downloadPage.downloadComplete) === 'DOWNLOAD COMPLETE' browser.getText(downloadPage.downloadComplete) === 'DOWNLOAD COMPLETE'
); );
}); });
assert.ok(fs.existsSync(`${downloadDir}/${file}`)); assert.ok(fs.existsSync(path.join(downloadDir, file)));
}); });
}); });
}); });

View File

@ -1,8 +1,8 @@
import HomePage from './pages/desktop/home_page'; /* global browser */
const assert = require('assert'); const assert = require('assert');
const HomePage = require('./pages/desktop/home_page');
describe('Firefox Send homepage', () => { describe('Firefox Send homepage', function() {
const baseUrl = browser.options['baseUrl']; const baseUrl = browser.options['baseUrl'];
const legalLinks = [ const legalLinks = [
'legal', 'legal',
@ -13,26 +13,24 @@ describe('Firefox Send homepage', () => {
]; ];
const socialLinks = ['github', 'twitter', 'mozilla']; const socialLinks = ['github', 'twitter', 'mozilla'];
beforeEach(() => { beforeEach(function() {
browser.url('/'); browser.url('/');
browser.pause(500); browser.pause(500);
}); });
it('should have the right title', () => { it('should have the right title', function() {
chai.expect(browser.getTitle()).to.equal('Firefox Send'); assert.equal(browser.getTitle(), 'Firefox Send');
}); });
legalLinks.forEach((link, i) => { legalLinks.forEach((link, i) => {
it(`should navigate to the correct legal pages, page: ${link}`, () => { it(`should navigate to the correct legal pages, page: ${link}`, function() {
let homePage = new HomePage(); const homePage = new HomePage();
// Click links on bottom of page // Click links on bottom of page
var els = browser.elements(homePage.legalLinks); const els = browser.elements(homePage.legalLinks);
if (i === 0) {
}
browser.elementIdClick(els.value[i].ELEMENT); browser.elementIdClick(els.value[i].ELEMENT);
// Wait for page to load // Wait for page to load
browser.waitUntil(() => { browser.waitUntil(() => {
let url = browser.getUrl(); const url = browser.getUrl();
return url !== baseUrl; return url !== baseUrl;
}); });
assert.ok(browser.getUrl().includes(link)); assert.ok(browser.getUrl().includes(link));
@ -40,14 +38,14 @@ describe('Firefox Send homepage', () => {
}); });
socialLinks.forEach((link, i) => { socialLinks.forEach((link, i) => {
it(`should navigate to the correct social pages, page: ${link}`, () => { it(`should navigate to the correct social pages, page: ${link}`, function() {
let homePage = new HomePage(); const homePage = new HomePage();
// Click links on bottom of page // Click links on bottom of page
var els = browser.elements(homePage.socialLinks); const els = browser.elements(homePage.socialLinks);
browser.elementIdClick(els.value[i].ELEMENT); browser.elementIdClick(els.value[i].ELEMENT);
// Wait for page to load // Wait for page to load
browser.waitUntil(() => { browser.waitUntil(() => {
let url = browser.getUrl(); const url = browser.getUrl();
return url !== baseUrl; return url !== baseUrl;
}); });
assert.ok(browser.getUrl().includes(link)); assert.ok(browser.getUrl().includes(link));

View File

@ -1,6 +1,7 @@
import Page from './page'; /* global browser */
const Page = require('./page');
export default class DownloadPage extends Page { class DownloadPage extends Page {
constructor() { constructor() {
super(); super();
this.downloadBtnLocator = '.btn--download'; this.downloadBtnLocator = '.btn--download';
@ -15,7 +16,7 @@ export default class DownloadPage extends Page {
waitForPageToLoad() { waitForPageToLoad() {
browser.waitUntil(() => { browser.waitUntil(() => {
browser.waitForExist(this.downloadBtnLocator); browser.waitForExist(this.downloadBtnLocator);
let el = browser.element(this.downloadBtnLocator); const el = browser.element(this.downloadBtnLocator);
return browser.elementIdDisplayed(el.value.ELEMENT); return browser.elementIdDisplayed(el.value.ELEMENT);
}); });
return this; return this;
@ -30,3 +31,4 @@ export default class DownloadPage extends Page {
return this.downloadCompletedLocator; return this.downloadCompletedLocator;
} }
} }
module.exports = DownloadPage;

View File

@ -1,6 +1,6 @@
import Page from './page'; const Page = require('./page');
export default class HomePage extends Page { class HomePage extends Page {
constructor() { constructor() {
super(); super();
this.legalSectionLinks = '.legalSection .legalSection__link'; this.legalSectionLinks = '.legalSection .legalSection__link';
@ -20,3 +20,4 @@ export default class HomePage extends Page {
return this.socialLinksLocator; return this.socialLinksLocator;
} }
} }
module.exports = HomePage;

View File

@ -1,4 +1,5 @@
export default class Page { /* global browser */
class Page {
constructor() {} constructor() {}
open(path) { open(path) {
@ -13,3 +14,4 @@ export default class Page {
*/ */
waitForPageToLoad() {} waitForPageToLoad() {}
} }
module.exports = Page;

View File

@ -1,7 +1,8 @@
import Page from './page'; /* global browser */
import SharePage from './share_page'; const Page = require('./page');
const SharePage = require('./share_page');
export default class ProgressPage extends Page { class ProgressPage extends Page {
constructor() { constructor() {
super(); super();
this.cancelBtnLocator = '.uploadCancel'; this.cancelBtnLocator = '.uploadCancel';
@ -16,10 +17,10 @@ export default class ProgressPage extends Page {
waitForPageToLoad() { waitForPageToLoad() {
browser.waitUntil(() => { browser.waitUntil(() => {
browser.waitForExist(this.progressIconLocator); browser.waitForExist(this.progressIconLocator);
let el = browser.element(this.progressIconLocator); const el = browser.element(this.progressIconLocator);
return browser.elementIdDisplayed(el.value.ELEMENT); return browser.elementIdDisplayed(el.value.ELEMENT);
}); });
let sharePage = new SharePage(); const sharePage = new SharePage();
return sharePage.waitForPageToLoad(); return sharePage.waitForPageToLoad();
} }
@ -27,3 +28,4 @@ export default class ProgressPage extends Page {
return this.cancelBtnLocator; return this.cancelBtnLocator;
} }
} }
module.exports = ProgressPage;

View File

@ -1,6 +1,7 @@
import Page from './page'; /* global browser */
const Page = require('./page');
export default class SharePage extends Page { class SharePage extends Page {
constructor() { constructor() {
super(); super();
this.sharePageLocator = '#shareWrapper'; this.sharePageLocator = '#shareWrapper';
@ -10,7 +11,7 @@ export default class SharePage extends Page {
waitForPageToLoad() { waitForPageToLoad() {
browser.waitUntil(() => { browser.waitUntil(() => {
browser.waitForExist(this.sharePageLocator); browser.waitForExist(this.sharePageLocator);
let el = browser.element(this.sharePageLocator); const el = browser.element(this.sharePageLocator);
return browser.elementIdDisplayed(el.value.ELEMENT); return browser.elementIdDisplayed(el.value.ELEMENT);
}); });
return this; return this;
@ -20,3 +21,4 @@ export default class SharePage extends Page {
return this.shareUrlLocator; return this.shareUrlLocator;
} }
} }
module.exports = SharePage;

View File

@ -1,24 +1,22 @@
import ProgressPage from './pages/desktop/progress_page'; /* global browser document */
import HomePage from './pages/desktop/home_page';
const assert = require('assert'); const assert = require('assert');
const ProgressPage = require('./pages/desktop/progress_page');
const HomePage = require('./pages/desktop/home_page');
describe('Firefox Send progress page', () => { describe('Firefox Send progress page', function() {
const baseUrl = browser.options['baseUrl']; beforeEach(function() {
beforeEach(() => {
browser.url('/'); browser.url('/');
}); });
it('should show an icon while an upload is in progress', () => { it('should show an icon while an upload is in progress', function() {
browser.execute(() => { browser.execute(() => {
document.getElementById('file-upload').style.display = 'block'; document.getElementById('file-upload').style.display = 'block';
}); });
browser.waitForExist('#file-upload'); browser.waitForExist('#file-upload');
let homePage = new HomePage(); const homePage = new HomePage();
browser.chooseFile('#file-upload', __filename); browser.chooseFile('#file-upload', __filename);
browser.click(homePage.readyToSend); browser.click(homePage.readyToSend);
let progressPage = new ProgressPage(); const progressPage = new ProgressPage();
assert.ok(progressPage.waitForPageToLoad()); assert.ok(progressPage.waitForPageToLoad());
}); });
}); });

View File

@ -0,0 +1,18 @@
// eslint-disable-next-line node/no-extraneous-require
const ip = require('ip');
const path = require('path');
const common = require('./wdio.common.conf');
/*/
Config for running selenium from a circleci docker container against localhost
/*/
exports.config = Object.assign({}, common.config, {
baseUrl: `http://${ip.address()}:8000`,
exclude: [path.join(__dirname, './integration/download-tests.js')],
maxInstances: 1,
bail: 1,
services: [require('./testServer')]
});

View File

@ -1,6 +1,10 @@
const path = require('path'); const path = require('path');
const tmp = require('tmp'); const mkdirp = require('mkdirp');
const tmpDir = tmp.dirSync({ mode: '0777', prefix: 'integrationTestsTmpDir-' }); const rimraf = require('rimraf');
const dir = path.join(__dirname, 'integration', 'downloads');
mkdirp.sync(dir);
rimraf.sync(`${dir}${path.sep}*`);
exports.config = { exports.config = {
specs: [path.join(__dirname, './integration/**/*-tests.js')], specs: [path.join(__dirname, './integration/**/*-tests.js')],
@ -16,7 +20,7 @@ exports.config = {
'browser.helperApps.neverAsk.openFile': 'text/plain', 'browser.helperApps.neverAsk.openFile': 'text/plain',
'browser.helperApps.neverAsk.saveToDisk': 'text/plain', 'browser.helperApps.neverAsk.saveToDisk': 'text/plain',
'browser.download.folderList': 2, 'browser.download.folderList': 2,
'browser.download.dir': `${tmpDir.name}` 'browser.download.dir': dir
} }
} }
} }
@ -29,7 +33,7 @@ exports.config = {
deprecationWarnings: true, deprecationWarnings: true,
bail: 0, bail: 0,
screenshotOnReject: false, screenshotOnReject: false,
baseUrl: 'http://localhost:8080', baseUrl: 'http://localhost:8000',
waitforTimeout: 20000, waitforTimeout: 20000,
connectionRetryTimeout: 90000, connectionRetryTimeout: 90000,
connectionRetryCount: 3, connectionRetryCount: 3,
@ -39,7 +43,6 @@ exports.config = {
mochaOpts: { mochaOpts: {
ui: 'bdd', ui: 'bdd',
timeout: 30000, timeout: 30000,
compilers: ['js:babel-register'],
retries: 1 retries: 1
} }
}; };

View File

@ -1,5 +1,10 @@
// eslint-disable-next-line node/no-extraneous-require
const ip = require('ip'); const ip = require('ip');
const common = require('./wdio.common.conf'); const common = require('./wdio.common.conf');
const dir =
common.config.capabilities[0]['moz:firefoxOptions'].prefs[
'browser.download.dir'
];
/*/ /*/
@ -16,6 +21,7 @@ exports.config = Object.assign({}, common.config, {
healthCheck: 'http://localhost:4444', healthCheck: 'http://localhost:4444',
options: { options: {
p: ['4444:4444'], p: ['4444:4444'],
mount: `type=bind,source=${dir},destination=${dir},consistency=delegated`,
shmSize: '2g' shmSize: '2g'
} }
} }

View File

@ -1,3 +1,4 @@
// eslint-disable-next-line node/no-extraneous-require
const ip = require('ip'); const ip = require('ip');
const common = require('./wdio.common.conf'); const common = require('./wdio.common.conf');

View File

@ -11,15 +11,16 @@ exports.config = Object.assign({}, common.config, {
baseUrl: process.env.TEST_SERVER || 'https://send.dev.mozaws.net', baseUrl: process.env.TEST_SERVER || 'https://send.dev.mozaws.net',
exclude: [ exclude: [
// the /test endpoint only exists on localhost // the /test endpoint only exists on localhost
path.join(__dirname, './ui/unit-tests.js') path.join(__dirname, './integration/unit-tests.js'),
// we don't have access to the fs in this context
path.join(__dirname, './integration/download-tests.js')
], ],
capabilities: [ capabilities: [
{ browserName: 'firefox' }, { browserName: 'firefox' },
{ browserName: 'chrome' }, { browserName: 'chrome' },
{ browserName: 'MicrosoftEdge' }, { browserName: 'MicrosoftEdge' },
{ {
browserName: 'safari', browserName: 'safari'
exclude: [path.join(__dirname, './ui/upload-tests.js')]
} }
], ],
services: ['sauce'], services: ['sauce'],

View File

@ -9,18 +9,13 @@ Config for running saucelabs against localhost
exports.config = Object.assign({}, common.config, { exports.config = Object.assign({}, common.config, {
maxInstances: 2, maxInstances: 2,
exclude: [path.join(__dirname, './integration/download-tests.js')],
capabilities: [ capabilities: [
{ browserName: 'firefox' }, { browserName: 'firefox' },
{ browserName: 'chrome' }, { browserName: 'chrome' },
{ browserName: 'MicrosoftEdge' }, { browserName: 'MicrosoftEdge' },
{ {
browserName: 'safari', browserName: 'safari'
exclude: [
// The safari driver doesn't support file uploads
// via input elements, but unit-tests.js covers
// the lower level uploading
path.join(__dirname, './ui/upload-tests.js')
]
} }
], ],
services: ['sauce', require('./testServer')], services: ['sauce', require('./testServer')],