Skip to content
This repository has been archived by the owner on Apr 24, 2021. It is now read-only.

Commit

Permalink
Moving stub to support actually running on FF if the appropriate API'…
Browse files Browse the repository at this point in the history
…s work and moving back to Notification API to get FF support back on the roadmap
  • Loading branch information
Matt Gaunt committed Apr 4, 2016
1 parent b0a81ee commit 297e0ca
Show file tree
Hide file tree
Showing 26 changed files with 1,400 additions and 864 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ To use the Propel library do the following:
var PropelClient = window.goog.propel.PropelClient;

// Check if push is supported by the current browsers
if (PropelClient.supported()) {
if (PropelClient.isSupported()) {
// Initialise Push Client
var propelClient = new PropelClient('/sw.js');
propelClient.addEventListener('statuschange', function(event) {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"require-dir": "^0.3.0",
"rollupify": "^0.2.0",
"run-sequence": "^1.1.5",
"selenium-webdriver": "^2.52.0",
"selenium-webdriver": "^2.53.1",
"sinon": "^1.17.3",
"sw-testing-helpers": "0.0.6",
"vinyl-buffer": "^1.0.0",
Expand Down
31 changes: 22 additions & 9 deletions src/client/push-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import EventDispatch from './event-dispatch';
const SUPPORTED = 'serviceWorker' in navigator &&
'PushManager' in window &&
'Notification' in window &&
'permissions' in navigator &&
'showNotification' in ServiceWorkerRegistration.prototype;

const ERROR_MESSAGES = {
Expand Down Expand Up @@ -78,7 +77,7 @@ export default class PushClient extends EventDispatch {
constructor(workerUrlOrRegistration, scope) {
super();

if (!PushClient.supported()) {
if (!PushClient.isSupported()) {
throw new Error('Your browser does not support the web push API');
}

Expand Down Expand Up @@ -106,14 +105,16 @@ export default class PushClient extends EventDispatch {

_dispatchStatusUpdate() {
return Promise.all([
this.getSubscription(),
this.getSubscription().catch(() => {
return null;
}),
PushClient.getPermissionState()
])
.then(results => {
return {
isSubscribed: (results[0] !== null),
currentSubscription: results[0],
permissionState: results[1].state
permissionState: results[1]
};
})
.then(status => {
Expand Down Expand Up @@ -187,6 +188,12 @@ export default class PushClient extends EventDispatch {
})
.then(() => {
this._dispatchStatusUpdate();
})
.catch(err => {
return this._dispatchStatusUpdate()
.then(() => {
throw err;
});
});
}

Expand Down Expand Up @@ -223,13 +230,17 @@ export default class PushClient extends EventDispatch {
/**
* Will manage requesting permission for push messages, resolving
* with the final permission status.
* @param {Boolean} dispatchStatusChange - Optional parameter with a
* default value of true. If true, a `statuschange` event will be
* dispatched once the permission state has resolved (i.e. use interacted
* with the permission dialog).
* @return {Promise<String>} Permission status of granted, default or denied
*/
requestPermission(dispatchStatusChange = true) {
return PushClient.getPermissionState()
.then(permissionState => {
// Check if requesting permission will show a prompt
if (permissionState.state === 'prompt') {
if (permissionState === 'default') {
this.dispatchEvent(new PushClientEvent('requestingpermission'));
}

Expand All @@ -248,17 +259,19 @@ export default class PushClient extends EventDispatch {
* @return {Boolean} Whether the current browser has everything needed
* to use push messaging.
*/
static supported() {
static isSupported() {
return SUPPORTED;
}

/**
* This method can be used to check if subscribing the user will display
* the permission dialog or not.
* @return {Promise<PermissionStatus>} PermistionStatus.state will be
* 'granted', 'denied' or 'prompt' to reflect the current permission state
* @return {Promise<PermissionStatus>} PermistionStatus will be
* 'granted', 'denied' or 'default' to reflect the current permission state
*/
static getPermissionState() {
return navigator.permissions.query({name: 'push', userVisibleOnly: true});
return new Promise(resolve => {
resolve(Notification.permission);
});
}
}
4 changes: 2 additions & 2 deletions src/client/subscription-failed-error.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@

const MESSAGES = {
'not supported': 'Your browser doesn\'t support push messaging.',
'blocked': 'The user denied permission to show notifications.',
'prompt': 'The user dismissed the notification permission dialog.',
'denied': 'The user denied permission to show notifications.',
'default': 'The user dismissed the notification permission dialog.',
'endpoint': 'No endpoint URL specified.',
'nogcmid': 'Please ensure you have a Web App Manifest with ' +
'a "gcm_sender_id" defined.'
Expand Down
37 changes: 32 additions & 5 deletions test/automated-suite.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const path = require('path');
const swTestingHelpers = require('sw-testing-helpers');
const testServer = swTestingHelpers.testServer;
const automatedBrowserTesting = swTestingHelpers.automatedBrowserTesting;
const seleniumFirefox = require('selenium-webdriver/firefox');

describe('Test Propel', function() {
// Browser tests can be slow
Expand Down Expand Up @@ -57,13 +58,39 @@ describe('Test Propel', function() {

const queueUnitTest = browserInfo => {
it(`should pass all tests in ${browserInfo.prettyName}`, () => {

switch (browserInfo.seleniumBrowserId) {
case 'firefox':
const ffProfile = new seleniumFirefox.Profile();
ffProfile.setPreference('security.turn_off_all_security_so_that_viruses_can_take_over_this_computer', true);
browserInfo.seleniumOptions.setProfile(ffProfile);
break;
default:
// NOOP
break;
}

globalDriverReference = browserInfo.getSeleniumDriver();

return automatedBrowserTesting.runMochaTests(
browserInfo.prettyName,
globalDriverReference,
`${testServerURL}/test/browser-tests/`
)
let initialisePromise = Promise.resolve();
if (browserInfo.seleniumBrowserId === 'firefox') {
// H/T to web-push for this trick to get permissions accepted / denied
// https://github.com/marco-c/web-push
initialisePromise = globalDriverReference.executeScript(() => {
/* global window, Components */
window.netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
Components.utils.import('resource://gre/modules/Services.jsm');
});
}

return initialisePromise
.then(() => {
return automatedBrowserTesting.runMochaTests(
browserInfo.prettyName,
globalDriverReference,
`${testServerURL}/test/browser-tests/`
);
})
.then(testResults => {
automatedBrowserTesting.manageTestResults(
browserInfo.prettyName,
Expand Down
29 changes: 21 additions & 8 deletions test/browser-tests/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,29 @@
<script src="/node_modules/chai/chai.js"></script>
<script src="/node_modules/mocha/mocha.js"></script>
<script src="/node_modules/sinon/pkg/sinon.js"></script>
<script src="/node_modules/sw-testing-helpers/src/in-browser-helpers/sw-utils.js"></script>

<!-- Helper functions will be under window.testHelper -->
<script src="/test/libs/helper-functions.js"></script>
<script src="/test/libs/state-stub.js"></script>
<script src="/test/libs/is-supported.js"></script>
<script src="/test/libs/stubs/base-stub.js"></script>
<script src="/test/libs/stubs/firefox-stub.js"></script>
<script src="/test/libs/stubs/full-stub.js"></script>
<script src="/test/libs/state-stub-singleton.js"></script>

<script>mocha.setup({
ui: 'bdd'
})</script>

<!-- In browser test scripts should be added to the page here-->
<script src="/test/browser-tests/push-client/push-client-lib.js"></script>
<script src="/test/browser-tests/push-client/push-client-methods.js"></script>
<script src="/test/browser-tests/push-client/lib-usage.js"></script>
<script src="/test/browser-tests/push-client/is-supported.js"></script>
<script src="/test/browser-tests/push-client/constructor.js"></script>
<script src="/test/browser-tests/push-client/get-registration.js"></script>
<script src="/test/browser-tests/push-client/get-permission-state.js"></script>
<script src="/test/browser-tests/push-client/get-subscription.js"></script>
<script src="/test/browser-tests/push-client/status-change-event.js"></script>
<script src="/test/browser-tests/push-client/request-permission.js"></script>
<script src="/test/browser-tests/push-client/subscribe.js"></script>
<script src="/test/browser-tests/push-client/unsubscribe.js"></script>

<script>
(function() {
Expand Down Expand Up @@ -83,16 +94,18 @@
// We unregister all service workers, clear all caches and remove
// All registered iframes
beforeEach(function() {
return testHelper.cleanState();
return window.goog.SWHelper.cleanState();
});

// Clean up after the final test has finished
after(function() {
return testHelper.cleanState();
return window.goog.SWHelper.cleanState();
});

mocha.checkLeaks();
mocha.globals(['goog']);
// Services is a global that is set if we use Firefox's API to disable
// permission prompts
mocha.globals(['goog', 'Services']);
var runResults = mocha.run();
// pass, fail and end events allow up to capture results and
// determine when to publish test results
Expand Down
112 changes: 112 additions & 0 deletions test/browser-tests/push-client/constructor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
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.
*/

// This is a test and we want descriptions to be useful, if this
// breaks the max-length, it's ok.

/* eslint-disable max-len, no-unused-expressions */
/* eslint-env browser, mocha */

'use strict';

describe('Test PushClient Constructor', function() {
if (!window.isPropelClientSupported) {
return;
}

const EMPTY_SW_PATH = '/test/browser-tests/push-client/empty-sw.js';
const ERROR_MESSAGES = {
'bad constructor': 'The PushClient constructor expects either service ' +
'worker registration or the path to a service worker file and an ' +
'optional scope string.',
'redundant worker': 'Worker became redundant'
};

const getUrlAndScope = function(client) {
return client.getRegistration().then(reg => {
const sw = reg.installing || reg.waiting || reg.active;
return {url: sw.scriptURL, scope: reg.scope};
});
};

it('should throw an error for no constructor arguments', function() {
window.chai.expect(() => {
/* eslint no-unused-vars: 0 */
var client = new window.goog.propel.PropelClient();
}).to.throw(ERROR_MESSAGES['bad constructor']);
});

it('should throw an error for Object in the constructor', function() {
window.chai.expect(() => {
/* eslint no-unused-vars: 0 */
var client = new window.goog.propel.PropelClient({});
}).to.throw(ERROR_MESSAGES['bad constructor']);
});

it('should throw an error for Array in the constructor', function() {
window.chai.expect(() => {
/* eslint no-unused-vars: 0 */
var client = new window.goog.propel.PropelClient([]);
}).to.throw(ERROR_MESSAGES['bad constructor']);
});

it('should throw an error for null in the constructor', function() {
window.chai.expect(() => {
/* eslint no-unused-vars: 0 */
var client = new window.goog.propel.PropelClient(null);
}).to.throw(ERROR_MESSAGES['bad constructor']);
});

it('should throw an error for an empty string in the constructor', function() {
window.chai.expect(() => {
/* eslint no-unused-vars: 0 */
var client = new window.goog.propel.PropelClient('');
}).to.throw(ERROR_MESSAGES['bad constructor']);
});

it('should be able to create a new push client with just a workerUrl', function() {
window.chai.expect(() => {
/* eslint no-unused-vars: 0 */
var client = new window.goog.propel.PropelClient('/sw.js', null);
}).not.to.throw();
});

it('should be able to create a new push client with a workerUrl and scope', function(done) {
const pushClient = new window.goog.propel.PropelClient(EMPTY_SW_PATH, './push-service');

getUrlAndScope(pushClient).then(result => {
window.chai.expect(result.url).to.contain(EMPTY_SW_PATH);
window.chai.expect(result.scope).to.contain('/test/browser-tests/push-service');

done();
}).catch(done);
});

it('should be able to create a new push client with a service worker registration', function(done) {
navigator.serviceWorker.register(EMPTY_SW_PATH)
.then(registration => {
const pushClient = new window.goog.propel.PropelClient(registration);

return getUrlAndScope(pushClient).then(result => {
window.chai.expect(result.url).to.contain(EMPTY_SW_PATH);
window.chai.expect(result.scope).to.contain('/test/browser-tests/push-client');

done();
}).catch(done);
})
.catch(done);
});
});
Loading

0 comments on commit 297e0ca

Please sign in to comment.