Skip to content

Commit 2bd428f

Browse files
yifanyangmmermerkaya
authored andcommitted
PR #700
1 parent d35dd55 commit 2bd428f

File tree

8 files changed

+166
-61
lines changed

8 files changed

+166
-61
lines changed

integration/shared/validator.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,16 @@ function validateNamespace(definition, candidate) {
8888
if (
8989
definitionChunk.__type === 'function' &&
9090
definitionChunk.__return &&
91-
typeof candidateChunk === 'function' &&
92-
candidateChunk()
91+
typeof candidateChunk === 'function'
9392
) {
93+
try {
94+
candidateChunk();
95+
} catch (e) {
96+
it(`Throws because current browser is unsupported`, () => {
97+
__expect(e.code).to.have.string('unsupported-browser');
98+
});
99+
return;
100+
}
94101
validateNamespace(definitionChunk.__return, candidateChunk());
95102
}
96103
});

packages/functions/test/browser/callable.test.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,16 @@ describe('Firebase Functions > Call', () => {
6868
// TODO(klimt): Move this to the cross-platform tests and delete this file,
6969
// once instance id works there.
7070
it('instance id', async () => {
71+
if (!('serviceWorker' in navigator)) {
72+
// Current platform does not support messaging, skip test.
73+
return;
74+
}
75+
7176
// Stub out the messaging method get an instance id token.
72-
const messaging = (firebase as any).messaging(app);
73-
const stub = sinon.stub(messaging, 'getToken');
74-
stub.returns(Promise.resolve('iid'));
77+
const messaging = firebase.messaging(app);
78+
const stub = sinon
79+
.stub(messaging, 'getToken')
80+
.returns(Promise.resolve('iid'));
7581

7682
const func = functions.httpsCallable('instanceIdTest');
7783
const result = await func({});

packages/messaging/index.ts

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,29 @@ import {
1919
_FirebaseNamespace,
2020
FirebaseServiceFactory
2121
} from '@firebase/app-types/private';
22+
2223
import { SWController } from './src/controllers/sw-controller';
2324
import { WindowController } from './src/controllers/window-controller';
25+
import { ERROR_CODES, errorFactory } from './src/models/errors';
2426

2527
import * as types from '@firebase/messaging-types';
2628

2729
export function registerMessaging(instance: _FirebaseNamespace): void {
2830
const messagingName = 'messaging';
2931
const factoryMethod: FirebaseServiceFactory = app => {
3032
if (self && 'ServiceWorkerGlobalScope' in self) {
31-
return new SWController(app);
33+
// Running in ServiceWorker context
34+
if (isSWControllerSupported()) {
35+
return new SWController(app);
36+
}
37+
} else {
38+
// Assume we are in the window context.
39+
if (isWindowControllerSupported()) {
40+
return new WindowController(app);
41+
}
3242
}
3343

34-
// Assume we are in the window context.
35-
return new WindowController(app);
44+
throw errorFactory.create(ERROR_CODES.UNSUPPORTED_BROWSER);
3645
};
3746

3847
const namespaceExports = {
@@ -63,3 +72,29 @@ declare module '@firebase/app-types' {
6372
messaging?(): types.FirebaseMessaging;
6473
}
6574
}
75+
76+
/**
77+
* Checks to see if the required APIs exist.
78+
*/
79+
export function isWindowControllerSupported(): boolean {
80+
return (
81+
'serviceWorker' in navigator &&
82+
'PushManager' in window &&
83+
'Notification' in window &&
84+
'fetch' in window &&
85+
ServiceWorkerRegistration.prototype.hasOwnProperty('showNotification') &&
86+
PushSubscription.prototype.hasOwnProperty('getKey')
87+
);
88+
}
89+
90+
/**
91+
* Checks to see if the required APIs exist within SW Context.
92+
*/
93+
function isSWControllerSupported(): boolean {
94+
return (
95+
'PushManager' in self &&
96+
'Notification' in self &&
97+
ServiceWorkerRegistration.prototype.hasOwnProperty('showNotification') &&
98+
PushSubscription.prototype.hasOwnProperty('getKey')
99+
);
100+
}

packages/messaging/src/controllers/window-controller.ts

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,6 @@ export class WindowController extends ControllerInterface {
7474
* permission isn't granted.
7575
*/
7676
getToken(): Promise<string | null> {
77-
// Check that the required API's are available
78-
if (!WindowController.isSupported_()) {
79-
return Promise.reject(
80-
errorFactory.create(ERROR_CODES.UNSUPPORTED_BROWSER)
81-
);
82-
}
83-
8477
return this.manifestCheck_().then(() => {
8578
return super.getToken();
8679
});
@@ -355,10 +348,6 @@ export class WindowController extends ControllerInterface {
355348
// Visible for testing
356349
// TODO: Make private
357350
setupSWMessageListener_(): void {
358-
if (!('serviceWorker' in navigator)) {
359-
return;
360-
}
361-
362351
navigator.serviceWorker.addEventListener(
363352
'message',
364353
event => {
@@ -384,21 +373,4 @@ export class WindowController extends ControllerInterface {
384373
false
385374
);
386375
}
387-
388-
/**
389-
* Checks to see if the required API's are valid or not.
390-
* @return Returns true if the desired APIs are available.
391-
*/
392-
// Visible for testing
393-
// TODO: Make private
394-
static isSupported_(): boolean {
395-
return (
396-
'serviceWorker' in navigator &&
397-
'PushManager' in window &&
398-
'Notification' in window &&
399-
'fetch' in window &&
400-
ServiceWorkerRegistration.prototype.hasOwnProperty('showNotification') &&
401-
PushSubscription.prototype.hasOwnProperty('getKey')
402-
);
403-
}
404376
}

packages/messaging/test/controller-get-token.test.ts

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -130,22 +130,6 @@ describe('Firebase Messaging > *Controller.getToken()', () => {
130130
return cleanUp();
131131
});
132132

133-
it('should throw on unsupported browsers', () => {
134-
sandbox
135-
.stub(WindowController, 'isSupported_')
136-
.callsFake(() => false);
137-
138-
const messagingService = new WindowController(app);
139-
return messagingService.getToken().then(
140-
() => {
141-
throw new Error('Expected getToken to throw ');
142-
},
143-
err => {
144-
assert.equal('messaging/' + ERROR_CODES.UNSUPPORTED_BROWSER, err.code);
145-
}
146-
);
147-
});
148-
149133
it('should handle a failure to get registration', () => {
150134
sandbox
151135
.stub(ControllerInterface.prototype, 'getNotificationPermission_')
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/**
2+
* Copyright 2018 Google Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import { expect } from 'chai';
18+
import { sandbox, SinonSandbox, SinonStub } from 'sinon';
19+
20+
import { FirebaseApp } from '@firebase/app-types';
21+
import {
22+
_FirebaseNamespace,
23+
FirebaseServiceFactory
24+
} from '@firebase/app-types/private';
25+
26+
import { registerMessaging } from '../index';
27+
import { ERROR_CODES } from '../src/models/errors';
28+
29+
import { SWController } from '../src/controllers/sw-controller';
30+
import { WindowController } from '../src/controllers/window-controller';
31+
import { makeFakeApp } from './testing-utils/make-fake-app';
32+
33+
describe('Firebase Messaging > registerMessaging', () => {
34+
let sinonSandbox: SinonSandbox;
35+
let registerService: SinonStub;
36+
let fakeFirebase: _FirebaseNamespace;
37+
38+
beforeEach(() => {
39+
sinonSandbox = sandbox.create();
40+
registerService = sinonSandbox.stub();
41+
42+
fakeFirebase = {
43+
INTERNAL: { registerService }
44+
} as any;
45+
});
46+
47+
afterEach(() => {
48+
sinonSandbox.restore();
49+
});
50+
51+
it('calls registerService', () => {
52+
registerMessaging(fakeFirebase);
53+
expect(registerService.callCount).to.equal(1);
54+
});
55+
56+
describe('factoryMethod', () => {
57+
let factoryMethod: FirebaseServiceFactory;
58+
let fakeApp: FirebaseApp;
59+
60+
beforeEach(() => {
61+
registerMessaging(fakeFirebase);
62+
factoryMethod = registerService.getCall(0).args[1];
63+
64+
fakeApp = makeFakeApp({
65+
messagingSenderId: '1234567890'
66+
});
67+
});
68+
69+
describe('in Service Worker context', () => {
70+
beforeEach(() => {
71+
// self.ServiceWorkerGlobalScope exists
72+
// can't stub a non-existing property, so no sinon.stub().
73+
(self as any).ServiceWorkerGlobalScope = {};
74+
});
75+
76+
afterEach(() => {
77+
delete (self as any).ServiceWorkerGlobalScope;
78+
});
79+
80+
it('returns a SWController', () => {
81+
const firebaseService = factoryMethod(fakeApp);
82+
expect(firebaseService).to.be.instanceOf(SWController);
83+
});
84+
});
85+
86+
describe('in Window context', () => {
87+
it('throws if required globals do not exist', () => {
88+
// Empty navigator, no navigator.serviceWorker ¯\_(ツ)_/¯
89+
sinonSandbox.stub(window, 'navigator').value({});
90+
91+
try {
92+
factoryMethod(fakeApp);
93+
} catch (e) {
94+
expect(e.code).to.equal(
95+
'messaging/' + ERROR_CODES.UNSUPPORTED_BROWSER
96+
);
97+
return;
98+
}
99+
throw new Error('Expected getToken to throw ');
100+
});
101+
102+
it('returns a WindowController', () => {
103+
const firebaseService = factoryMethod(fakeApp);
104+
expect(firebaseService).to.be.instanceOf(WindowController);
105+
});
106+
});
107+
});
108+
});

packages/messaging/test/testing-utils/messaging-test-runner.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
* limitations under the License.
1515
*/
1616

17-
import { WindowController } from '../../src/controllers/window-controller';
17+
import { isWindowControllerSupported } from '../../index';
1818

1919
/** Runner for tests that require service worker functionality. */
20-
const runner = WindowController.isSupported_() ? describe : describe.skip;
20+
const runner = isWindowControllerSupported() ? describe : describe.skip;
2121
export { runner as describe };

packages/messaging/test/window-controller.test.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -351,13 +351,6 @@ describe('Firebase Messaging > *WindowController', () => {
351351
});
352352

353353
describe('setupSWMessageListener_()', () => {
354-
it('should not do anything is no service worker support', () => {
355-
sandbox.stub(window, 'navigator').value({});
356-
357-
const controller = new WindowController(app);
358-
controller.setupSWMessageListener_();
359-
});
360-
361354
it('should add listener when supported', () => {
362355
const spy = sandbox.spy();
363356
sandbox.stub(navigator, 'serviceWorker').value({

0 commit comments

Comments
 (0)