mirror of
https://github.com/civitai/civitai.git
synced 2026-09-20 22:08:18 +08:00
8fddfbe6e0
Moderators can now put an already-transferred Hugging Face file onto a model version without leaving its Manage files page. The "Add from Hugging Face imports" button opens a picker that lists unattached imports, grouped by batch and filterable by group name; each file is attached once a type is chosen for it. The type is never defaulted. `suggestFileType` deliberately makes no suggestion for primary weights, and that label decides whether the version loads, so a list's first entry is not a safe fallback. A suggestion, where one exists, is shown only as the placeholder. The import page's own Attach control dropped the same fallback. The picker opens through the dialog store. Manage files is itself a store dialog, and an inline Modal rendered at Mantine's lower default z-index, behind it, so the button appeared to do nothing. `FilesProvider` seeds its file list once, so a file created outside its upload path never appeared until a reload. `adoptFiles` adds the named files, read from `getByIdForEdit` (the primary): append-only, so unsaved metadata edits and in-flight uploads are untouched. The server-row mapping is now one function shared with the initial seed. The attach loop runs one file at a time, attempts every file after a failure, and reports the ids it created. A lost import claim leaves a created file whose id appears only in the error, so every failure is shown and the notification stays open. `getModelFileTypeOptions` is now the one definition of the file-type list and its labels, used by the picker, the Attach control and the creator's own type select. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015cyrXpr87t9Tj3bnzRrUhp
50 lines
1.9 KiB
TypeScript
50 lines
1.9 KiB
TypeScript
import { describe, expect, test, vi } from 'vitest';
|
|
import { page } from 'vitest/browser';
|
|
import type * as FilesProviderModule from '~/components/Resource/FilesProvider';
|
|
import { renderWithProviders } from '../../../../test/component-setup';
|
|
|
|
const { mockOpen, mockAdoptFiles, user } = vi.hoisted(() => ({
|
|
mockOpen: vi.fn(),
|
|
mockAdoptFiles: vi.fn(),
|
|
user: { current: { isModerator: true } as { isModerator: boolean } | null },
|
|
}));
|
|
|
|
// Pins the dialog-store route; the reason is on AddFromImportsButton.
|
|
vi.mock('~/components/Dialog/triggers/add-from-hugging-face-imports', () => ({
|
|
openAddFromImportsModal: mockOpen,
|
|
}));
|
|
vi.mock('~/components/Resource/FilesProvider', async (importOriginal) => ({
|
|
...(await importOriginal<typeof FilesProviderModule>()),
|
|
useFilesContext: () => ({ adoptFiles: mockAdoptFiles, modelType: 'Checkpoint' }),
|
|
}));
|
|
vi.mock('~/hooks/useCurrentUser', () => ({ useCurrentUser: () => user.current }));
|
|
|
|
import { AddFromImportsButton } from '~/components/Moderation/HuggingFaceImport/AddFromImportsButton';
|
|
|
|
describe('AddFromImportsButton', () => {
|
|
test('opens the picker through the dialog store, with the provider handles', async () => {
|
|
user.current = { isModerator: true };
|
|
renderWithProviders(<AddFromImportsButton modelVersionId={42} />);
|
|
|
|
await page.getByRole('button', { name: 'Add from Hugging Face imports' }).click();
|
|
|
|
expect(mockOpen).toHaveBeenCalledWith({
|
|
modelVersionId: 42,
|
|
modelType: 'Checkpoint',
|
|
adoptFiles: mockAdoptFiles,
|
|
});
|
|
});
|
|
|
|
test('renders nothing for a non-moderator', async () => {
|
|
user.current = { isModerator: false };
|
|
renderWithProviders(
|
|
<div data-testid="host">
|
|
<AddFromImportsButton modelVersionId={42} />
|
|
</div>
|
|
);
|
|
|
|
await expect.element(page.getByTestId('host')).toBeInTheDocument();
|
|
expect(page.getByTestId('host').element().childElementCount).toBe(0);
|
|
});
|
|
});
|