7a0da7932b
OSV-Scanner (Scheduled) / scan-scheduled (push) Failing after 0s
Create Release / test-gate (push) Has been cancelled
Create Release / release-gate (push) Has been cancelled
Create Release / ci-gate (push) Has been cancelled
Create Release / version-check (push) Has been cancelled
Create Release / e2e-test-gate (push) Has been cancelled
Create Release / responsive-test-gate (push) Has been cancelled
Create Release / compat-test-gate (push) Has been cancelled
Create Release / compose-integration-gate (push) Has been cancelled
Create Release / vulture-gate (push) Has been cancelled
Create Release / build (push) Has been cancelled
Create Release / provenance (push) Has been cancelled
Create Release / prerelease-docker (push) Has been cancelled
Create Release / publish-docker (push) Has been cancelled
Create Release / create-release (push) Has been cancelled
Create Release / cleanup-changelog (push) Has been cancelled
Create Release / trigger-pypi (push) Has been cancelled
Create Release / monitor-pypi (push) Has been cancelled
Create Release / Clean up orphan prerelease tags and signatures (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Has been cancelled
Docker Tests (Consolidated) / Accessibility Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Unit Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Example Tests (push) Has been cancelled
Docker Tests (Consolidated) / Production Image Smoke Test (push) Has been cancelled
Docker Tests (Consolidated) / Infrastructure Tests (push) Has been cancelled
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Has been cancelled
Backwards Compatibility / Verify Encryption Constants (push) Has been cancelled
Backwards Compatibility / PyPI Version Compatibility (push) Has been cancelled
Backwards Compatibility / Database Migration Tests (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Docker Tests (Consolidated) / detect-changes (push) Has been cancelled
Docker Tests (Consolidated) / Build Test Image (push) Has been cancelled
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Has been cancelled
70 lines
2.5 KiB
JavaScript
70 lines
2.5 KiB
JavaScript
/**
|
|
* Tests for components/subscription-manager.js — formatTimeUntil.
|
|
*
|
|
* Pure math that powers the "Next refresh" label on subscription cards.
|
|
* Boundary behavior (≤0 collapses to "Now", minute/hour/day transitions)
|
|
* has bitten this kind of code before; lock it down here so future
|
|
* refactors of the display label don't silently flip a day boundary.
|
|
*/
|
|
|
|
import '@js/components/subscription-manager.js';
|
|
|
|
let formatTimeUntil;
|
|
|
|
beforeAll(() => {
|
|
// The module wires up its singleton inside a DOMContentLoaded listener.
|
|
// happy-dom usually fires the lifecycle event before the import settles,
|
|
// so dispatch it manually if the singleton isn't there yet.
|
|
if (!window.subscriptionManager) {
|
|
document.dispatchEvent(new Event('DOMContentLoaded'));
|
|
}
|
|
formatTimeUntil = window.subscriptionManager.formatTimeUntil.bind(
|
|
window.subscriptionManager
|
|
);
|
|
});
|
|
|
|
describe('subscriptionManager.formatTimeUntil', () => {
|
|
it('returns "Now" for 0 ms', () => {
|
|
expect(formatTimeUntil(0)).toBe('Now');
|
|
});
|
|
|
|
it('returns "Now" for negative ms (overdue subscription)', () => {
|
|
expect(formatTimeUntil(-5000)).toBe('Now');
|
|
expect(formatTimeUntil(-86_400_000)).toBe('Now');
|
|
});
|
|
|
|
it('returns minutes for sub-hour durations', () => {
|
|
expect(formatTimeUntil(2 * 60 * 1000)).toBe('2m');
|
|
expect(formatTimeUntil(59 * 60 * 1000)).toBe('59m');
|
|
});
|
|
|
|
it('returns "0m" for sub-minute positive durations', () => {
|
|
// 30 seconds — too short for a minute, but > 0 so not "Now".
|
|
expect(formatTimeUntil(30_000)).toBe('0m');
|
|
});
|
|
|
|
it('returns hours once at the 1-hour boundary', () => {
|
|
expect(formatTimeUntil(60 * 60 * 1000)).toBe('1h');
|
|
expect(formatTimeUntil(23 * 60 * 60 * 1000)).toBe('23h');
|
|
});
|
|
|
|
it('returns days once at the 24-hour boundary', () => {
|
|
expect(formatTimeUntil(24 * 60 * 60 * 1000)).toBe('1d');
|
|
expect(formatTimeUntil(7 * 24 * 60 * 60 * 1000)).toBe('7d');
|
|
});
|
|
|
|
it('handles very large durations without overflow', () => {
|
|
// 999 days
|
|
expect(formatTimeUntil(999 * 24 * 60 * 60 * 1000)).toBe('999d');
|
|
});
|
|
|
|
it('floors at unit boundaries — 25h reports as 1d, not 1h', () => {
|
|
expect(formatTimeUntil(25 * 60 * 60 * 1000)).toBe('1d');
|
|
});
|
|
|
|
it('floors just under the next unit (59m59s stays minutes)', () => {
|
|
const ms = 59 * 60 * 1000 + 59 * 1000;
|
|
expect(formatTimeUntil(ms)).toBe('59m');
|
|
});
|
|
});
|