Public Access
feat(points): show points result on every status save
Core now settles on GET /api/rewards/games/{appid}. The Frontend
shows a toast, refreshes the header balance, and lists the paid
rows and reasons on the game page. Deploy Core first.
This commit is contained in:
1 parent
9adc606c57
commit
814decc781
20 files changed
+429
-12
No files matched your search
@@ -13,8 +13,12 @@ vi.mock('sonner', () => ({toast: Object.assign(vi.fn(), {success: vi.fn(), error
|
||||
const card = (appid, question, name = `Game ${appid}`) => ({appid, name, imageUrl: null, question, status: 'PLAYING',
|
||||
playtimeMinutes: 1500, normallyMinutes: null, lastActivity: null});
|
||||
|
||||
const booked = (appid) => ({balance: 30, missing: {}, paid: [{kind: 'FINISHED', appid, points: 30, paidAt: '2026-10-09T10:00:00Z', bookedNow: true}]});
|
||||
const WALLET = {'GET /api/rewards/wallet': json(200, {balance: 30, catalog: [], owned: [], equipped: {}, history: []})};
|
||||
const pointsCalls = () => globalThis.fetch.mock.calls.filter(([url]) => url.includes('/api/rewards/games/'));
|
||||
|
||||
const renderPage = (routes) => {
|
||||
const mock = fetchRoutes(routes);
|
||||
const mock = fetchRoutes({...WALLET, ...routes});
|
||||
render(<MemoryRouter><PreferencesProvider><QuestionsPage/></PreferencesProvider></MemoryRouter>);
|
||||
return mock;
|
||||
};
|
||||
@@ -45,6 +49,7 @@ describe('QuestionsPage', () => {
|
||||
const mock = renderPage({
|
||||
'GET /api/library/questions': json(200, {results: [card(1, 'START'), card(2, 'START')]}),
|
||||
'POST /api/library/questions/1': json(200, {next: null}),
|
||||
'GET /api/rewards/games/1': json(200, booked(1)),
|
||||
});
|
||||
await screen.findByText('Game 1');
|
||||
|
||||
@@ -73,6 +78,7 @@ describe('QuestionsPage', () => {
|
||||
renderPage({
|
||||
'GET /api/library/questions': json(200, {results: [card(1, 'FINISHED')]}),
|
||||
'POST /api/library/questions/1': json(200, {next: card(1, 'RATE')}),
|
||||
'GET /api/rewards/games/1': json(200, booked(1)),
|
||||
});
|
||||
await screen.findByText('QUESTIONS.FINISHED.ASK');
|
||||
|
||||
@@ -82,6 +88,36 @@ describe('QuestionsPage', () => {
|
||||
expect(screen.queryByText('QUESTIONS.FINISHED.ASK')).toBeNull();
|
||||
});
|
||||
|
||||
it('showsThePointsToastAfterAYesToFinished', async () => {
|
||||
renderPage({
|
||||
'GET /api/library/questions': json(200, {results: [card(1, 'FINISHED')]}),
|
||||
'POST /api/library/questions/1': json(200, {next: null}),
|
||||
'GET /api/rewards/games/1': json(200, booked(1)),
|
||||
});
|
||||
await screen.findByText('QUESTIONS.FINISHED.ASK');
|
||||
|
||||
fireEvent.click(screen.getByRole('button', {name: 'QUESTIONS.YES'}));
|
||||
|
||||
await waitFor(() => expect(toast.success).toHaveBeenCalledWith('POINTS.GAME.TOAST_BOOKED:30'));
|
||||
expect(pointsCalls()).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('asksForNoPointsAfterANoOrTheRatingAnswer', async () => {
|
||||
renderPage({
|
||||
'GET /api/library/questions': json(200, {results: [card(1, 'FINISHED'), card(2, 'RATE')]}),
|
||||
'POST /api/library/questions/1': json(200, {next: null}),
|
||||
'POST /api/library/questions/2': json(200, {next: null}),
|
||||
});
|
||||
await screen.findByText('Game 1');
|
||||
|
||||
fireEvent.click(screen.getAllByRole('button', {name: 'QUESTIONS.NO'})[0]);
|
||||
await waitFor(() => expect(screen.queryByText('Game 1')).toBeNull());
|
||||
fireEvent.click(screen.getByRole('button', {name: 'BACKLOG.RATING_STARS:5'}));
|
||||
await screen.findByText('QUESTIONS.EMPTY');
|
||||
|
||||
expect(pointsCalls()).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('sendsTheRatingOfTheStars', async () => {
|
||||
const mock = renderPage({
|
||||
'GET /api/library/questions': json(200, {results: [card(1, 'RATE')]}),
|
||||
|
||||
Reference in new issue
Block a user