Test sweep (#420)

* Big ole test re-jig

* Current work

* Moving all tests over to the test runner

* Fixing last nits in the build and test runner

* Adding precaching integration tests

* Moving sw-appcache-behavior to integration test

* Adding bg-sync to test suite again - incoming fails

* Fixing the last pieces of the test sweep

* Removing logs

* Removing number of repeats in tests - should be determined by the individual tests - not the runner

* Small move around with sw-appcache

* Retry the end to end-to-end test
This commit is contained in:
Matt Gaunt
2017-04-07 10:59:53 -07:00
committed by Addy Osmani
parent 0342d41e66
commit 1f62f7a2b3
78 changed files with 779 additions and 1456 deletions
+24 -1
View File
@@ -14,18 +14,31 @@
*/
const path = require('path');
const gulp = require('gulp');
const chalk = require('chalk');
const promisify = require('promisify-node');
const {taskHarness, buildJSBundle} = require('../utils/build');
const fsePromise = promisify('fs-extra');
const printHeading = (heading) => {
/* eslint-disable no-console */
process.stdout.write(chalk.inverse(` ⚒️ ${heading} `));
/* eslint-enable no-console */
};
const printBuildTime = (buildTime) => {
process.stdout.write(chalk.inverse(`${buildTime} \n`));
};
/**
* Buids a given project.
* @param {String} projectPath The path to a project directory.
* @return {Promise} Resolves if building succeeds, rejects if it fails.
*/
const buildPackage = (projectPath) => {
printHeading(`Building ${path.basename(projectPath)}`);
const startTime = Date.now();
const buildDir = `${projectPath}/build`;
// Copy over package.json and README.md so that build/ contains what we
@@ -40,6 +53,9 @@ const buildPackage = (projectPath) => {
return fsePromise.copy(
path.join(__dirname, '..', 'LICENSE'),
path.join(projectPath, 'LICENSE'));
})
.then(() => {
printBuildTime(((Date.now() - startTime) / 1000) + 's');
});
};
@@ -57,7 +73,14 @@ gulp.task('build:shared', () => {
});
gulp.task('build', () => {
return taskHarness(buildPackage, global.projectOrStar);
// Start a new line before the build package logs start.
console.log();
return taskHarness(buildPackage, global.projectOrStar)
.then(() => {
// End new line before the rest of logs start
console.log();
});
});
gulp.task('build:watch', ['build'], (unusedCallback) => {
+2 -2
View File
@@ -16,10 +16,10 @@
/* eslint-disable no-console, valid-jsdoc */
const gulp = require('gulp');
const testServer = require('../utils/test-server.js');
const testServerGen = require('../utils/test-server-generator.js');
gulp.task('serve', (unusedCallback) => {
return testServer.start('.', global.port)
return testServerGen().start('.', global.port)
.then((port) => {
console.log(`Primary Server http://localhost:${port}/`);
console.log(`Secondary Server http://localhost:${port + 1}/`);
+10 -11
View File
@@ -15,7 +15,6 @@
const seleniumAssistant = require('selenium-assistant');
const gulp = require('gulp');
const mocha = require('gulp-spawn-mocha');
const glob = require('glob');
const runSequence = require('run-sequence');
gulp.task('download-browsers', function() {
@@ -38,18 +37,18 @@ gulp.task('download-browsers', function() {
});
});
gulp.task('mocha', ['build', 'download-browsers'], () => {
const mochaOptions = {};
gulp.task('mocha', ['build'], () => {
const mochaOptions = {
env: {
projectOrStar: global.projectOrStar,
},
};
if (global.cliOptions.grep) {
mochaOptions.grep = global.cliOptions.grep;
}
const testGlob = `packages/${global.projectOrStar}/test/*.js`;
const testFiles = glob.sync(testGlob);
if (testFiles.length === 0) {
// Mocha fails when no tests are found so return early.
return;
}
return gulp.src(testGlob, {read: false})
return gulp.src('test/bootstrap.js', {read: false})
.pipe(mocha(mochaOptions))
.once('error', (error) => {
console.error(error);
@@ -57,6 +56,6 @@ gulp.task('mocha', ['build', 'download-browsers'], () => {
});
});
gulp.task('test', ['lint'], (callback) => {
gulp.task('test', ['lint', 'download-browsers'], (callback) => {
runSequence('mocha', callback);
});
+5 -1
View File
@@ -1,7 +1,11 @@
{
"env": {
"mocha": true
},
"rules": {
"no-invalid-this": 0,
"no-console": 0,
"valid-jsdoc": 0
"valid-jsdoc": 0,
"max-len": 0,
}
}
@@ -16,30 +16,18 @@
'use strict';
/* eslint-env node, mocha, browser, serviceworker */
/* eslint-disable max-len, no-unused-expressions */
// These tests make use of selenium-webdriver. You can find the relevant
// documentation here: http://selenium.googlecode.com/git/docs/api/javascript/index.html
const chai = require('chai');
const parseManifest = require('parse-appcache-manifest');
const path = require('path');
const promisify = require('promisify-node');
const seleniumAssistant = require('selenium-assistant');
const fs = require('fs');
const testServer = require('../../../utils/test-server');
// Ensure the selenium drivers are added Node scripts path.
require('geckodriver');
require('chromedriver');
const testServerGen = require('../../../../utils/test-server-generator');
const fsePromise = promisify('fs-extra');
const expect = chai.expect;
const TIMEOUT = 10 * 1000;
const RETRIES = 3;
let tempDirectory = path.join(__dirname, 'end-to-end-caching', 'temp');
let tempDirectory = path.join(__dirname, '..', 'end-to-end-caching', 'temp');
// Helper method to generate the text of an App Cache manifest with a
// specific version.
@@ -69,18 +57,27 @@ const generateInitialManifests = () => {
return Promise.all(fileCreationPromisees);
};
const configureTestSuite = function(browser) {
let globalDriverReference = null;
let baseTestUrl;
module.exports = (webdriverCb) => {
describe(`sw-appcache-behavior Integration Test`, function() {
this.timeout(10 * 1000);
this.retries(3);
describe(`sw-appcache-behavior Test Suite with (${browser.getPrettyName()} - ${browser.getVersionNumber()})`, function() {
this.timeout(TIMEOUT);
this.retries(RETRIES);
let testServer;
let baseTestUrl;
let webdriverInstance;
// Set up the web server before running any tests in this suite.
before(function() {
const buildFile = path.join(__dirname, '..', 'build',
webdriverInstance = webdriverCb();
if (!webdriverInstance) {
throw new Error('Unable to get web driver instance.');
}
webdriverInstance.manage().timeouts().setScriptTimeout(10 * 1000);
const buildFile = path.join(__dirname, '..', '..', 'build',
'client-runtime.js');
try {
fs.accessSync(buildFile, fs.F_OK);
} catch (err) {
@@ -88,43 +85,34 @@ const configureTestSuite = function(browser) {
'build this project before running any tests.');
}
return generateInitialManifests()
.then(() => {
return testServer.start('.');
testServer = testServerGen();
return testServer.start('.', 5050);
})
.then((portNumber) => {
baseTestUrl = `http://localhost:${portNumber}/packages/sw-appcache-behavior/test/`;
console.log('Test Server: ' + baseTestUrl);
console.log('');
});
});
// Kill the web server once all tests are complete.
after(function() {
return seleniumAssistant.killWebDriver(globalDriverReference)
.then(() => {
return testServer.stop();
})
.then(() => {
return fsePromise.remove(tempDirectory);
});
});
const promises = [
fsePromise.remove(tempDirectory),
];
if (testServer) {
promises.push(testServer.stop());
}
it('should be able to get a global driver.', function() {
return browser.getSeleniumDriver()
.then((driver) => {
globalDriverReference = driver;
globalDriverReference.manage().timeouts().setScriptTimeout(TIMEOUT);
});
return Promise.all(promises);
});
it('should register a service worker to control the client', function() {
const url = `${baseTestUrl}end-to-end-caching/step1.html`;
return globalDriverReference.get(url)
return webdriverInstance.get(url)
.then(() => {
return globalDriverReference.wait(() => {
return globalDriverReference.executeScript(() => {
return webdriverInstance.wait(() => {
return webdriverInstance.executeScript(() => {
if (navigator.serviceWorker.controller) {
return true;
}
@@ -134,7 +122,7 @@ const configureTestSuite = function(browser) {
});
})
.then(() => {
return globalDriverReference.executeScript(() => {
return webdriverInstance.executeScript(() => {
return navigator.serviceWorker.controller;
});
})
@@ -145,7 +133,7 @@ const configureTestSuite = function(browser) {
});
it('should create one cache', function() {
return globalDriverReference.executeAsyncScript((callback) => {
return webdriverInstance.executeAsyncScript((callback) => {
window.caches.keys().then(callback);
})
.then((caches) => {
@@ -154,11 +142,11 @@ const configureTestSuite = function(browser) {
});
it('should cache items in the CACHE section of the manifest', function() {
const manifestContent = fs.readFileSync(path.join(__dirname, 'end-to-end-caching', 'temp', 'manifest1.appcache')).toString();
const manifestContent = fs.readFileSync(path.join(__dirname, '..', 'end-to-end-caching', 'temp', 'manifest1.appcache')).toString();
const parsedManifest = parseManifest(manifestContent);
expect(parsedManifest.cache).to.have.length.above(0);
return globalDriverReference.executeAsyncScript((entries, callback) => {
return webdriverInstance.executeAsyncScript((entries, callback) => {
Promise.all(
entries.map((entry) => {
// The App Cache manifest URL is the base for any relative URLs.
@@ -177,7 +165,7 @@ const configureTestSuite = function(browser) {
});
it('should cache a master entry for initial navigation', function() {
return globalDriverReference.executeAsyncScript((callback) => {
return webdriverInstance.executeAsyncScript((callback) => {
window.caches.match(window.location).then(callback);
})
.then((match) => {
@@ -192,9 +180,9 @@ const configureTestSuite = function(browser) {
it('should cache another master entry for subsequent navigation', function() {
const url = `${baseTestUrl}end-to-end-caching/step2.html`;
return globalDriverReference.get(url)
return webdriverInstance.get(url)
.then(() => {
return globalDriverReference.executeAsyncScript((callback) => {
return webdriverInstance.executeAsyncScript((callback) => {
window.setTimeout(() => {
window.caches.match(window.location).then(callback);
}, 100); // Timeouts... ugh.
@@ -207,9 +195,9 @@ const configureTestSuite = function(browser) {
it('should not cache a master entry when there is no manifest', function() {
const url = `${baseTestUrl}end-to-end-caching/step3.html`;
return globalDriverReference.get(url)
return webdriverInstance.get(url)
.then(() => {
return globalDriverReference.executeAsyncScript((callback) => {
return webdriverInstance.executeAsyncScript((callback) => {
window.setTimeout(() => {
window.caches.match(window.location).then(callback);
}, 100); // Timeouts... ugh.
@@ -221,7 +209,7 @@ const configureTestSuite = function(browser) {
});
it('should use a different cache when an existing manifest is updated', function() {
return globalDriverReference.executeAsyncScript((callback) => {
return webdriverInstance.executeAsyncScript((callback) => {
window.caches.keys().then(callback);
})
.then((previousCaches) => {
@@ -230,9 +218,9 @@ const configureTestSuite = function(browser) {
// update flow.
const outputPath = path.join(tempDirectory, 'manifest1.appcache');
return fsePromise.outputFile(outputPath, generateManifestText(2))
.then(() => globalDriverReference.get(url))
.then(() => webdriverInstance.get(url))
.then(() => {
return globalDriverReference.executeAsyncScript((callback) => {
return webdriverInstance.executeAsyncScript((callback) => {
window.setTimeout(() => {
// This will resolve with an array of arrays, with each item
// in the inner array corresponding to a cache entry.
@@ -251,12 +239,12 @@ const configureTestSuite = function(browser) {
});
it('should use a different cache when the manifest is different', function() {
return globalDriverReference.executeAsyncScript((callback) => {
return webdriverInstance.executeAsyncScript((callback) => {
window.caches.keys().then(callback);
}).then((previousCaches) => {
const url = `${baseTestUrl}end-to-end-caching/step4.html`;
return globalDriverReference.get(url).then(() => {
return globalDriverReference.executeAsyncScript((callback) => {
return webdriverInstance.get(url).then(() => {
return webdriverInstance.executeAsyncScript((callback) => {
window.setTimeout(() => window.caches.keys().then(callback), 100);
}).then((currentCaches) => {
// This is a roundabout way of checking to make sure there's one
@@ -271,15 +259,3 @@ const configureTestSuite = function(browser) {
});
});
};
seleniumAssistant.getLocalBrowsers().forEach(function(browser) {
switch (browser.getId()) {
case 'chrome':
case 'firefox':
configureTestSuite(browser);
break;
default:
console.warn(`Skipping ${browser.getPrettyName()}.`);
break;
}
});
@@ -4,5 +4,6 @@
"no-console": 0,
"valid-jsdoc": 0,
"require-jsdoc": 0,
"max-len": 0
}
}
@@ -1,96 +0,0 @@
/*
Copyright 2016 Google Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
'use strict';
/* eslint-env node, mocha, browser, serviceworker */
/* eslint-disable max-len, no-unused-expressions */
// These tests make use of selenium-webdriver. You can find the relevant
// documentation here: http://selenium.googlecode.com/git/docs/api/javascript/index.html
const seleniumAssistant = require('selenium-assistant');
const swTestingHelpers = require('sw-testing-helpers');
const testServer = new swTestingHelpers.TestServer();
const TIMEOUT = 10 * 1000;
const RETRIES = 3;
const configureTestSuite = function(browser) {
let globalDriverReference = null;
let baseTestUrl;
describe(`sw-background-sync-queue Test Suite with (${browser.getPrettyName()} - ${browser.getVersionNumber()})`, function() {
this.retries(RETRIES);
this.timeout(TIMEOUT);
// Set up the web server before running any tests in this suite.
before(function() {
return testServer.startServer('.').then((portNumber) => {
baseTestUrl = `http://localhost:${portNumber}/packages/sw-background-sync-queue/test/`;
});
});
// Kill the web server once all tests are complete.
after(function() {
return testServer.killServer();
});
afterEach(function() {
this.timeout(6000);
return seleniumAssistant.killWebDriver(globalDriverReference)
.then(() => {
globalDriverReference = null;
});
});
it('should pass all tests', function() {
return browser.getSeleniumDriver()
.then((driver) => {
globalDriverReference = driver;
globalDriverReference.manage().timeouts().setScriptTimeout(TIMEOUT);
})
.then(() => {
return swTestingHelpers.mochaUtils.startWebDriverMochaTests(
browser.getPrettyName(),
globalDriverReference,
`${baseTestUrl}unit/`
);
})
.then((testResults) => {
console.log(
swTestingHelpers.mochaUtils.prettyPrintResults(testResults)
);
if (testResults.failed.length > 0) {
throw new Error('Some of the browser tests failed');
}
});
});
});
};
(function(browser) {
switch (browser.getId()) {
case 'chrome':
case 'firefox':
configureTestSuite(browser);
break;
default:
console.warn(`Skipping ${browser.getPrettyName()}.`);
break;
}
})(seleniumAssistant.getLocalBrowsers()[0]);
@@ -31,6 +31,17 @@ describe('queue-utils test', () => {
maxAge: maxAgeTimeStamp,
};
beforeEach(function() {
const idbHelper = new goog.backgroundSyncQueue.test.IDBHelper(
'bgQueueSyncDB', 1, 'QueueStore');
return idbHelper.getAllKeys()
.then((keys) => {
keys.forEach((key) => {
idbHelper.delete(key);
});
});
});
it('test queueableRequest', () => {
const request = new Request('http://localhost:3001/__echo/date-with-cors/random');
return queueUtils.getQueueableRequest({
@@ -18,9 +18,15 @@
describe('response-manager test', () => {
const response = 'VALUE';
const idbHelper = new goog.backgroundSyncQueue.test.IDBHelper(
'bgQueueSyncDB', 1, 'QueueStore');
const resManager = goog.backgroundSyncQueue.test.responseManager;
let idbHelper;
let resManager;
before(() => {
idbHelper = new goog.backgroundSyncQueue.test.IDBHelper(
'bgQueueSyncDB', 1, 'QueueStore');
resManager = goog.backgroundSyncQueue.test.responseManager;
});
it('check get', () => {
return idbHelper.put('key', {response: response}).then(()=>{
return resManager.getResponse({id: 'key'}).then((data)=>{
@@ -0,0 +1,18 @@
{
"browser": {
"scripts": [
"/node_modules/mockdate/src/mockdate.js",
"/node_modules/sinon/pkg/sinon.js",
"/packages/sw-background-sync-queue/build/test/idb-helper.js",
"/packages/sw-background-sync-queue/build/test/constants.js",
"/packages/sw-background-sync-queue/build/test/request-queue.js",
"/packages/sw-background-sync-queue/build/test/request-manager.js",
"/packages/sw-background-sync-queue/build/test/response-manager.js",
"/packages/sw-background-sync-queue/build/test/background-sync-queue.js",
"/packages/sw-background-sync-queue/build/test/background-sync-idb-helper.js",
"/packages/sw-background-sync-queue/build/test/queue-utils.js",
"/packages/sw-background-sync-queue/build/test/broadcast-manager.js",
"/packages/sw-background-sync-queue/build/test/sw-background-queue.js"
]
}
}
@@ -1,88 +0,0 @@
<!--
Copyright 2016 Google Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<html>
<head>
<meta charset="utf-8">
<title>SW Helpers Tests</title>
<link href="/node_modules/mocha/mocha.css" rel="stylesheet" />
<!--
iframes are used to manage service worker scoping.
This will hide them and stop the page from jumping around
-->
<style>
iframe {
width: 0;
height: 0;
}
</style>
</head>
<body>
<div id="mocha"></div>
<script src="/node_modules/chai/chai.js"></script>
<script src="/node_modules/mocha/mocha.js"></script>
<!-- sw-testing-helpers -->
<script src="/packages/sw-background-sync-queue/build/test/idb-helper.js"></script>
<script src="/node_modules/sw-testing-helpers/build/browser/mocha-utils.js"></script>
<script src="/node_modules/sw-testing-helpers/build/browser/sw-utils.js"></script>
<script src="/node_modules/mockdate/src/mockdate.js"></script>
<script src="/node_modules/sinon/pkg/sinon.js"></script>
<script src="/packages/sw-background-sync-queue/build/test/constants.js"></script>
<script src="/packages/sw-background-sync-queue/build/test/request-queue.js"></script>
<script src="/packages/sw-background-sync-queue/build/test/request-manager.js"></script>
<script src="/packages/sw-background-sync-queue/build/test/response-manager.js"></script>
<script src="/packages/sw-background-sync-queue/build/test/background-sync-queue.js"></script>
<script src="/packages/sw-background-sync-queue/build/test/background-sync-idb-helper.js"></script>
<script src="/packages/sw-background-sync-queue/build/test/queue-utils.js"></script>
<script src="/packages/sw-background-sync-queue/build/test/broadcast-manager.js"></script>
<script src="/packages/sw-background-sync-queue/build/test/sw-background-queue.js"></script>
<!--
Timeout is extended to ensure tests for max-cache-age
have enough time to complete
-->
<script>mocha.setup({
ui: 'bdd',
timeout: 10000
})</script>
<!-- In browser test scripts should be added to the page here-->
<script src="request-queue.js"></script>
<script src="background-sync-queue.js"></script>
<script src="background-sync-idb-helper.js"></script>
<script src="request-manager.js"></script>
<script src="broadcast-manager.js"></script>
<script src="queue-utils.js"></script>
<script src="response-manager.js"></script>
<script>
(function() {
// This make browsers without a service worker pass tests by
// bypassing the tests altogether.
// This is desirable to allow travis to run tests in all browsers
// regardless of support or not and perform tests when the browser
// starts to support service workers.
if (!('serviceWorker' in navigator)) {
publishTestResults();
return;
}
window.goog.mochaUtils.startInBrowserMochaTests().then(results => {
window.testsuite = results;
});
})();
</script>
</body>
</html>
@@ -1,69 +0,0 @@
/*
Copyright 2017 Google Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
const seleniumAssistant = require('selenium-assistant');
const swTestingHelpers = require('sw-testing-helpers');
const testServer = require('../../../utils/test-server.js');
const RETRIES = 3;
const TIMEOUT = 10 * 1000;
const packageName = 'sw-broadcast-cache-update';
describe(`${packageName} Browser Tests`, function() {
this.retries(RETRIES);
this.timeout(TIMEOUT);
let globalDriverBrowser;
let testHarnessUrl;
// Set up the web server before running any tests in this suite.
before(() => testServer.start('.').then((portNumber) => {
testHarnessUrl = `http://localhost:${portNumber}/__test/mocha/${packageName}`;
}));
// Kill the web server once all tests are complete.
after(() => testServer.stop());
afterEach(() => seleniumAssistant.killWebDriver(globalDriverBrowser)
.then(() => globalDriverBrowser = null));
const setupTestSuite = (assistantDriver) => {
it(`should pass all tests in ${assistantDriver.getPrettyName()}`, () => {
return assistantDriver.getSeleniumDriver()
.then((driver) => globalDriverBrowser = driver)
.then(() => swTestingHelpers.mochaUtils.startWebDriverMochaTests(
assistantDriver.getPrettyName(),
globalDriverBrowser,
testHarnessUrl
)).then((testResults) => {
console.log(swTestingHelpers.mochaUtils.prettyPrintResults(testResults));
if (testResults.failed.length > 0) {
throw new Error('Some of the browser tests failed.');
}
});
});
};
seleniumAssistant.getLocalBrowsers().forEach((browser) => {
switch(browser.getId()) {
case 'chrome':
case 'firefox':
setupTestSuite(browser);
break;
default:
console.log(`Skipping tests for ${browser.getId()}.`);
}
});
});
@@ -1,16 +0,0 @@
describe('Service Worker Unit Test Registration', function() {
const pathPrefix = '../sw/';
const swUnitTests = [
'broadcast-cache-update.js',
'broadcast-cache-update-plugin.js',
'broadcast-update.js',
'namespace.js',
'responses-are-same.js',
].map((script) => `${pathPrefix}${script}`);
swUnitTests.forEach(function(swUnitTestPath) {
it(`should register ${swUnitTestPath}`, function() {
return goog.mochaUtils.registerServiceWorkerMochaTests(swUnitTestPath);
});
});
});
@@ -4,7 +4,7 @@ const depcheck = require('depcheck');
describe('Test Dependencies', function() {
it('should have required dependencies', function() {
return new Promise((resolve, reject) => {
depcheck(path.join(__dirname, '..'), {
depcheck(path.join(__dirname, '..', '..'), {
ignoreDirs: [
'test',
'build',
@@ -1,7 +1,7 @@
const proxyquire = require('proxyquire');
const swBuild = require('../src/index.js');
const errors = require('../src/lib/errors');
const swBuild = require('../../src/index.js');
const errors = require('../../src/lib/errors');
describe('Test generateFileManifest', function() {
const EXAMPLE_INPUT = {
@@ -46,7 +46,7 @@ describe('Test generateFileManifest', function() {
size: 2,
}];
const generateFileManifest = proxyquire(
'../src/lib/generate-file-manifest.js', {
'../../src/lib/generate-file-manifest.js', {
'./get-file-manifest-entries': ({rootDirectory, staticFileGlobs, globIgnores}) => {
if (globIgnores !== EXAMPLE_INPUT.globIgnores) {
throw new Error('Invalid glob ignores value.');
@@ -1,13 +1,14 @@
const path = require('path');
const fs = require('fs');
const fsExtra = require('fs-extra');
const testServer = require('../../../utils/test-server.js');
const validator = require('../../sw-cli/test/utils/e2e-sw-validator.js');
const testServerGen = require('../../../../utils/test-server-generator.js');
const validator = require('../../../sw-cli/test/utils/e2e-sw-validator.js');
require('chai').should();
describe('Generate SW End-to-End Tests', function() {
let tmpDirectory;
let testServer;
let baseTestUrl;
// NOTE: No JPG
const FILE_EXTENSIONS = ['html', 'css', 'js', 'png'];
@@ -22,7 +23,8 @@ describe('Generate SW End-to-End Tests', function() {
path.join(__dirname, 'tmp-')
);
return testServer.start(tmpDirectory)
testServer = testServerGen();
return testServer.start(tmpDirectory, 5050)
.then((portNumber) => {
baseTestUrl = `http://localhost:${portNumber}`;
});
@@ -36,16 +38,17 @@ describe('Generate SW End-to-End Tests', function() {
it('should be able to generate a service for example-1 with sw-build', function() {
this.timeout(120 * 1000);
this.retries(2);
process.chdir(tmpDirectory);
fsExtra.copySync(
path.join(__dirname, '..', '..', 'sw-cli', 'test', 'static', 'example-project-1'),
path.join(__dirname, '..', '..', '..', 'sw-cli', 'test', 'static', 'example-project-1'),
tmpDirectory);
const swName = `${Date.now()}-sw.js`;
const swBuild = require('../build/index.js');
const swBuild = require('../../build/index.js');
return validator.performTest(() => {
return swBuild.generateSW({
rootDirectory: tmpDirectory,
@@ -1,7 +1,7 @@
const proxyquire = require('proxyquire');
const path = require('path');
const errors = require('../src/lib/errors');
const errors = require('../../src/lib/errors');
describe('Test generateSW()', function() {
const EXAMPLE_INPUT = {
@@ -17,7 +17,7 @@ describe('Test generateSW()', function() {
let generateSW;
beforeEach(function() {
generateSW = proxyquire('../src/lib/generate-sw', {
generateSW = proxyquire('../../src/lib/generate-sw', {
'./utils/copy-sw-lib': (rootDirectory) => {
if (rootDirectory === EXAMPLE_INPUT.rootDirectory) {
return Promise.resolve(path.join(rootDirectory, 'sw-lib.v0.0.0.js'));
@@ -186,7 +186,7 @@ describe('Test generateSW()', function() {
let args = Object.assign({}, EXAMPLE_INPUT);
args.rootDirectory = '.';
generateSW = proxyquire('../src/lib/generate-sw', {
generateSW = proxyquire('../../src/lib/generate-sw', {
'./utils/copy-sw-lib': (rootDirectory) => {
if (rootDirectory === '.') {
return Promise.resolve(path.join(rootDirectory, 'sw-lib.v0.0.0.js'));
@@ -212,7 +212,7 @@ describe('Test generateSW()', function() {
// rootDirectory - valid nested folder
it('should be able to write service worker to the a directory', function() {
generateSW = proxyquire('../src/lib/generate-sw', {
generateSW = proxyquire('../../src/lib/generate-sw', {
'./utils/copy-sw-lib': (rootDirectory) => {
if (rootDirectory === EXAMPLE_INPUT.rootDirectory) {
return Promise.resolve(path.join(rootDirectory, 'sw-lib.v0.0.0.js'));
@@ -1,7 +1,7 @@
const path = require('path');
const swBuild = require('../src/index.js');
const errors = require('../src/lib/errors');
const swBuild = require('../../src/index.js');
const errors = require('../../src/lib/errors');
require('chai').should();
@@ -89,7 +89,7 @@ describe('Test getFileManifestEntries', function() {
staticFileGlobs: [
'**/*.{html,js,css}',
],
rootDirectory: path.join(__dirname, '..', '..',
rootDirectory: path.join(__dirname, '..', '..', '..',
'sw-cli', 'test', 'static', 'example-project-1'),
};
@@ -121,7 +121,7 @@ describe('Test getFileManifestEntries', function() {
staticFileGlobs: [
'**/*.{html,js,css}',
],
rootDirectory: path.join(__dirname, '..', '..',
rootDirectory: path.join(__dirname, '..', '..', '..',
'sw-cli', 'test', 'static', 'example-project-1'),
modifyUrlPrefix: {
'/styles': '/static/styles',
@@ -2,8 +2,8 @@ const path = require('path');
const fs = require('fs');
const fsExtra = require('fs-extra');
const errors = require('../src/lib/errors');
const swBuild = require('../build/index.js');
const errors = require('../../src/lib/errors');
const swBuild = require('../../build/index.js');
describe('Test Injection Manifest', function() {
let tmpDirectory;
@@ -39,7 +39,7 @@ describe('Test Injection Manifest', function() {
it(`should be able to read and inject in doc ${docName}`, function() {
return swBuild.injectManifest({
dest: tmpDirectory,
rootDirectory: path.join(__dirname, 'static', 'injection-samples'),
rootDirectory: path.join(__dirname, '..', 'static', 'injection-samples'),
staticFileGlobs: ['**\/*.{html,css}'],
swFile: docName,
})
@@ -58,7 +58,7 @@ describe('Test Injection Manifest', function() {
it(`should throw due to no injection point in bad-no-injection.js`, function() {
return swBuild.injectManifest({
dest: tmpDirectory,
rootDirectory: path.join(__dirname, 'static', 'injection-samples'),
rootDirectory: path.join(__dirname, '..', 'static', 'injection-samples'),
staticFileGlobs: ['**\/*.{html,css}'],
swFile: 'bad-no-injection.js',
})
@@ -76,7 +76,7 @@ describe('Test Injection Manifest', function() {
it(`should throw due to no injection point in bad-multiple-injection.js`, function() {
return swBuild.injectManifest({
dest: tmpDirectory,
rootDirectory: path.join(__dirname, 'static', 'injection-samples'),
rootDirectory: path.join(__dirname, '..', 'static', 'injection-samples'),
staticFileGlobs: ['**\/*.{html,css}'],
swFile: 'bad-multiple-injection.js',
})
@@ -1,6 +1,6 @@
const proxyquire = require('proxyquire');
const errors = require('../src/lib/errors.js');
const errors = require('../../src/lib/errors.js');
require('chai').should();
@@ -9,7 +9,7 @@ describe('src/lib/utils/write-file-manifest.js', function() {
const FAKE_PATH = 'fake-path/manifest-name.js';
it('should handle a bad manifest format', function() {
const writeFileManifest = require('../src/lib/utils/write-file-manifest');
const writeFileManifest = require('../../src/lib/utils/write-file-manifest');
return writeFileManifest(FAKE_PATH, [], 'invalid-format')
.then(() => {
throw new Error('Expected error to be thrown.');
@@ -31,7 +31,7 @@ describe('src/lib/utils/write-file-manifest.js', function() {
null,
undefined,
];
const writeFileManifest = require('../src/lib/utils/write-file-manifest');
const writeFileManifest = require('../../src/lib/utils/write-file-manifest');
badInputs.reduce((promiseChain, badInput) => {
return promiseChain.then(() => {
return writeFileManifest(badInput, [])
@@ -64,7 +64,7 @@ describe('src/lib/utils/write-file-manifest.js', function() {
}],
[{}],
];
const writeFileManifest = require('../src/lib/utils/write-file-manifest');
const writeFileManifest = require('../../src/lib/utils/write-file-manifest');
return badInputs.reduce((promiseChain, badInput) => {
return promiseChain.then(() => {
return writeFileManifest('manifest.js', badInput)
@@ -81,7 +81,7 @@ describe('src/lib/utils/write-file-manifest.js', function() {
});
it('should handle failing mkdirp.sync', function() {
const writeFileManifest = proxyquire('../src/lib/utils/write-file-manifest', {
const writeFileManifest = proxyquire('../../src/lib/utils/write-file-manifest', {
mkdirp: (dirname, cb) => {
cb(INJECTED_ERROR);
},
@@ -99,7 +99,7 @@ describe('src/lib/utils/write-file-manifest.js', function() {
});
it('should handle fs.readFile error when checking template', function() {
const writeFileManifest = proxyquire('../src/lib/utils/write-file-manifest', {
const writeFileManifest = proxyquire('../../src/lib/utils/write-file-manifest', {
mkdirp: (dirname, cb) => {
cb();
},
@@ -122,7 +122,7 @@ describe('src/lib/utils/write-file-manifest.js', function() {
});
it('should handle error when populating template', function() {
const writeFileManifest = proxyquire('../src/lib/utils/write-file-manifest', {
const writeFileManifest = proxyquire('../../src/lib/utils/write-file-manifest', {
'mkdirp': (dirname, cb) => {
cb();
},
@@ -148,7 +148,7 @@ describe('src/lib/utils/write-file-manifest.js', function() {
});
it('should handle error writing file', function() {
const writeFileManifest = proxyquire('../src/lib/utils/write-file-manifest', {
const writeFileManifest = proxyquire('../../src/lib/utils/write-file-manifest', {
'mkdirp': (dirname, cb) => {
cb();
},
@@ -1,5 +1,5 @@
const proxyquire = require('proxyquire');
const errors = require('../src/lib/errors.js');
const errors = require('../../src/lib/errors.js');
require('chai').should();
@@ -14,7 +14,7 @@ describe('lib/write-sw.js', function() {
});
it('should handle failing mkdirp.sync', function() {
const writeSw = proxyquire('../src/lib/write-sw', {
const writeSw = proxyquire('../../src/lib/write-sw', {
mkdirp: {
sync: () => {
throw INJECTED_ERROR;
@@ -43,7 +43,7 @@ describe('lib/write-sw.js', function() {
});
it('should handle fs.readFile error when checking template', function() {
const writeSw = proxyquire('../src/lib/write-sw', {
const writeSw = proxyquire('../../src/lib/write-sw', {
mkdirp: {
sync: () => {
return;
@@ -77,7 +77,7 @@ describe('lib/write-sw.js', function() {
});
it('should handle error when populating template', function() {
const writeSw = proxyquire('../src/lib/write-sw', {
const writeSw = proxyquire('../../src/lib/write-sw', {
'mkdirp': {
sync: () => {
return;
@@ -114,7 +114,7 @@ describe('lib/write-sw.js', function() {
});
it('should handle error writing file', function() {
const writeSw = proxyquire('../src/lib/write-sw', {
const writeSw = proxyquire('../../src/lib/write-sw', {
'mkdirp': {
sync: () => {
return;
@@ -1,6 +1,6 @@
const proxyquire = require('proxyquire');
const path = require('path');
const errors = require('../src/lib/errors.js');
const errors = require('../../src/lib/errors.js');
require('chai').should();
@@ -18,7 +18,7 @@ describe('Copy SW Lib', function() {
},
pipe: (stream) => stream,
};
const copySWLib = proxyquire('../src/lib/utils/copy-sw-lib', {
const copySWLib = proxyquire('../../src/lib/utils/copy-sw-lib', {
mkdirp: {
sync: () => {
return;
@@ -56,7 +56,7 @@ describe('Copy SW Lib', function() {
},
pipe: (stream) => stream,
};
const copySWLib = proxyquire('../src/lib/utils/copy-sw-lib', {
const copySWLib = proxyquire('../../src/lib/utils/copy-sw-lib', {
mkdirp: {
sync: () => {
return;
@@ -1,5 +1,5 @@
const constants = require('../src/lib/constants');
const filterFiles = require('../src/lib/utils/filter-files');
const constants = require('../../src/lib/constants');
const filterFiles = require('../../src/lib/utils/filter-files');
require('chai').should();
@@ -1,4 +1,4 @@
const getStringDetails = require('../src/lib/utils/get-string-details');
const getStringDetails = require('../../src/lib/utils/get-string-details');
require('chai').should();
describe('src/lib/utils/get-string-details.js', function() {
@@ -1,7 +1,7 @@
const proxyquire = require('proxyquire');
const path = require('path');
const errors = require('../src/lib/errors.js');
const errors = require('../../src/lib/errors.js');
require('chai').should();
@@ -9,7 +9,7 @@ describe('src/lib/utils/get-file-details.js', function() {
const INJECTED_ERROR = new Error('Injected Error');
it('should handle glob sync error', function() {
const getFileDetails = proxyquire('../src/lib/utils/get-file-details', {
const getFileDetails = proxyquire('../../src/lib/utils/get-file-details', {
glob: {
sync: () => {
throw INJECTED_ERROR;
@@ -37,7 +37,7 @@ describe('src/lib/utils/get-file-details.js', function() {
const OK_FILE_1 = 'ok.txt';
const OK_FILE_2 = 'ok-2.txt';
const getFileDetails = proxyquire('../src/lib/utils/get-file-details', {
const getFileDetails = proxyquire('../../src/lib/utils/get-file-details', {
'glob': {
sync: () => {
return [
@@ -89,7 +89,7 @@ describe('src/lib/utils/get-file-details.js', function() {
'node_modules/',
];
const getFileDetails = proxyquire('../src/lib/utils/get-file-details', {
const getFileDetails = proxyquire('../../src/lib/utils/get-file-details', {
'glob': {
sync: (pattern, options) => {
if (options.ignore !== GLOB_IGNORE) {
@@ -1,14 +1,15 @@
const proxyquire = require('proxyquire');
const errors = require('../src/lib/errors.js');
const clearRequire = require('clear-require');
const errors = require('../../src/lib/errors.js');
require('chai').should();
describe('src/lib/utils/get-file-hash.js', function() {
const INJECTED_ERROR = new Error('Injected Error');
it('should handle readFileSync Error', function() {
const getFileHash = proxyquire('../src/lib/utils/get-file-hash', {
const getFileHash = proxyquire('../../src/lib/utils/get-file-hash', {
fs: {
readFileSync: () => {
throw INJECTED_ERROR;
@@ -29,7 +30,7 @@ describe('src/lib/utils/get-file-hash.js', function() {
});
it('should return string for valid file', function() {
const getFileHash = proxyquire('../src/lib/utils/get-file-hash', {
const getFileHash = proxyquire('../../src/lib/utils/get-file-hash', {
fs: {
readFileSync: (file) => {
if (file === 'fake-file.txt') {
@@ -48,8 +49,8 @@ describe('src/lib/utils/get-file-hash.js', function() {
it('should handle unexpected input', function() {
// Proxyquire's old version is used if we don't clear it.
clearRequire('../src/lib/utils/get-file-hash');
const getFileHash = require('../src/lib/utils/get-file-hash');
clearRequire('../../src/lib/utils/get-file-hash');
const getFileHash = require('../../src/lib/utils/get-file-hash');
const inputTests = [
null,
@@ -1,14 +1,15 @@
const proxyquire = require('proxyquire');
const errors = require('../src/lib/errors.js');
const clearRequire = require('clear-require');
const errors = require('../../src/lib/errors.js');
require('chai').should();
describe('src/lib/utils/get-file-size.js', function() {
const INJECTED_ERROR = new Error('Injected Error');
it('should handle erroring statSync', function() {
const getFileSize = proxyquire('../src/lib/utils/get-file-size', {
const getFileSize = proxyquire('../../src/lib/utils/get-file-size', {
fs: {
statSync: () => {
throw INJECTED_ERROR;
@@ -29,7 +30,7 @@ describe('src/lib/utils/get-file-size.js', function() {
});
it('should return null for non-files', function() {
const getFileSize = proxyquire('../src/lib/utils/get-file-size', {
const getFileSize = proxyquire('../../src/lib/utils/get-file-size', {
fs: {
statSync: () => {
return {
@@ -49,7 +50,7 @@ describe('src/lib/utils/get-file-size.js', function() {
it('should be able to get file details', function() {
const injectedSize = 1234;
const getFileSize = proxyquire('../src/lib/utils/get-file-size', {
const getFileSize = proxyquire('../../src/lib/utils/get-file-size', {
fs: {
statSync: () => {
return {
@@ -70,8 +71,8 @@ describe('src/lib/utils/get-file-size.js', function() {
it('should handle unexpected input', function() {
// Proxyquire's old version is used if we don't clear it.
clearRequire('../src/lib/utils/get-file-size');
const getFileSize = require('../src/lib/utils/get-file-size');
clearRequire('../../src/lib/utils/get-file-size');
const getFileSize = require('../../src/lib/utils/get-file-size');
const inputTests = [
null,
@@ -1,4 +1,4 @@
const getCompositeDetails = require('../src/lib/utils/get-composite-details');
const getCompositeDetails = require('../../src/lib/utils/get-composite-details');
require('chai').should();
describe('src/lib/utils/get-composite-details.js', function() {
@@ -1,4 +1,4 @@
const getStringHash = require('../src/lib/utils/get-string-hash');
const getStringHash = require('../../src/lib/utils/get-string-hash');
require('chai').should();
describe('src/lib/utils/get-string-hash.js', function() {
@@ -1,5 +1,5 @@
const modifyUrlPrefix = require('../src/lib/utils/modify-url-prefix');
const errors = require('../src/lib/errors');
const modifyUrlPrefix = require('../../src/lib/utils/modify-url-prefix');
const errors = require('../../src/lib/errors');
describe('Test modifyUrlPrefix Logic', function() {
const EXAMPLE_MODIFIERS = {
@@ -1,69 +0,0 @@
/*
Copyright 2017 Google Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
const seleniumAssistant = require('selenium-assistant');
const swTestingHelpers = require('sw-testing-helpers');
const testServer = require('../../../utils/test-server.js');
const RETRIES = 3;
const TIMEOUT = 10 * 1000;
const packageName = 'sw-cache-expiration';
describe(`${packageName} Browser Tests`, function() {
this.retries(RETRIES);
this.timeout(TIMEOUT);
let globalDriverBrowser;
let testHarnessUrl;
// Set up the web server before running any tests in this suite.
before(() => testServer.start('.').then((portNumber) => {
testHarnessUrl = `http://localhost:${portNumber}/__test/mocha/${packageName}`;
}));
// Kill the web server once all tests are complete.
after(() => testServer.stop());
afterEach(() => seleniumAssistant.killWebDriver(globalDriverBrowser)
.then(() => globalDriverBrowser = null));
const setupTestSuite = (assistantDriver) => {
it(`should pass all tests in ${assistantDriver.getPrettyName()}`, () => {
return assistantDriver.getSeleniumDriver()
.then((driver) => globalDriverBrowser = driver)
.then(() => swTestingHelpers.mochaUtils.startWebDriverMochaTests(
assistantDriver.getPrettyName(),
globalDriverBrowser,
testHarnessUrl
)).then((testResults) => {
console.log(swTestingHelpers.mochaUtils.prettyPrintResults(testResults));
if (testResults.failed.length > 0) {
throw new Error('Some of the browser tests failed.');
}
});
});
};
seleniumAssistant.getLocalBrowsers().forEach((browser) => {
switch(browser.getId()) {
case 'chrome':
case 'firefox':
setupTestSuite(browser);
break;
default:
console.log(`Skipping tests for ${browser.getId()}.`);
}
});
});
@@ -1,14 +0,0 @@
describe('Service Worker Unit Test Registration', function() {
const pathPrefix = '../sw/';
const swUnitTests = [
'namespace.js',
'cache-expiration.js',
'cache-expiration-plugin.js',
].map((script) => `${pathPrefix}${script}`);
swUnitTests.forEach(function(swUnitTestPath) {
it(`should register ${swUnitTestPath}`, function() {
return goog.mochaUtils.registerServiceWorkerMochaTests(swUnitTestPath);
});
});
});
@@ -1,70 +0,0 @@
/*
Copyright 2017 Google Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
const seleniumAssistant = require('selenium-assistant');
const swTestingHelpers = require('sw-testing-helpers');
const testServer = require('../../../utils/test-server.js');
const RETRIES = 3;
const TIMEOUT = 10 * 1000;
const PACKAGE_NAME = 'sw-cacheable-response';
describe(`${PACKAGE_NAME} Browser Tests`, function() {
this.retries(RETRIES);
this.timeout(TIMEOUT);
let globalDriverBrowser;
let testHarnessUrl;
// Set up the web server before running any tests in this suite.
before(() => testServer.start('.').then((portNumber) => {
testHarnessUrl = `http://localhost:${portNumber}/__test/mocha/` +
PACKAGE_NAME;
}));
// Kill the web server once all tests are complete.
after(() => testServer.stop());
afterEach(() => seleniumAssistant.killWebDriver(globalDriverBrowser)
.then(() => globalDriverBrowser = null));
const setupTestSuite = (assistantDriver) => {
it(`should pass all tests in ${assistantDriver.getPrettyName()}`, () => {
return assistantDriver.getSeleniumDriver()
.then((driver) => globalDriverBrowser = driver)
.then(() => swTestingHelpers.mochaUtils.startWebDriverMochaTests(
assistantDriver.getPrettyName(),
globalDriverBrowser,
testHarnessUrl
)).then((testResults) => {
console.log(swTestingHelpers.mochaUtils.prettyPrintResults(testResults));
if (testResults.failed.length > 0) {
throw new Error('Some of the browser tests failed.');
}
});
});
};
seleniumAssistant.getLocalBrowsers().forEach((browser) => {
switch(browser.getId()) {
case 'chrome':
case 'firefox':
setupTestSuite(browser);
break;
default:
console.log(`Skipping tests for ${browser.getId()}.`);
}
});
});
@@ -1,14 +0,0 @@
describe('Service Worker Unit Test Registration', function() {
const pathPrefix = '../sw/';
const swUnitTests = [
'cacheable-response.js',
'cacheable-response-plugin.js',
'namespace.js',
].map((script) => `${pathPrefix}${script}`);
swUnitTests.forEach(function(swUnitTestPath) {
it(`should register ${swUnitTestPath}`, function() {
return goog.mochaUtils.registerServiceWorkerMochaTests(swUnitTestPath);
});
});
});
@@ -1,14 +1,14 @@
const proxyquire = require('proxyquire');
const sinon = require('sinon');
const path = require('path');
const cliHelper = require('./utils/cli-test-helper.js');
const errors = require('../src/lib/errors.js');
const cliHelper = require('../utils/cli-test-helper.js');
const errors = require('../../src/lib/errors.js');
require('chai').should();
describe('Ask for File Extensions to Cache', function() {
const globalStubs = [];
const Q_PATH = '../src/lib/questions/ask-extensions-to-cache.js';
const Q_PATH = '../../src/lib/questions/ask-extensions-to-cache.js';
afterEach(function() {
cliHelper.endLogCapture();
@@ -1,14 +1,14 @@
const proxyquire = require('proxyquire');
const sinon = require('sinon');
const cliHelper = require('./utils/cli-test-helper.js');
const errors = require('../src/lib/errors.js');
const cliHelper = require('../utils/cli-test-helper.js');
const errors = require('../../src/lib/errors.js');
require('chai').should();
describe('Ask for File Manifest Name', function() {
const globalStubs = [];
const Q_PATH = '../src/lib/questions/ask-manifest-name.js';
const Q_PATH = '../../src/lib/questions/ask-manifest-name.js';
afterEach(function() {
cliHelper.endLogCapture();
@@ -1,14 +1,14 @@
const proxyquire = require('proxyquire');
const sinon = require('sinon');
const path = require('path');
const cliHelper = require('./utils/cli-test-helper.js');
const errors = require('../src/lib/errors.js');
const cliHelper = require('../utils/cli-test-helper.js');
const errors = require('../../src/lib/errors.js');
require('chai').should();
describe('Ask for Root Directory', function() {
const globalStubs = [];
const Q_PATH = '../src/lib/questions/ask-root-of-web-app.js';
const Q_PATH = '../../src/lib/questions/ask-root-of-web-app.js';
afterEach(function() {
cliHelper.endLogCapture();
@@ -1,13 +1,13 @@
const proxyquire = require('proxyquire');
const sinon = require('sinon');
const cliHelper = require('./utils/cli-test-helper.js');
const errors = require('../src/lib/errors.js');
const cliHelper = require('../utils/cli-test-helper.js');
const errors = require('../../src/lib/errors.js');
require('chai').should();
describe('Ask to Save to Config File', function() {
const globalStubs = [];
const Q_PATH = '../src/lib/questions/ask-save-config.js';
const Q_PATH = '../../src/lib/questions/ask-save-config.js';
afterEach(function() {
cliHelper.endLogCapture();
@@ -1,13 +1,13 @@
const proxyquire = require('proxyquire');
const sinon = require('sinon');
const cliHelper = require('./utils/cli-test-helper.js');
const errors = require('../src/lib/errors.js');
const cliHelper = require('../utils/cli-test-helper.js');
const errors = require('../../src/lib/errors.js');
require('chai').should();
describe('Ask for Service Worker Name', function() {
const globalStubs = [];
const Q_PATH = '../src/lib/questions/ask-sw-name.js';
const Q_PATH = '../../src/lib/questions/ask-sw-name.js';
afterEach(function() {
cliHelper.endLogCapture();
@@ -4,7 +4,7 @@ const depcheck = require('depcheck');
describe('Test Dependencies', function() {
it('should have required dependencies', function() {
return new Promise((resolve, reject) => {
depcheck(path.join(__dirname, '..'), {
depcheck(path.join(__dirname, '..', '..'), {
ignoreDirs: [
'test',
'build',
@@ -111,14 +111,14 @@ describe('Generate Manifest End-to-End Tests', function() {
this.timeout(60 * 1000);
fsExtra.copySync(
path.join(__dirname, 'static', 'example-project-1'),
path.join(__dirname, '..', 'static', 'example-project-1'),
tmpDirectory);
const relativeProjPath = path.relative(process.cwd(), tmpDirectory);
const manifestName = `${Date.now()}-manifest.js`;
const SWCli = proxyquire('../build/index', {
const SWCli = proxyquire('../../build/index', {
'./lib/questions/ask-root-of-web-app': () => {
return Promise.resolve(relativeProjPath);
},
@@ -4,13 +4,14 @@ const fs = require('fs');
const fsExtra = require('fs-extra');
const testServer = require('../../../utils/test-server.js');
const validator = require('./utils/e2e-sw-validator.js');
const testServerGen = require('../../../../utils/test-server-generator.js');
const validator = require('../utils/e2e-sw-validator.js');
require('chai').should();
describe('Generate SW End-to-End Tests', function() {
let tmpDirectory;
let testServer;
let baseTestUrl;
// NOTE: No jpg
@@ -21,7 +22,8 @@ describe('Generate SW End-to-End Tests', function() {
path.join(__dirname, 'tmp-')
);
return testServer.start(tmpDirectory)
testServer = testServerGen();
return testServer.start(tmpDirectory, 5050)
.then((portNumber) => {
baseTestUrl = `http://localhost:${portNumber}`;
});
@@ -43,13 +45,13 @@ describe('Generate SW End-to-End Tests', function() {
process.chdir(tmpDirectory);
fsExtra.copySync(
path.join(__dirname, 'static', 'example-project-1'),
path.join(__dirname, '..', 'static', 'example-project-1'),
tmpDirectory);
const swName = `${Date.now()}-sw.js`;
let enforceNoQuestions = false;
const SWCli = proxyquire('../build/index', {
const SWCli = proxyquire('../../build/index', {
'./lib/questions/ask-root-of-web-app': () => {
if (enforceNoQuestions) {
return Promise.reject('Injected Error - No Questions Expected');
@@ -1,5 +1,5 @@
const generateGlobPattern = require('../src/lib/utils/generate-glob-pattern');
const errors = require('../src/lib/errors');
const generateGlobPattern = require('../../src/lib/utils/generate-glob-pattern');
const errors = require('../../src/lib/errors');
require('chai').should();
@@ -1,10 +1,10 @@
const proxyquire = require('proxyquire');
const cliHelper = require('./utils/cli-test-helper.js');
const errors = require('../src/lib/errors');
const cliHelper = require('../utils/cli-test-helper.js');
const errors = require('../../src/lib/errors');
describe('Test Get Config', function() {
it('should be able to handle readFile error', function() {
const getConfig = proxyquire('../src/lib/utils/get-config', {
const getConfig = proxyquire('../../src/lib/utils/get-config', {
fs: {
readFile: (path, cb) => {
cb(new Error('Injected Error'));
@@ -20,7 +20,7 @@ describe('Test Get Config', function() {
});
it('should handle non-json config file', function() {
const getConfig = proxyquire('../src/lib/utils/get-config', {
const getConfig = proxyquire('../../src/lib/utils/get-config', {
fs: {
readFile: (path, cb) => {
cb(null, 'Not JSON at all.');
@@ -57,7 +57,7 @@ describe('Test Get Config', function() {
const data = {
example: 'Hi.',
};
const getConfig = proxyquire('../src/lib/utils/get-config', {
const getConfig = proxyquire('../../src/lib/utils/get-config', {
fs: {
readFile: (path, cb) => {
cb(null, JSON.stringify(data));
@@ -1,9 +1,9 @@
const proxyquire = require('proxyquire');
const errors = require('../src/lib/errors');
const errors = require('../../src/lib/errors');
describe('Test Save Config', function() {
it('should be able to handle writeFile error', function() {
const saveConfig = proxyquire('../src/lib/utils/save-config', {
const saveConfig = proxyquire('../../src/lib/utils/save-config', {
fs: {
writeFile: (path, content, cb) => {
cb(new Error('Injected Error'));
@@ -21,7 +21,7 @@ describe('Test Save Config', function() {
});
it('should resolve on writing file', function() {
const saveConfig = proxyquire('../src/lib/utils/save-config', {
const saveConfig = proxyquire('../../src/lib/utils/save-config', {
fs: {
writeFile: (path, content, cb) => {
cb(null);
@@ -1,92 +0,0 @@
/*
Copyright 2016 Google Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
const seleniumAssistant = require('selenium-assistant');
const swTestingHelpers = require('sw-testing-helpers');
const testServer = require('../../../utils/test-server.js');
const RETRIES = 3;
const TIMEOUT = 10 * 1000;
describe('sw-lib Tests', function() {
this.retries(RETRIES);
this.timeout(TIMEOUT);
let globalDriverBrowser;
let baseTestUrl;
// Set up the web server before running any tests in this suite.
before(function() {
return testServer.start('.').then((portNumber) => {
baseTestUrl = `http://localhost:${portNumber}/packages/sw-lib`;
});
});
// Kill the web server once all tests are complete.
after(function() {
return testServer.stop();
});
afterEach(function() {
if (!globalDriverBrowser) {
return;
}
return seleniumAssistant.killWebDriver(globalDriverBrowser)
.then(() => {
globalDriverBrowser = null;
});
});
const setupTestSuite = (assistantDriver) => {
describe(`sw-lib Tests in ${assistantDriver.getPrettyName()}`, function() {
it('should pass all browser based unit tests', function() {
return assistantDriver.getSeleniumDriver()
.then((driver) => {
globalDriverBrowser = driver;
})
.then(() => {
return swTestingHelpers.mochaUtils.startWebDriverMochaTests(
assistantDriver.getPrettyName(),
globalDriverBrowser,
`${baseTestUrl}/test/browser/`
);
})
.then((testResults) => {
console.log(
swTestingHelpers.mochaUtils.prettyPrintResults(testResults)
);
if (testResults.failed.length > 0) {
throw new Error('Failing tests');
}
});
});
});
};
const availableBrowsers = seleniumAssistant.getLocalBrowsers();
availableBrowsers.forEach((browser) => {
switch(browser.getId()) {
case 'chrome':
case 'firefox':
setupTestSuite(browser);
break;
default:
console.log(`Skipping tests for ${browser.getId()}`);
break;
}
});
});
@@ -137,8 +137,8 @@ describe('cache-revisioned-e2e.js', function() {
.concat(testSet['set-5'])
.concat(testSet['set-6']);
const sw1 = '../static/sw/cache-revisioned-1.js';
const sw2 = '../static/sw/cache-revisioned-2.js';
const sw1 = '/packages/sw-lib/test/static/sw/cache-revisioned-1.js';
const sw2 = '/packages/sw-lib/test/static/sw/cache-revisioned-2.js';
return window.goog.swUtils.activateSW(sw1)
.then((iframe) => {
return testFileSet(iframe, sw1, allAssets1);
-85
View File
@@ -1,85 +0,0 @@
<!--
Copyright 2016 Google Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<html>
<head>
<meta charset="utf-8">
<title>SW Helpers Tests</title>
<link href="/node_modules/mocha/mocha.css" rel="stylesheet" />
<!--
iframes are used to manage service worker scoping.
This will hide them and stop the page from jumping around
-->
<style>
iframe {
width: 0;
height: 0;
}
</style>
</head>
<body>
<div id="mocha"></div>
<script src="/node_modules/chai/chai.js"></script>
<script src="/node_modules/mocha/mocha.js"></script>
<!-- sw-testing-helpers -->
<script src="/node_modules/sw-testing-helpers/build/browser/mocha-utils.js"></script>
<script src="/node_modules/sw-testing-helpers/build/browser/sw-utils.js"></script>
<script src="/node_modules/sinon/pkg/sinon.js"></script>
<!--
Timeout is extended to ensure tests for max-cache-age
have enough time to complete
-->
<script>
mocha.setup({
ui: 'bdd',
timeout: 10000
});
chai.should();
const expect = chai.expect;
</script>
<!-- In browser test scripts should be added to the page here-->
<!-- Test Data here is used in tests and they rely on each other. -->
<script src="/packages/sw-precaching/test/static/test-data.js"></script>
<script src="/packages/sw-lib/test/static/test-data.js"></script>
<script src="library-namespace.js"></script>
<script src="cache-revisioned-e2e.js"></script>
<script src="cache-unrevisioned-e2e.js"></script>
<script src="navigation-route-e2e.js"></script>
<script>
(function() {
// This make browsers without a service worker pass tests by
// bypassing the tests altogether.
// This is desirable to allow travis to run tests in all browsers
// regardless of support or not and perform tests when the browser
// starts to support service workers.
if (!('serviceWorker' in navigator)) {
window.testsuite = {};
return;
}
window.goog.mochaUtils.startInBrowserMochaTests().then(results => {
window.testsuite = results;
});
})();
</script>
</body>
</html>
@@ -66,24 +66,4 @@ describe('Test Behaviors of Loading the Script', function() {
document.head.appendChild(scriptElement);
});
});
it('should perform basic.js sw tests', function() {
const serviceWorkerPath = '../sw/basic.js';
return window.goog.mochaUtils.registerServiceWorkerMochaTests(serviceWorkerPath);
});
it('should perform router.js sw tests', function() {
const serviceWorkerPath = '../sw/router.js';
return window.goog.mochaUtils.registerServiceWorkerMochaTests(serviceWorkerPath);
});
it('should perform cache-revisioned-assets.js sw tests', function() {
const serviceWorkerPath = '../sw/cache-revisioned-assets.js';
return window.goog.mochaUtils.registerServiceWorkerMochaTests(serviceWorkerPath);
});
it('should perform caching-strategies.js sw tests', function() {
const serviceWorkerPath = '../sw/caching-strategies.js';
return window.goog.mochaUtils.registerServiceWorkerMochaTests(serviceWorkerPath);
});
});
+8
View File
@@ -0,0 +1,8 @@
{
"browser": {
"scripts": [
"/packages/sw-precaching/test/static/test-data.js",
"/packages/sw-lib/test/static/test-data.js"
]
}
}
@@ -1,97 +0,0 @@
/*
Copyright 2016 Google Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
'use strict';
/* eslint-env node, mocha, browser, serviceworker */
/* eslint-disable max-len, no-unused-expressions */
// These tests make use of selenium-webdriver. You can find the relevant
// documentation here: http://selenium.googlecode.com/git/docs/api/javascript/index.html
const seleniumAssistant = require('selenium-assistant');
const swTestingHelpers = require('sw-testing-helpers');
const testServer = require('../../../utils/test-server');
const TIMEOUT = 10 * 1000;
const RETRIES = 3;
describe(`sw-offline-google-analytics Test Suite`, function() {
this.retries(RETRIES);
this.timeout(TIMEOUT);
let globalDriverReference = null;
let baseTestUrl;
// Set up the web server before running any tests in this suite.
before(function() {
return testServer.start('.').then((portNumber) => {
baseTestUrl = `http://localhost:${portNumber}/packages/sw-offline-google-analytics/test/`;
});
});
// Kill the web server once all tests are complete.
after(function() {
return testServer.stop();
});
afterEach(function() {
this.timeout(6000);
return seleniumAssistant.killWebDriver(globalDriverReference)
.then(() => {
globalDriverReference = null;
});
});
const configureTestSuite = function(browser) {
it(`should pass all tests in (${browser.getPrettyName()} - ${browser.getVersionNumber()})`, function() {
return browser.getSeleniumDriver()
.then((driver) => {
globalDriverReference = driver;
globalDriverReference.manage().timeouts().setScriptTimeout(TIMEOUT);
})
.then(() => {
return swTestingHelpers.mochaUtils.startWebDriverMochaTests(
browser.getPrettyName(),
globalDriverReference,
`${baseTestUrl}unit/`
);
})
.then((testResults) => {
console.log(
swTestingHelpers.mochaUtils.prettyPrintResults(testResults)
);
if (testResults.failed.length > 0) {
throw new Error('Some of the browser tests failed.');
}
});
});
};
seleniumAssistant.getLocalBrowsers().forEach(function(browser) {
switch (browser.getId()) {
case 'chrome':
case 'firefox':
configureTestSuite(browser);
break;
default:
console.warn(`Skipping ${browser.getPrettyName()}.`);
break;
}
});
});
@@ -0,0 +1,11 @@
{
"browser": {
"scripts": [
"/node_modules/mockdate/src/mockdate.js",
"/packages/sw-offline-google-analytics/build/test/constants.js",
"/packages/sw-offline-google-analytics/build/test/idb-helper.js",
"/packages/sw-offline-google-analytics/build/test/replay-queued-requests.js",
"/packages/sw-offline-google-analytics/build/test/enqueue-request.js"
]
}
}
@@ -1,80 +0,0 @@
<!--
Copyright 2016 Google Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<html>
<head>
<meta charset="utf-8">
<title>SW Helpers Tests</title>
<link href="/node_modules/mocha/mocha.css" rel="stylesheet" />
<!--
iframes are used to manage service worker scoping.
This will hide them and stop the page from jumping around
-->
<style>
iframe {
width: 0;
height: 0;
}
</style>
</head>
<body>
<div id="mocha"></div>
<script src="/node_modules/chai/chai.js"></script>
<script src="/node_modules/mocha/mocha.js"></script>
<!-- sw-testing-helpers -->
<script src="/node_modules/sw-testing-helpers/build/browser/mocha-utils.js"></script>
<script src="/node_modules/sw-testing-helpers/build/browser/sw-utils.js"></script>
<script src="/node_modules/mockdate/src/mockdate.js"></script>
<script src="/node_modules/sinon/pkg/sinon.js"></script>
<script src="/packages/sw-offline-google-analytics/build/test/constants.js"></script>
<script src="/packages/sw-offline-google-analytics/build/test/idb-helper.js"></script>
<script src="/packages/sw-offline-google-analytics/build/test/replay-queued-requests.js"></script>
<script src="/packages/sw-offline-google-analytics/build/test/enqueue-request.js"></script>
<!--
Timeout is extended to ensure tests for max-cache-age
have enough time to complete
-->
<script>mocha.setup({
ui: 'bdd',
timeout: 10000
})</script>
<!-- In browser test scripts should be added to the page here-->
<script src="replay-queued-requests.js"></script>
<script src="enqueue-request.js"></script>
<script>
(function() {
// This make browsers without a service worker pass tests by
// bypassing the tests altogether.
// This is desirable to allow travis to run tests in all browsers
// regardless of support or not and perform tests when the browser
// starts to support service workers.
if (!('serviceWorker' in navigator)) {
publishTestResults();
return;
}
window.goog.mochaUtils.startInBrowserMochaTests().then(results => {
window.testsuite = results;
});
})();
</script>
</body>
</html>
+1
View File
@@ -3,6 +3,7 @@
"no-console": 0,
"max-len": 0,
"no-invalid-this": 0,
"valid-jsdoc": 0,
},
"env": {
"mocha": true
@@ -1,90 +0,0 @@
/*
Copyright 2016 Google Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
const seleniumAssistant = require('selenium-assistant');
const swTestingHelpers = require('sw-testing-helpers');
const testServer = require('../../../utils/test-server.js');
require('chromedriver');
require('geckodriver');
const RETRIES = 3;
const TIMEOUT = 30 * 1000;
describe(`sw-precaching Browser Tests`, function() {
this.retries(RETRIES);
this.timeout(TIMEOUT);
let globalDriverBrowser;
let baseTestUrl;
// Set up the web server before running any tests in this suite.
before(function() {
return testServer.start('.')
.then((portNumber) => {
baseTestUrl = `http://localhost:${portNumber}/packages/sw-precaching`;
});
});
// Kill the web server once all tests are complete.
after(function() {
return testServer.stop();
});
afterEach(function() {
return seleniumAssistant.killWebDriver(globalDriverBrowser)
.then(() => {
globalDriverBrowser = null;
});
});
const setupTestSuite = (assistantDriver) => {
it(`should pass all browser based unit tests in ${assistantDriver.getPrettyName()}`, function() {
return assistantDriver.getSeleniumDriver()
.then((driver) => {
globalDriverBrowser = driver;
})
.then(() => {
return swTestingHelpers.mochaUtils.startWebDriverMochaTests(
assistantDriver.getPrettyName(),
globalDriverBrowser,
`${baseTestUrl}/test/browser/`
);
})
.then((testResults) => {
console.log(
swTestingHelpers.mochaUtils.prettyPrintResults(testResults)
);
if (testResults.failed.length > 0) {
throw new Error('Some of the browser tests failed');
}
});
});
};
const availableBrowsers = seleniumAssistant.getLocalBrowsers();
availableBrowsers.forEach((browser) => {
switch(browser.getId()) {
case 'chrome':
case 'firefox':
setupTestSuite(browser);
break;
default:
console.log(`Skipping tests for ${browser.getId()}`);
break;
}
});
});
@@ -1,7 +1,7 @@
/* global goog, expect */
describe('sw-precaching Test Revisioned Caching', function() {
const STATIC_ASSETS_PATH = '../static';
const STATIC_ASSETS_PATH = '/packages/sw-precaching/test/static';
const deleteIndexedDB = () => {
return new Promise((resolve, reject) => {
@@ -1,80 +0,0 @@
<!--
Copyright 2016 Google Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<html>
<head>
<meta charset="utf-8">
<title>SW Helpers Tests</title>
<link href="/node_modules/mocha/mocha.css" rel="stylesheet" />
<!--
iframes are used to manage service worker scoping.
This will hide them and stop the page from jumping around
-->
<style>
iframe {
width: 0;
height: 0;
}
</style>
</head>
<body>
<div id="mocha"></div>
<script src="/node_modules/chai/chai.js"></script>
<script src="/node_modules/mocha/mocha.js"></script>
<!-- sw-testing-helpers -->
<script src="/node_modules/sw-testing-helpers/build/browser/mocha-utils.js"></script>
<script src="/node_modules/sw-testing-helpers/build/browser/sw-utils.js"></script>
<script src="/node_modules/sinon/pkg/sinon.js"></script>
<!--
Timeout is extended to ensure tests for max-cache-age
have enough time to complete
-->
<script>
mocha.setup({
ui: 'bdd',
timeout: 10000
});
chai.should();
const expect = chai.expect;
</script>
<!-- In browser test scripts should be added to the page here-->
<script src="../static/test-data.js"></script>
<script src="library-namespace.js"></script>
<script src="cache-testing.js"></script>
<script src="register-sw-tests.js"></script>
<script>
(function() {
// This make browsers without a service worker pass tests by
// bypassing the tests altogether.
// This is desirable to allow travis to run tests in all browsers
// regardless of support or not and perform tests when the browser
// starts to support service workers.
if (!('serviceWorker' in navigator)) {
window.testsuite = {};
return;
}
window.goog.mochaUtils.startInBrowserMochaTests().then(results => {
window.testsuite = results;
});
})();
</script>
</body>
</html>
@@ -1,23 +0,0 @@
describe('Service Worker Unit Tests', function() {
beforeEach(function() {
return window.goog.swUtils.cleanState();
});
afterEach(function() {
return window.goog.swUtils.cleanState();
});
const swUnitTests = [
'basic.js',
'revisioned-caching.js',
'unrevisioned-caching.js',
'cookies.js',
];
swUnitTests.forEach((swUnitTestPath) => {
it(`should register '${swUnitTestPath}' sw tests`, function() {
return window.goog.mochaUtils.registerServiceWorkerMochaTests(`../sw/${swUnitTestPath}`);
});
});
});
+7
View File
@@ -0,0 +1,7 @@
{
"browser": {
"scripts": [
"/packages/sw-precaching/test/static/test-data.js"
]
}
}
@@ -0,0 +1,84 @@
const fs = require('fs');
const path = require('path');
const fsExtra = require('fs-extra');
const testServerGen = require('../../../../utils/test-server-generator.js');
/**
* This test is largely a smoke test to ensure the routes from PrecacheManager
* is possible.
*/
module.exports = (webdriverCb) => {
describe('Routing Example', function() {
let tmpDirectory;
let testServer;
let baseTestUrl;
let webdriverInstance;
before(function() {
tmpDirectory = fs.mkdtempSync(
path.join(__dirname, 'tmp-')
);
fsExtra.copySync(
path.join(__dirname, '..', 'static', 'routing-demo'),
tmpDirectory);
webdriverInstance = webdriverCb();
if (!webdriverInstance) {
throw new Error('Skipping selenium test due to no webdriver.');
}
testServer = testServerGen();
return testServer.start('.', 5050)
.then((portNumber) => {
baseTestUrl = `http://localhost:${portNumber}`;
});
});
after(function() {
this.timeout(4 * 1000);
fsExtra.removeSync(tmpDirectory);
return testServer.stop();
});
it('should be able to install a service worker and serve page offline', function() {
this.timeout(14 * 1000);
const relativePath = path.relative('.', tmpDirectory);
return webdriverInstance.get(baseTestUrl + `/${relativePath}/`)
.then(() => {
return webdriverInstance.wait(() => {
return webdriverInstance.executeScript(() => {
return typeof window.__testResult !== 'undefined';
});
});
})
.then(() => {
return webdriverInstance.executeScript(() => {
return window.__testResult;
});
})
.then((testResult) => {
if (testResult.error) {
throw new Error('Unable to load page: ' + testResult.error);
}
fsExtra.removeSync(path.join(tmpDirectory, 'example.html'));
})
.then(() => {
return webdriverInstance.get(baseTestUrl + `/${relativePath}/example.html`);
})
.then(() => {
return webdriverInstance.wait(() => {
return webdriverInstance.executeScript(() => {
return typeof window.__testResult !== 'undefined';
});
});
});
});
});
};
@@ -1,93 +0,0 @@
const fs = require('fs');
const path = require('path');
const fsExtra = require('fs-extra');
const seleniumAssistant = require('selenium-assistant');
const testServer = require('../../../utils/test-server.js');
/**
* This test is largely a smoke test to ensure the routes from PrecacheManager
* is possible.
*/
describe('Routing Example', function() {
let tmpDirectory;
let baseTestUrl;
let globalDriver;
afterEach(function() {
this.timeout(10 * 1000);
if (globalDriver) {
return seleniumAssistant.killWebDriver(globalDriver)
.then(() => {
globalDriver = null;
});
}
});
before(function() {
tmpDirectory = fs.mkdtempSync(
path.join(__dirname, 'tmp-')
);
fsExtra.copySync(
path.join(__dirname, 'static', 'routing-demo'),
tmpDirectory);
return testServer.start('.')
.then((portNumber) => {
baseTestUrl = `http://localhost:${portNumber}`;
});
});
after(function() {
fsExtra.removeSync(tmpDirectory);
return testServer.stop();
});
it('should be able to install a service worker and serve page offline', function() {
this.timeout(14 * 1000);
this.retries(3);
const relativePath = path.relative('.', tmpDirectory);
const chromeBrowser = seleniumAssistant.getLocalBrowser('chrome', 'stable');
return chromeBrowser.getSeleniumDriver()
.then((driver) => {
globalDriver = driver;
})
.then(() => {
return globalDriver.get(baseTestUrl + `/${relativePath}/`);
})
.then(() => {
return globalDriver.wait(() => {
return globalDriver.executeScript(() => {
return typeof window.__testResult !== 'undefined';
});
});
})
.then(() => {
return globalDriver.executeScript(() => {
return window.__testResult;
});
})
.then((testResult) => {
if (testResult.error) {
throw new Error('Unable to load page: ' + testResult.error);
}
fsExtra.removeSync(path.join(tmpDirectory, 'example.html'));
})
.then(() => {
return globalDriver.get(baseTestUrl + `/${relativePath}/example.html`);
})
.then(() => {
return globalDriver.wait(() => {
return globalDriver.executeScript(() => {
return typeof window.__testResult !== 'undefined';
});
});
});
});
});
@@ -1,68 +0,0 @@
/*
Copyright 2017 Google Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
const seleniumAssistant = require('selenium-assistant');
const swTestingHelpers = require('sw-testing-helpers');
const testServer = require('../../../utils/test-server.js');
const RETRIES = 3;
const TIMEOUT = 10 * 1000;
describe(`sw-routing Browser Tests`, function() {
this.retries(RETRIES);
this.timeout(TIMEOUT);
let globalDriverBrowser;
let baseTestUrl;
// Set up the web server before running any tests in this suite.
before(() => testServer.start('.').then((portNumber) => {
baseTestUrl = `http://localhost:${portNumber}/packages/sw-routing`;
}));
// Kill the web server once all tests are complete.
after(() => testServer.stop());
afterEach(() => seleniumAssistant.killWebDriver(globalDriverBrowser)
.then(() => globalDriverBrowser = null));
const setupTestSuite = (assistantDriver) => {
it(`should pass all tests in ${assistantDriver.getPrettyName()}`, () => {
return assistantDriver.getSeleniumDriver()
.then((driver) => globalDriverBrowser = driver)
.then(() => swTestingHelpers.mochaUtils.startWebDriverMochaTests(
assistantDriver.getPrettyName(),
globalDriverBrowser,
`${baseTestUrl}/test/browser/`
)).then((testResults) => {
console.log(swTestingHelpers.mochaUtils.prettyPrintResults(testResults));
if (testResults.failed.length > 0) {
throw new Error('Some of the browser tests failed.');
}
});
});
};
seleniumAssistant.getLocalBrowsers().forEach((browser) => {
switch(browser.getId()) {
case 'chrome':
case 'firefox':
setupTestSuite(browser);
break;
default:
console.log(`Skipping tests for ${browser.getId()}.`);
}
});
});
@@ -1,17 +0,0 @@
describe('Service Worker Unit Test Registration', function() {
const pathPrefix = '../sw/';
const swUnitTests = [
'express-route.js',
'namespace.js',
'navigation-route.js',
'regexp-route.js',
'route.js',
'routing-suite.js',
].map((script) => `${pathPrefix}${script}`);
swUnitTests.forEach(function(swUnitTestPath) {
it(`should register ${swUnitTestPath}`, function() {
return goog.mochaUtils.registerServiceWorkerMochaTests(swUnitTestPath);
});
});
});
@@ -41,6 +41,11 @@
<script src="/node_modules/sw-testing-helpers/build/browser/mocha-utils.js"></script>
<script src="/node_modules/sw-testing-helpers/build/browser/sw-utils.js"></script>
<script src="/node_modules/sinon/pkg/sinon.js"></script>
{{#if config.browser}}
{{#each config.browser.scripts}}
<script src="{{this}}"></script>
{{/each}}
{{/if}}
<script>
mocha.setup({
@@ -10,11 +10,14 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- This file is served via /__test/mocha/<pkg>
See utils/service-instance.js for the serving logic. -->
<html>
<head>
<meta charset="utf-8">
<title>SW Helpers Tests</title>
<link href="/node_modules/mocha/mocha.css" rel="stylesheet" />
<title>Mocha Test Harness: {{pkg}}</title>
<base href="/packages/{{pkg}}/test/browser/">
<link href="/node_modules/mocha/mocha.css" rel="stylesheet">
<!--
iframes are used to manage service worker scoping.
@@ -41,17 +44,24 @@
<script>
mocha.setup({
ui: 'bdd',
timeout: 10000
ui: 'bdd'
});
chai.should();
const expect = chai.expect;
</script>
<!-- In browser test scripts should be added to the page here -->
<script src="register-unit-tests.js"></script>
<script src="end-to-end.js"></script>
<!-- Package-specific tests matching packages/<pkg>/test/browser/*.js -->
<script>
describe('{{pkg}} > test/sw/*.js', function() {
{{#each scripts}}
it(`should run '{{this}}' sw tests`, function() {
return window.goog.mochaUtils.registerServiceWorkerMochaTests('{{this}}');
});
{{/each}}
});
</script>
<script>
(function() {
+10
View File
@@ -0,0 +1,10 @@
{
"rules": {
"no-console": 0,
"max-len": 0,
"no-invalid-this": 0,
},
"env": {
"mocha": true
}
}
+13
View File
@@ -0,0 +1,13 @@
const glob = require('glob');
const path = require('path');
const TestRunner = require('../utils/test-runner');
const testGlob = `packages/${process.env.projectOrStar}/test/`;
const testFiles = glob.sync(testGlob);
const packageNames = testFiles.map((testFile) => {
const packageName = testFile.split(path.sep)[1];
return packageName;
});
const testRunner = new TestRunner(packageNames);
testRunner.start();
+62 -6
View File
@@ -27,6 +27,7 @@ const serveStatic = require('serve-static');
class ServerInstance {
constructor() {
this._server = null;
this._sockets = [];
this._app = express();
this._app.use(cookieParser());
@@ -73,19 +74,66 @@ class ServerInstance {
// Harness to kick off all the in-browser tests for a given package.
// It will pick up a list of all the top-level .js files and automatically
// inject them into the HTML as <script> tags.
this._app.get('/__test/mocha/:pkg', function(req, res) {
this._app.get('/__test/mocha/browser/:pkg', function(req, res) {
const pkg = req.params.pkg;
const pattern = `packages/${pkg}/test/browser/*.js`;
const scripts = glob.sync(pattern).map((script) => `/${script}`);
const repoRoot = path.join(__dirname, '..');
const scripts = glob.sync(pattern, {
cwd: repoRoot,
root: repoRoot,
}).map((script) => {
// Converts packages/<pkg name>/test/sw/<filename>.js
// to /packages/<pkg name>/test/sw/<filename>.js
return `/${script}`;
});
if (scripts.length === 0) {
throw Error(`No test scripts match the pattern '${pattern}'.`);
const errMsg = `No test scripts match the pattern '${pattern}'.`;
/* eslint-disable no-console */
console.log(errMsg);
/* eslint-enable no-console */
res.status(500).send(errMsg);
return;
}
let config = {};
try {
// Read JSON file to avoid the require cache
config =
JSON.parse(
fs.readFileSync(
path.join(__dirname, '..', 'packages', pkg, 'test', 'config.json')
, 'utf-8')
);
} catch (err) {
// NOOP
}
const source = fs.readFileSync(path.join(
__dirname, '..', 'templates', 'test-harness.hbs'), 'utf-8');
__dirname, '..', 'templates', 'test-browser.hbs'), 'utf-8');
const template = handlebars.compile(source);
const html = template({scripts, pkg});
const html = template({
scripts,
config,
pkg,
});
res.send(html);
});
this._app.get('/__test/mocha/sw/:pkg', function(req, res) {
/* eslint-disable no-console */
const pkg = req.params.pkg;
const pattern = `packages/${pkg}/test/sw/*.js`;
const scriptPaths = glob.sync(pattern).map((script) => {
// Converts packages/<pkg name>/test/sw/<filename>.js
// to /packages/<pkg name>/test/sw/<filename>.js
return `/${script}`;
});
const source = fs.readFileSync(path.join(
__dirname, '..', 'templates', 'test-sw.hbs'), 'utf-8');
const template = handlebars.compile(source);
const html = template({scripts: scriptPaths, pkg});
res.send(html);
});
@@ -133,11 +181,19 @@ class ServerInstance {
}
resolve(this._server.address().port);
});
this._server.on('connection', (socket) => {
this._sockets.push(socket);
});
});
}
stop() {
return new Promise((resolve) => {
this._sockets.forEach((socket) => {
socket.destroy();
});
this._server.close(resolve);
this._server = null;
});
+250
View File
@@ -0,0 +1,250 @@
const path = require('path');
const chalk = require('chalk');
const glob = require('glob');
const seleniumAssistant = require('selenium-assistant');
const swTestingHelpers = require('sw-testing-helpers');
const testServerGen = require('./test-server-generator.js');
/* eslint-disable no-console, require-jsdoc, no-invalid-this, max-len */
/* eslint-env mocha */
class TestRunner {
constructor(packageNames) {
this._packagePathsToTest = packageNames.map((packageName) => {
return path.join(__dirname, '..', 'packages', packageName);
});
}
printHeading(heading) {
console.log(chalk.inverse(`\n ☢️ ${heading} `));
}
start() {
const that = this;
describe('Test Runner Environment', function() {
let testServer;
before(function() {
that.printHeading(`Starting test server`);
testServer = testServerGen();
return testServer.start('.')
.then((portNumber) => {
that._baseTestUrl = `http://localhost:${portNumber}`;
});
});
// Kill the web server once all tests are complete.
after(function() {
that.printHeading(`Killing test server`);
return testServer.stop();
});
const getBaseTestUrl = () => {
return that._baseTestUrl;
};
that._configureBrowserTests(getBaseTestUrl);
that._configureNodeTests(getBaseTestUrl);
});
}
_configureBrowserTests(getBaseTestUrl) {
if (!this._testsRequireBrowser()) {
return;
}
const availableBrowsers = seleniumAssistant.getLocalBrowsers();
availableBrowsers.forEach((browser) => {
switch(browser.getId()) {
case 'chrome':
case 'firefox':
this._addBrowserTests(browser, getBaseTestUrl);
break;
}
});
}
_addBrowserTests(browser, getBaseTestUrl) {
const that = this;
describe(``, function() {
let webdriverInstance;
before(function() {
that.printHeading(`Starting browser tests in ${browser.getPrettyName()} - ${browser.getVersionNumber()}`);
});
after(function() {
// Killing a web driver can be slow...
this.timeout(10 * 1000);
return seleniumAssistant.killWebDriver(webdriverInstance);
});
it('should be able to get a valid webdriver instance', function() {
// Starting a web driver can be slow...
this.timeout(10 * 1000);
this.retries(2);
return browser.getSeleniumDriver()
.then((driver) => {
webdriverInstance = driver;
});
});
const getWebdriver = () => {
return webdriverInstance;
};
that._packagePathsToTest.forEach((packagePath) => {
if (that._hasBrowserTests(packagePath)) {
that._runBrowserTests(getWebdriver, packagePath, getBaseTestUrl);
} else if (process.env.TRAVIS) {
console.log('No browser tests.');
}
if (that._hasServiceWorkerTests(packagePath)) {
that._runServiceWorkerTests(getWebdriver, packagePath, getBaseTestUrl);
} else if (process.env.TRAVIS) {
console.log('No service worker tests.');
}
if (that._hasIntegrationTests(packagePath)) {
that._runIntegrationTests(getWebdriver, packagePath, getBaseTestUrl);
} else if (process.env.TRAVIS) {
console.log('No integration tests.');
}
});
});
}
_handleMochaResults(testResults) {
if (process.env.TRAVIS || testResults.failed.length > 0) {
console.log(
swTestingHelpers.mochaUtils.prettyPrintResults(testResults)
);
}
if (testResults.failed.length > 0) {
throw new Error(`${testResults.failed.length} test${testResults.failed.length > 1 ? 's' : ''} failed.`);
}
}
_testsRequireBrowser() {
let hasBrowserTests = false;
for (let i = 0; i < this._packagePathsToTest.length && !hasBrowserTests; i++) {
const packagePath = this._packagePathsToTest[i];
hasBrowserTests = this._hasBrowserTests(packagePath) ||
this._hasServiceWorkerTests(packagePath) ||
this._hasIntegrationTests(packagePath);
}
return hasBrowserTests;
}
_testsRequireNode() {
let hasNodeTests = false;
for (let i = 0; i < this._packagePathsToTest.length && !hasNodeTests; i++) {
const packagePath = this._packagePathsToTest[i];
hasNodeTests = this._hasNodeTests(packagePath);
}
return hasNodeTests;
}
_hasServiceWorkerTests(packagePath) {
return glob.sync(`${packagePath}/test/sw/*.js`).length > 0;
}
_hasBrowserTests(packagePath) {
return glob.sync(`${packagePath}/test/browser/*.js`).length > 0;
}
_hasIntegrationTests(packagePath) {
return glob.sync(`${packagePath}/test/integration/*.js`).length > 0;
}
_hasNodeTests(packagePath) {
return glob.sync(`${packagePath}/test/node/*.js`).length > 0;
}
_runBrowserTests(webdriverCb, packagePath, getBaseTestUrl) {
const that = this;
it(`should pass '${path.basename(packagePath)}' browser tests`, function() {
this.timeout(10 * 1000);
const webdriver = webdriverCb();
if (!webdriver) {
console.warn('Skipping selenium test due to no webdriver.');
return;
}
return swTestingHelpers.mochaUtils.startWebDriverMochaTests(
path.basename(packagePath),
webdriver,
`${getBaseTestUrl()}/__test/mocha/browser/${path.basename(packagePath)}`
)
.then(that._handleMochaResults);
});
}
_runServiceWorkerTests(webdriverCb, packagePath, getBaseTestUrl) {
const that = this;
it(`should pass '${path.basename(packagePath)}' sw tests`, function() {
this.timeout(10 * 1000);
const webdriver = webdriverCb();
if (!webdriver) {
console.warn('Skipping selenium test due to no webdriver.');
return;
}
return swTestingHelpers.mochaUtils.startWebDriverMochaTests(
path.basename(packagePath),
webdriver,
`${getBaseTestUrl()}/__test/mocha/sw/${path.basename(packagePath)}`
)
.then(that._handleMochaResults);
});
}
_runIntegrationTests(webdriverCb, packagePath, getBaseTestUrl) {
const integrationTests = glob.sync(`${packagePath}/test/integration/*.js`);
global.getBaseTestUrl = getBaseTestUrl;
integrationTests.forEach((testFile) => {
const testCb = require(testFile);
testCb(webdriverCb);
});
}
_configureNodeTests(getBaseTestUrl) {
if (!this._testsRequireNode()) {
return;
}
const that = this;
describe(``, function() {
before(function() {
that.printHeading(`Starting Node tests`);
});
that._packagePathsToTest.forEach((packagePath) => {
if (that._hasNodeTests(packagePath)) {
that._runNodeTests(packagePath, getBaseTestUrl);
} else if (process.env.TRAVIS) {
console.log('No node tests.');
}
});
});
}
_runNodeTests(packagePath, getBaseTestUrl) {
const nodeTests = glob.sync(`${packagePath}/test/node/*.js`);
global.getBaseTestUrl = getBaseTestUrl;
nodeTests.forEach((nodeTextFile) => {
require(nodeTextFile);
});
}
}
module.exports = TestRunner;
+83
View File
@@ -0,0 +1,83 @@
/*
Copyright 2016 Google Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* README:
* This test server is used in unit tests as well as
* by the 'gulp serve' task, so please make sure
* changes here work in all scenarios.
*
* There are two servers so tests can make requests to a foreign origin.
*/
/* eslint-disable valid-jsdoc */
const ServerInstance = require('./server-instance');
const getNewServerInstance = () => {
let primaryServer;
let secondaryServer;
return {
/**
* Calling start will create two servers. The primary port will be returned
* and the secondary server will be on the primary port + 1;
*/
start: (rootDirectory, port) => {
if (primaryServer || secondaryServer) {
return Promise.reject('Server already running');
}
if (!port) {
port = 3004;
}
primaryServer = new ServerInstance();
secondaryServer = new ServerInstance();
return primaryServer.start(rootDirectory, port)
.then((primaryPort) => {
let secondaryPort = primaryPort + 1;
return secondaryServer.start(rootDirectory, secondaryPort)
.then((actualSecondaryPort) => {
if (actualSecondaryPort !== secondaryPort) {
return Promise.all([
primaryServer.stop(),
secondaryServer.stop(),
])
.then(() => {
Promise.reject(new Error('Server could not get the required ' +
'ports or primaryPort and primaryPort + 1.'));
});
} else {
return primaryPort;
}
});
});
},
stop: () => {
return Promise.all([
primaryServer.stop(),
secondaryServer.stop(),
])
.then(() => {
primaryServer = null;
secondaryServer = null;
});
},
};
};
module.exports = getNewServerInstance;
-79
View File
@@ -1,79 +0,0 @@
/*
Copyright 2016 Google Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* README:
* This test server is used in unit tests as well as
* by the 'gulp serve' task, so please make sure
* changes here work in all scenarios.
*
* There are two servers so tests can make requests to a foreign origin.
*/
/* eslint-disable valid-jsdoc */
const ServerInstance = require('./server-instance');
let primaryServer;
let secondaryServer;
module.exports = {
/**
* Calling start will create two servers. The primary port will be returned
* and the secondary server will be on the primary port + 1;
*/
start: (rootDirectory, port) => {
if (primaryServer || secondaryServer) {
return Promise.reject('Server already running');
}
if (!port) {
port = 3004;
}
primaryServer = new ServerInstance();
secondaryServer = new ServerInstance();
return primaryServer.start(rootDirectory, port)
.then((primaryPort) => {
let secondaryPort = primaryPort + 1;
return secondaryServer.start(rootDirectory, secondaryPort)
.then((actualSecondaryPort) => {
if (actualSecondaryPort !== secondaryPort) {
return Promise.all([
primaryServer.stop(),
secondaryServer.stop(),
])
.then(() => {
Promise.reject(new Error('Server could not get the required ' +
'ports or primaryPort and primaryPort + 1.'));
});
} else {
return primaryPort;
}
});
});
},
stop: () => {
return Promise.all([
primaryServer.stop(),
secondaryServer.stop(),
])
.then(() => {
primaryServer = null;
secondaryServer = null;
});
},
};