Files
plezy/website/tests/content_contracts.test.ts

173 lines
5.1 KiB
TypeScript

import { describe, expect, test } from 'bun:test';
import {
detectMobileStorePlatform,
linuxArchitectures,
storeOptionsForPlatform
} from '../src/lib/content/downloads';
import {
faqSchemaMainEntity,
faqs,
watchTogetherFaqAnswer
} from '../src/lib/content/faqs';
import {
buildSoftwareApplicationOffers,
normalizeUsdStorePrice
} from '../src/lib/content/software_app_offers';
import { csr as privacyCsr } from '../src/routes/privacy/+page';
describe('mobile store selection', () => {
test('treats missing and unrecognized client evidence as unknown', () => {
expect(detectMobileStorePlatform()).toBe('unknown');
expect(
detectMobileStorePlatform({
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)',
platform: 'Win32',
maxTouchPoints: 0
})
).toBe('unknown');
});
test('detects iOS and Android user agents', () => {
expect(
detectMobileStorePlatform({
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_0 like Mac OS X)'
})
).toBe('ios');
expect(
detectMobileStorePlatform({
userAgent: 'Mozilla/5.0 (Linux; Android 15; Pixel 9)'
})
).toBe('android');
});
test('distinguishes desktop-mode iPadOS from a non-touch Mac', () => {
const desktopSafari = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)';
expect(
detectMobileStorePlatform({
userAgent: desktopSafari,
platform: 'MacIntel',
maxTouchPoints: 5
})
).toBe('ios');
expect(
detectMobileStorePlatform({
userAgent: desktopSafari,
platform: 'MacIntel',
maxTouchPoints: 0
})
).toBe('unknown');
});
test('shows only the matching store when known and both stores when unknown', () => {
expect(storeOptionsForPlatform('ios').map((option) => option.id)).toEqual(['app-store']);
expect(storeOptionsForPlatform('android').map((option) => option.id)).toEqual([
'play-store'
]);
expect(storeOptionsForPlatform('unknown').map((option) => option.id)).toEqual([
'app-store',
'play-store'
]);
});
});
describe('Linux download inventory', () => {
test('keeps a unique four-format artifact matrix for x64 and ARM64', () => {
const artifactNames = linuxArchitectures.map((architecture) =>
architecture.formats.map(({ url }) => url.slice(url.lastIndexOf('/') + 1))
);
expect(linuxArchitectures.map(({ label }) => label)).toEqual(['x64 (Intel/AMD)', 'ARM64']);
expect(artifactNames).toEqual([
[
'plezy-linux-x64.deb',
'plezy-linux-x64.rpm',
'plezy-linux-x64.pkg.tar.zst',
'plezy-linux-x64.tar.gz'
],
[
'plezy-linux-arm64.deb',
'plezy-linux-arm64.rpm',
'plezy-linux-arm64.pkg.tar.zst',
'plezy-linux-arm64.tar.gz'
]
]);
const urls = linuxArchitectures.flatMap((architecture) =>
architecture.formats.map(({ url }) => url)
);
expect(new Set(urls).size).toBe(8);
expect(
urls.every((url) =>
url.startsWith('https://github.com/edde746/plezy/releases/latest/download/')
)
).toBe(true);
});
});
describe('software application offers', () => {
test('accepts only finite nonnegative numeric USD prices', () => {
expect(normalizeUsdStorePrice(0, 'USD')).toBe('0');
expect(normalizeUsdStorePrice(4.99, 'USD')).toBe('4.99');
for (const value of [-1, Number.NaN, Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY, '4.99', null]) {
expect(normalizeUsdStorePrice(value, 'USD')).toBeNull();
}
for (const currency of ['EUR', 'usd', '', null, undefined]) {
expect(normalizeUsdStorePrice(4.99, currency)).toBeNull();
}
});
test('keeps unavailable paid-store links without describing them as free', () => {
const offers = buildSoftwareApplicationOffers({
appStorePrice: null,
playStorePrice: null
});
expect(offers.find(({ category }) => category === 'App Store')).toEqual({
'@type': 'Offer',
url: 'https://apps.apple.com/us/app/id6754315964',
category: 'App Store'
});
expect(offers.find(({ category }) => category === 'Google Play')).toEqual({
'@type': 'Offer',
url: 'https://play.google.com/store/apps/details?id=com.edde746.plezy',
category: 'Google Play'
});
expect(offers.filter(({ price }) => price === '0').map(({ category }) => category)).toEqual([
'GitHub'
]);
});
test('attaches valid USD prices to each paid mobile store', () => {
const offers = buildSoftwareApplicationOffers({
appStorePrice: '4.99',
playStorePrice: '3.99'
});
expect(offers.find(({ category }) => category === 'App Store')).toMatchObject({
price: '4.99',
priceCurrency: 'USD'
});
expect(offers.find(({ category }) => category === 'Google Play')).toMatchObject({
price: '3.99',
priceCurrency: 'USD'
});
});
});
describe('route content contracts', () => {
test('uses the same Watch Together answer in the visible FAQ and FAQ schema', () => {
const visibleFaq = faqs.find(({ id }) => id === 'watch-together');
expect(visibleFaq).toBeDefined();
expect(visibleFaq?.answer).toBe(watchTogetherFaqAnswer);
const schemaFaq = faqSchemaMainEntity.find(({ name }) => name === visibleFaq?.question);
expect(schemaFaq).toBeDefined();
expect(schemaFaq?.acceptedAnswer.text).toBe(watchTogetherFaqAnswer);
});
test('keeps the privacy route server-rendered without client hydration', () => {
expect(privacyCsr).toBe(false);
});
});