208 lines
5.5 KiB
TypeScript
208 lines
5.5 KiB
TypeScript
|
// Copyright 2021 Signal Messenger, LLC
|
||
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||
|
|
||
|
import { assert } from 'chai';
|
||
|
import { omit } from 'lodash';
|
||
|
import { BadgeCategory } from '../../badges/BadgeCategory';
|
||
|
import { BadgeImageTheme } from '../../badges/BadgeImageTheme';
|
||
|
|
||
|
import { parseBadgesFromServer } from '../../badges/parseBadgesFromServer';
|
||
|
|
||
|
describe('parseBadgesFromServer', () => {
|
||
|
const UPDATES_URL = 'https://updates2.signal.org/desktop';
|
||
|
|
||
|
const validBadgeData = {
|
||
|
id: 'fake-badge-id',
|
||
|
category: 'donor',
|
||
|
name: 'Cool Donor',
|
||
|
description: 'Hello {short_name}',
|
||
|
svg: 'huge badge.svg',
|
||
|
svgs: ['small', 'medium', 'large'].map(size => ({
|
||
|
dark: `${size} badge dark.svg`,
|
||
|
light: `${size} badge light.svg`,
|
||
|
})),
|
||
|
};
|
||
|
const validBadge = {
|
||
|
id: validBadgeData.id,
|
||
|
category: BadgeCategory.Donor,
|
||
|
name: 'Cool Donor',
|
||
|
descriptionTemplate: 'Hello {short_name}',
|
||
|
images: [
|
||
|
...['small', 'medium', 'large'].map(size => ({
|
||
|
[BadgeImageTheme.Dark]: {
|
||
|
url: `https://updates2.signal.org/static/badges/${size}%20badge%20dark.svg`,
|
||
|
},
|
||
|
[BadgeImageTheme.Light]: {
|
||
|
url: `https://updates2.signal.org/static/badges/${size}%20badge%20light.svg`,
|
||
|
},
|
||
|
})),
|
||
|
{
|
||
|
[BadgeImageTheme.Transparent]: {
|
||
|
url: 'https://updates2.signal.org/static/badges/huge%20badge.svg',
|
||
|
},
|
||
|
},
|
||
|
],
|
||
|
};
|
||
|
|
||
|
it('returns an empty array if passed a non-array', () => {
|
||
|
[undefined, null, 'foo.svg', validBadgeData].forEach(input => {
|
||
|
assert.isEmpty(parseBadgesFromServer(input, UPDATES_URL));
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('returns an empty array if passed one', () => {
|
||
|
assert.isEmpty(parseBadgesFromServer([], UPDATES_URL));
|
||
|
});
|
||
|
|
||
|
it('parses valid badge data', () => {
|
||
|
const input = [validBadgeData];
|
||
|
assert.deepStrictEqual(parseBadgesFromServer(input, UPDATES_URL), [
|
||
|
validBadge,
|
||
|
]);
|
||
|
});
|
||
|
|
||
|
it('only returns the first 1000 badges', () => {
|
||
|
const input = Array(1234).fill(validBadgeData);
|
||
|
assert.lengthOf(parseBadgesFromServer(input, UPDATES_URL), 1000);
|
||
|
});
|
||
|
|
||
|
it('discards badges with invalid IDs', () => {
|
||
|
[undefined, null, 123].forEach(id => {
|
||
|
const invalidBadgeData = {
|
||
|
...validBadgeData,
|
||
|
name: 'Should be missing',
|
||
|
id,
|
||
|
};
|
||
|
const input = [validBadgeData, invalidBadgeData];
|
||
|
assert.deepStrictEqual(parseBadgesFromServer(input, UPDATES_URL), [
|
||
|
validBadge,
|
||
|
]);
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('discards badges with invalid names', () => {
|
||
|
[undefined, null, 123].forEach(name => {
|
||
|
const invalidBadgeData = {
|
||
|
...validBadgeData,
|
||
|
description: 'Should be missing',
|
||
|
name,
|
||
|
};
|
||
|
const input = [validBadgeData, invalidBadgeData];
|
||
|
assert.deepStrictEqual(parseBadgesFromServer(input, UPDATES_URL), [
|
||
|
validBadge,
|
||
|
]);
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('discards badges with invalid description templates', () => {
|
||
|
[undefined, null, 123].forEach(description => {
|
||
|
const invalidBadgeData = {
|
||
|
...validBadgeData,
|
||
|
name: 'Hello',
|
||
|
description,
|
||
|
};
|
||
|
const input = [validBadgeData, invalidBadgeData];
|
||
|
assert.deepStrictEqual(parseBadgesFromServer(input, UPDATES_URL), [
|
||
|
validBadge,
|
||
|
]);
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('discards badges that lack a valid "huge" SVG', () => {
|
||
|
const input = [
|
||
|
validBadgeData,
|
||
|
omit(validBadgeData, 'svg'),
|
||
|
{ ...validBadgeData, svg: 123 },
|
||
|
];
|
||
|
assert.deepStrictEqual(parseBadgesFromServer(input, UPDATES_URL), [
|
||
|
validBadge,
|
||
|
]);
|
||
|
});
|
||
|
|
||
|
it('discards badges that lack exactly 3 valid "normal" SVGs', () => {
|
||
|
const input = [
|
||
|
validBadgeData,
|
||
|
omit(validBadgeData, 'svgs'),
|
||
|
{ ...validBadgeData, svgs: 'bad!' },
|
||
|
{ ...validBadgeData, svgs: [] },
|
||
|
{
|
||
|
...validBadgeData,
|
||
|
svgs: validBadgeData.svgs.slice(0, 2),
|
||
|
},
|
||
|
{
|
||
|
...validBadgeData,
|
||
|
svgs: [{}, ...validBadgeData.svgs.slice(1)],
|
||
|
},
|
||
|
{
|
||
|
...validBadgeData,
|
||
|
svgs: [{ dark: 123 }, ...validBadgeData.svgs.slice(1)],
|
||
|
},
|
||
|
{
|
||
|
...validBadgeData,
|
||
|
svgs: [
|
||
|
...validBadgeData.svgs,
|
||
|
{
|
||
|
dark: 'too.svg',
|
||
|
light: 'many.svg',
|
||
|
},
|
||
|
],
|
||
|
},
|
||
|
];
|
||
|
assert.deepStrictEqual(parseBadgesFromServer(input, UPDATES_URL), [
|
||
|
validBadge,
|
||
|
]);
|
||
|
});
|
||
|
|
||
|
it('converts "donor" to the Donor category', () => {
|
||
|
const input = [validBadgeData];
|
||
|
assert.strictEqual(
|
||
|
parseBadgesFromServer(input, UPDATES_URL)[0]?.category,
|
||
|
BadgeCategory.Donor
|
||
|
);
|
||
|
});
|
||
|
|
||
|
it('converts "other" to the Other category', () => {
|
||
|
const input = [
|
||
|
{
|
||
|
...validBadgeData,
|
||
|
category: 'other',
|
||
|
},
|
||
|
];
|
||
|
assert.strictEqual(
|
||
|
parseBadgesFromServer(input, UPDATES_URL)[0]?.category,
|
||
|
BadgeCategory.Other
|
||
|
);
|
||
|
});
|
||
|
|
||
|
it('converts unexpected categories to Other', () => {
|
||
|
const input = [
|
||
|
{
|
||
|
...validBadgeData,
|
||
|
category: 'garbage',
|
||
|
},
|
||
|
];
|
||
|
assert.strictEqual(
|
||
|
parseBadgesFromServer(input, UPDATES_URL)[0]?.category,
|
||
|
BadgeCategory.Other
|
||
|
);
|
||
|
});
|
||
|
|
||
|
it('parses your own badges', () => {
|
||
|
const input = [
|
||
|
{
|
||
|
...validBadgeData,
|
||
|
expiration: 1234,
|
||
|
visible: true,
|
||
|
},
|
||
|
];
|
||
|
|
||
|
const badge = parseBadgesFromServer(input, UPDATES_URL)[0];
|
||
|
if (!badge || !('expiresAt' in badge) || !('isVisible' in badge)) {
|
||
|
throw new Error('Badge is invalid');
|
||
|
}
|
||
|
|
||
|
assert.strictEqual(badge.expiresAt, 1234 * 1000);
|
||
|
assert.isTrue(badge.isVisible);
|
||
|
});
|
||
|
});
|