55 lines
3.3 KiB
JavaScript
55 lines
3.3 KiB
JavaScript
|
|
"use strict";
|
||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||
|
|
const pruneTokens_1 = require("./pruneTokens");
|
||
|
|
// Shapes mirror what firebase-admin's FirebaseMessagingError actually throws (see errorInfo.code),
|
||
|
|
// plus the `code` getter form. Both must be recognised; transient/server errors must NOT be.
|
||
|
|
const deadNotRegistered = { errorInfo: { code: 'messaging/registration-token-not-registered' }, codePrefix: 'messaging' };
|
||
|
|
const deadInvalidToken = { code: 'messaging/invalid-registration-token' };
|
||
|
|
const transientUnavailable = { errorInfo: { code: 'messaging/server-unavailable' } };
|
||
|
|
const transientInternal = { code: 'messaging/internal-error' };
|
||
|
|
const badPayload = { errorInfo: { code: 'messaging/invalid-argument' } }; // payload bug — must NOT prune
|
||
|
|
const rej = (reason) => ({ status: 'rejected', reason });
|
||
|
|
const ful = () => ({ status: 'fulfilled', value: 'id' });
|
||
|
|
describe('isDeadTokenError', () => {
|
||
|
|
it('is true for permanently-dead token codes (both errorInfo.code and code shapes)', () => {
|
||
|
|
expect((0, pruneTokens_1.isDeadTokenError)(deadNotRegistered)).toBe(true);
|
||
|
|
expect((0, pruneTokens_1.isDeadTokenError)(deadInvalidToken)).toBe(true);
|
||
|
|
});
|
||
|
|
it('is false for transient/server errors — never prune on these', () => {
|
||
|
|
expect((0, pruneTokens_1.isDeadTokenError)(transientUnavailable)).toBe(false);
|
||
|
|
expect((0, pruneTokens_1.isDeadTokenError)(transientInternal)).toBe(false);
|
||
|
|
});
|
||
|
|
it('is false for invalid-argument — that blames the payload, not the token', () => {
|
||
|
|
expect((0, pruneTokens_1.isDeadTokenError)(badPayload)).toBe(false);
|
||
|
|
});
|
||
|
|
it('is false for missing/garbage reasons (fail safe)', () => {
|
||
|
|
expect((0, pruneTokens_1.isDeadTokenError)(undefined)).toBe(false);
|
||
|
|
expect((0, pruneTokens_1.isDeadTokenError)(null)).toBe(false);
|
||
|
|
expect((0, pruneTokens_1.isDeadTokenError)({})).toBe(false);
|
||
|
|
expect((0, pruneTokens_1.isDeadTokenError)('boom')).toBe(false);
|
||
|
|
expect((0, pruneTokens_1.isDeadTokenError)({ code: 42 })).toBe(false);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
describe('selectDeadTokens', () => {
|
||
|
|
it('maps rejected-dead results to their token by index', () => {
|
||
|
|
const tokens = ['A', 'B', 'C'];
|
||
|
|
const results = [ful(), rej(deadNotRegistered), rej(transientUnavailable)];
|
||
|
|
expect((0, pruneTokens_1.selectDeadTokens)(tokens, results)).toEqual(['B']);
|
||
|
|
});
|
||
|
|
it('ignores fulfilled sends and transient failures', () => {
|
||
|
|
const tokens = ['A', 'B'];
|
||
|
|
expect((0, pruneTokens_1.selectDeadTokens)(tokens, [ful(), rej(transientInternal)])).toEqual([]);
|
||
|
|
});
|
||
|
|
it('dedupes when the same dead token appears twice', () => {
|
||
|
|
const tokens = ['A', 'A'];
|
||
|
|
expect((0, pruneTokens_1.selectDeadTokens)(tokens, [rej(deadNotRegistered), rej(deadInvalidToken)])).toEqual(['A']);
|
||
|
|
});
|
||
|
|
it('returns empty when there are no failures', () => {
|
||
|
|
expect((0, pruneTokens_1.selectDeadTokens)(['A', 'B'], [ful(), ful()])).toEqual([]);
|
||
|
|
});
|
||
|
|
it('never selects a token whose index is missing', () => {
|
||
|
|
// more results than tokens (defensive) — no crash, no phantom token
|
||
|
|
expect((0, pruneTokens_1.selectDeadTokens)(['A'], [rej(deadNotRegistered), rej(deadNotRegistered)])).toEqual(['A']);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
//# sourceMappingURL=pruneTokens.test.js.map
|