feat(points): add effect engines and effects shop

This commit is contained in:
lobo committed 2026-10-01 15:09:25 +02:00
1 parent 2ec5833f29
commit dd45c0b5f6
12 files changed
+697 -11

No files matched your search

+40 -1
View File
@@ -1,6 +1,6 @@
// @vitest-environment jsdom
import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest';
import {cleanup, fireEvent, screen, waitFor, within} from '@testing-library/react';
import {act, cleanup, fireEvent, screen, waitFor, within} from '@testing-library/react';
import {toast} from 'sonner';
import PointsPage from './PointsPage.jsx';
import {fetchRoutes, json} from '../test/fetchRoutes.js';
@@ -16,6 +16,9 @@ const wallet = (extra = {}) => ({
{code: 'BORDER_GOLD', slot: 'AVATAR_BORDER', price: 150},
{code: 'BORDER_NEON', slot: 'AVATAR_BORDER', price: 200},
{code: 'BADGE_PILE_SLAYER', slot: 'BADGE', price: 100},
{code: 'FX_GOLD_SHINE', slot: 'COMPLETED_EFFECT', price: 300},
{code: 'BG_GRID', slot: 'PAGE_BACKGROUND', price: 450},
{code: 'BN_GRID', slot: 'BANNER_BACKGROUND', price: 300},
],
owned: ['BADGE_PILE_SLAYER'],
equipped: {},
@@ -47,6 +50,42 @@ afterEach(() => {
});
describe('PointsPage', () => {
it('shows the effect slots with a preview of each look', async () => {
await renderPage();
const card = (slot) => screen.getByText(`POINTS.SLOTS.${slot}`).closest('[data-slot="card"]');
const cover = within(card('COMPLETED_EFFECT')).getByText('POINTS.ITEMS.FX_GOLD_SHINE').closest('li').firstChild;
expect(cover.classList.contains('fx-cover-gold-shine')).toBe(true);
expect(card('PAGE_BACKGROUND').querySelector('[data-effect="grid"]')).not.toBeNull();
expect(card('BANNER_BACKGROUND').querySelector('[data-effect="grid"]')).not.toBeNull();
});
it('holds the frame of previews that are off screen', async () => {
const callbacks = [];
vi.stubGlobal('IntersectionObserver', class {
constructor(callback) { callbacks.push(callback); }
observe = vi.fn();
unobserve = vi.fn();
disconnect = vi.fn();
});
try {
await renderPage();
const card = (slot) => screen.getByText(`POINTS.SLOTS.${slot}`).closest('[data-slot="card"]');
const cover = within(card('COMPLETED_EFFECT')).getByText('POINTS.ITEMS.FX_GOLD_SHINE').closest('li').firstChild;
const banner = card('BANNER_BACKGROUND').querySelector('[data-effect="grid"]').parentElement;
expect(cover.classList.contains('fx-paused')).toBe(false);
act(() => callbacks[0]([{target: cover, isIntersecting: false}, {target: banner, isIntersecting: false}]));
expect(cover.classList.contains('fx-paused')).toBe(true);
expect(banner.classList.contains('fx-paused')).toBe(true);
act(() => callbacks[0]([{target: cover, isIntersecting: true}]));
expect(cover.classList.contains('fx-paused')).toBe(false);
} finally {
vi.unstubAllGlobals();
}
});
it('groups the catalog by slot and disables Buy below the price', async () => {
await renderPage();