Files
vngeoguessr/tests/daily-progress.test.js
tiennm99 8450b75bce feat(daily): one panorama a day, the same for everyone, with a streak
/api/daily opens an ordinary session on a panorama picked
deterministically from the day and cached in Redis for two days, so
the Postgres draw and the Mapillary lookup happen once a day. Days
roll over at midnight Vietnam time. The round is scored by /api/guess
like any other and counted under its own level in the statistics.

There is no daily leaderboard: the only identity is a cookie and a
localStorage name, so a dated board would be won by whoever opened the
most private windows. The browser keeps the finished round and replays
it on a revisit, and tracks the streak of consecutive days. The home
page carries the challenge card and the result dialog shares the
outcome as a squares line.
2026-09-20 23:23:02 +07:00

29 lines
1.1 KiB
JavaScript

import { describe, it, expect } from 'vitest';
import { nextStreak, currentStreak } from '../src/lib/daily-progress.js';
// The streak rule, without a browser: the day after the last play extends it,
// the same day keeps it, any gap restarts it.
describe('daily streak', () => {
const played = (day, streak) => ({ day, streak });
it('starts at one with no history', () => {
expect(nextStreak(null, '2026-09-21')).toBe(1);
});
it('extends across consecutive days and keeps within a day', () => {
expect(nextStreak(played('2026-09-20', 3), '2026-09-21')).toBe(4);
expect(nextStreak(played('2026-09-21', 4), '2026-09-21')).toBe(4);
});
it('restarts after a missed day', () => {
expect(nextStreak(played('2026-09-19', 7), '2026-09-21')).toBe(1);
});
it('shows a streak only while it is still alive', () => {
expect(currentStreak(null, '2026-09-21')).toBe(0);
expect(currentStreak(played('2026-09-21', 2), '2026-09-21')).toBe(2);
expect(currentStreak(played('2026-09-20', 2), '2026-09-21')).toBe(2);
expect(currentStreak(played('2026-09-18', 9), '2026-09-21')).toBe(0);
});
});