feat: implement AI styling foundation and billing scope rework
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (push) Has been cancelled
tests / ui (push) Has been cancelled

This commit is contained in:
Codex Agent
2026-02-06 20:01:58 +01:00
parent df00deb0df
commit 36bed12ff9
80 changed files with 8944 additions and 49 deletions

View File

@@ -1,9 +1,13 @@
import React from 'react';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { render, waitFor } from '@testing-library/react';
import { render, screen, waitFor } from '@testing-library/react';
const setSearchParamsMock = vi.fn();
const pushGuestToastMock = vi.fn();
const mockEventData = {
token: 'demo',
event: { name: 'Demo Event', capabilities: { ai_styling: false } },
};
vi.mock('react-router-dom', () => ({
useNavigate: () => vi.fn(),
@@ -11,7 +15,7 @@ vi.mock('react-router-dom', () => ({
}));
vi.mock('../context/EventDataContext', () => ({
useEventData: () => ({ token: 'demo', event: { name: 'Demo Event' } }),
useEventData: () => mockEventData,
}));
vi.mock('../hooks/usePollGalleryDelta', () => ({
@@ -73,6 +77,10 @@ vi.mock('../components/ShareSheet', () => ({
default: () => null,
}));
vi.mock('../components/AiMagicEditSheet', () => ({
default: () => null,
}));
vi.mock('../lib/toast', () => ({
pushGuestToast: (...args: unknown[]) => pushGuestToastMock(...args),
}));
@@ -115,6 +123,8 @@ describe('GalleryScreen', () => {
pushGuestToastMock.mockClear();
fetchGalleryMock.mockReset();
fetchPhotoMock.mockReset();
mockEventData.token = 'demo';
mockEventData.event = { name: 'Demo Event', capabilities: { ai_styling: false } };
});
afterEach(() => {
@@ -160,4 +170,33 @@ describe('GalleryScreen', () => {
expect(setSearchParamsMock).not.toHaveBeenCalled();
expect(pushGuestToastMock).not.toHaveBeenCalled();
});
it('does not show ai magic edit action when ai styling is not entitled', async () => {
fetchGalleryMock.mockResolvedValue({
data: [{ id: 123, thumbnail_url: '/storage/demo.jpg', likes_count: 2 }],
});
fetchPhotoMock.mockRejectedValue(Object.assign(new Error('not found'), { status: 404 }));
render(<GalleryScreen />);
await waitFor(() => expect(fetchGalleryMock).toHaveBeenCalled());
await waitFor(() =>
expect(screen.queryByLabelText('AI Magic Edit')).not.toBeInTheDocument()
);
});
it('keeps ai magic edit action hidden while rollout flag is disabled', async () => {
mockEventData.event = { name: 'Demo Event', capabilities: { ai_styling: true } };
fetchGalleryMock.mockResolvedValue({
data: [{ id: 123, thumbnail_url: '/storage/demo.jpg', likes_count: 2 }],
});
fetchPhotoMock.mockRejectedValue(Object.assign(new Error('not found'), { status: 404 }));
render(<GalleryScreen />);
await waitFor(() => expect(fetchGalleryMock).toHaveBeenCalled());
await waitFor(() =>
expect(screen.queryByLabelText('AI Magic Edit')).not.toBeInTheDocument()
);
});
});