Add consent-gated media exchange library
This commit is contained in:
1 parent
b8e4a1bb88
commit
bf474dfe10
42 files changed
+2533
-9
No files matched your search
@@ -0,0 +1,76 @@
|
||||
// @vitest-environment jsdom
|
||||
|
||||
import '@testing-library/jest-dom/vitest';
|
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||
import { cleanup, render, screen, waitFor } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { HttpResponse, http } from 'msw';
|
||||
import { setupServer } from 'msw/node';
|
||||
import { afterAll, afterEach, beforeAll, describe, expect, it, vi } from 'vitest';
|
||||
import { MediaLibraryPage } from '../../apps/dashboard/src/features/media-library/media-library-page.js';
|
||||
|
||||
const asset = {
|
||||
id: '019fe789-1b99-7ce1-8402-b3cbc32a445a', tags: ['selfie'], safety: 'sfw',
|
||||
classificationStatus: 'ready', description: 'A face-led self portrait.', confidence: 0.91,
|
||||
fileName: 'portrait.jpg', mimeType: 'image/jpeg', sizeBytes: 1024, width: 640, height: 480,
|
||||
enabled: true, consentConfirmedAt: 1, createdAt: 1, updatedAt: 1,
|
||||
sendCount: 0, lastSentAt: null,
|
||||
urlPath: '/library-media/portrait.jpg',
|
||||
};
|
||||
const server = setupServer();
|
||||
|
||||
function renderPage() {
|
||||
const client = new QueryClient({ defaultOptions: { queries: { retry: false }, mutations: { retry: false } } });
|
||||
return render(<QueryClientProvider client={client}><MediaLibraryPage /></QueryClientProvider>);
|
||||
}
|
||||
|
||||
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));
|
||||
afterEach(() => { cleanup(); server.resetHandlers(); vi.restoreAllMocks(); });
|
||||
afterAll(() => server.close());
|
||||
|
||||
describe('exchange library page', () => {
|
||||
it('keeps images blurred and saves operator tag corrections', async () => {
|
||||
let update: unknown;
|
||||
server.use(
|
||||
http.get('/api/media-library', () => HttpResponse.json([asset])),
|
||||
http.patch('/api/media-library/:id', async ({ request }) => {
|
||||
update = await request.json();
|
||||
return HttpResponse.json({ ...asset, ...(update as object) });
|
||||
}),
|
||||
);
|
||||
const user = userEvent.setup();
|
||||
renderPage();
|
||||
|
||||
const image = await screen.findByRole('img', { name: /Library image tagged selfie/i });
|
||||
expect(image).toHaveClass('is-blurred');
|
||||
await user.click(screen.getByRole('button', { name: 'Reveal' }));
|
||||
expect(image).not.toHaveClass('is-blurred');
|
||||
await user.click(screen.getByRole('checkbox', { name: 'topless' }));
|
||||
await user.selectOptions(screen.getByRole('combobox', { name: 'Safety' }), 'nsfw');
|
||||
await user.click(screen.getByRole('button', { name: 'Save changes' }));
|
||||
await waitFor(() => expect(update).toEqual({ tags: ['selfie', 'topless'], safety: 'nsfw', enabled: true }));
|
||||
});
|
||||
|
||||
it('requires consent in the UI and uploads the selected image for classification', async () => {
|
||||
let consentHeader: string | null = null;
|
||||
server.use(
|
||||
http.get('/api/media-library', () => HttpResponse.json([])),
|
||||
http.post('/api/media-library', ({ request }) => {
|
||||
consentHeader = request.headers.get('x-consent-confirmed');
|
||||
return HttpResponse.json(asset, { status: 201 });
|
||||
}),
|
||||
);
|
||||
const user = userEvent.setup();
|
||||
renderPage();
|
||||
await screen.findByText('No exchange images yet.');
|
||||
const upload = screen.getByRole('button', { name: 'Upload and classify' });
|
||||
expect(upload).toBeDisabled();
|
||||
await user.upload(screen.getByLabelText(/Choose image/), new File(['image'], 'portrait.jpg', { type: 'image/jpeg' }));
|
||||
expect(upload).toBeDisabled();
|
||||
await user.click(screen.getByRole('checkbox', { name: /I confirm every depicted adult consented/i }));
|
||||
expect(upload).toBeEnabled();
|
||||
await user.click(upload);
|
||||
await screen.findByText('Image added. Review its tags before relying on it.');
|
||||
expect(consentHeader).toBe('true');
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user