From 3af9524a00e7fa69e9621d26e6eec1fa74c981e7 Mon Sep 17 00:00:00 2001 From: Nicolas Clerc Date: Mon, 7 Aug 2023 14:17:48 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=9A(frontend)=20use=20nested=20routes?= =?UTF-8?q?=20for=20classroom=20related=20resources?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As we want to only use API nested routes, our classroom components needs to handle them. --- .../DocumentRow/index.spec.tsx | 36 ++++++++- .../UploadDocuments/DocumentRow/index.tsx | 21 +++-- .../UploadDocuments/index.spec.tsx | 80 ++++++++++++------- .../SupportSharing/UploadDocuments/index.tsx | 6 +- .../DashboardClassroom/index.spec.tsx | 6 +- .../src/data/queries/index.spec.tsx | 23 ++++-- .../lib_classroom/src/data/queries/index.tsx | 33 +++++--- .../createClassroomDocument/index.spec.ts | 22 +++-- .../createClassroomDocument/index.ts | 6 +- .../src/utils/tests/factories.ts | 2 +- 10 files changed, 165 insertions(+), 70 deletions(-) diff --git a/src/frontend/packages/lib_classroom/src/components/ClassroomWidgetProvider/widgets/SupportSharing/UploadDocuments/DocumentRow/index.spec.tsx b/src/frontend/packages/lib_classroom/src/components/ClassroomWidgetProvider/widgets/SupportSharing/UploadDocuments/DocumentRow/index.spec.tsx index bba6fbebad..d8459da5c3 100644 --- a/src/frontend/packages/lib_classroom/src/components/ClassroomWidgetProvider/widgets/SupportSharing/UploadDocuments/DocumentRow/index.spec.tsx +++ b/src/frontend/packages/lib_classroom/src/components/ClassroomWidgetProvider/widgets/SupportSharing/UploadDocuments/DocumentRow/index.spec.tsx @@ -1,5 +1,6 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; -import { render, screen } from '@testing-library/react'; +import { render, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; import fetchMock from 'fetch-mock'; import { uploadState, useJwt } from 'lib-components'; import { wrapInIntlProvider } from 'lib-tests'; @@ -73,6 +74,39 @@ describe('', () => { ).toBeEnabled(); }); + it('sets a document as default', async () => { + const classroom = classroomMockFactory({ started: false }); + const document = classroomDocumentMockFactory({ + filename: 'my_document.pdf', + classroom_id: classroom.id, + }); + fetchMock.patch( + `/api/classrooms/${classroom.id}/classroomdocuments/${document.id}/`, + { + ...document, + is_default: true, + }, + ); + render( + wrapInIntlProvider( + wrapInClassroom( + + + , + classroom, + ), + ), + ); + + userEvent.click( + screen.getByRole('button', { name: 'Click to set as default document' }), + ); + await waitFor(() => expect(fetchMock.calls()).toHaveLength(1)); + }); + it('renders a row in UPLOAD_IN_PROGRESS state', () => { const classroom = classroomMockFactory({ id: '1', started: false }); const document = classroomDocumentMockFactory({ diff --git a/src/frontend/packages/lib_classroom/src/components/ClassroomWidgetProvider/widgets/SupportSharing/UploadDocuments/DocumentRow/index.tsx b/src/frontend/packages/lib_classroom/src/components/ClassroomWidgetProvider/widgets/SupportSharing/UploadDocuments/DocumentRow/index.tsx index 7f41164871..6472002548 100644 --- a/src/frontend/packages/lib_classroom/src/components/ClassroomWidgetProvider/widgets/SupportSharing/UploadDocuments/DocumentRow/index.tsx +++ b/src/frontend/packages/lib_classroom/src/components/ClassroomWidgetProvider/widgets/SupportSharing/UploadDocuments/DocumentRow/index.tsx @@ -65,7 +65,10 @@ export const DocumentRow = ({ uploadingObject, }: DocumentRowProps) => { const intl = useIntl(); - const updateClassroomMutation = useUpdateClassroomDocument(document.id); + const updateClassroomMutation = useUpdateClassroomDocument( + document.classroom_id, + document.id, + ); const deleteDocumentMutation = useDeleteClassroomDocument(); const [isUploadInProgress, setIsUploadInProgress] = useState(false); @@ -88,12 +91,18 @@ export const DocumentRow = ({ }, [updateClassroomMutation]); const setDeleteDocument = useCallback(() => { - deleteDocumentMutation.mutate(document.id, { - onSuccess: () => { - window.dispatchEvent(new CustomEvent('classroomDocumentUpdated')); + deleteDocumentMutation.mutate( + { + classroomId: document.classroom_id, + classroomDocumentId: document.id, + }, + { + onSuccess: () => { + window.dispatchEvent(new CustomEvent('classroomDocumentUpdated')); + }, }, - }); - }, [deleteDocumentMutation, document.id]); + ); + }, [deleteDocumentMutation, document.classroom_id, document.id]); useEffect(() => { (document.upload_state === uploadState.PENDING && uploadingObject) || diff --git a/src/frontend/packages/lib_classroom/src/components/ClassroomWidgetProvider/widgets/SupportSharing/UploadDocuments/index.spec.tsx b/src/frontend/packages/lib_classroom/src/components/ClassroomWidgetProvider/widgets/SupportSharing/UploadDocuments/index.spec.tsx index 3045f8a952..a9a699464e 100644 --- a/src/frontend/packages/lib_classroom/src/components/ClassroomWidgetProvider/widgets/SupportSharing/UploadDocuments/index.spec.tsx +++ b/src/frontend/packages/lib_classroom/src/components/ClassroomWidgetProvider/widgets/SupportSharing/UploadDocuments/index.spec.tsx @@ -12,7 +12,10 @@ import { Deferred, render } from 'lib-tests'; import React, { PropsWithChildren } from 'react'; import { createClassroomDocument } from '@lib-classroom/data/sideEffects/createClassroomDocument'; -import { classroomDocumentMockFactory } from '@lib-classroom/utils/tests/factories'; +import { + classroomDocumentMockFactory, + classroomMockFactory, +} from '@lib-classroom/utils/tests/factories'; import { UploadDocuments } from '.'; @@ -55,7 +58,7 @@ describe('', () => { it('renders a Dropzone with the relevant messages', () => { fetchMock.mock( - '/api/classroomdocuments/', + '/api/classrooms/1/classroomdocuments/', { upload_max_size_bytes: Math.pow(10, 9), }, @@ -93,7 +96,7 @@ describe('', () => { }); fetchMock.mock( - '/api/classroomdocuments/', + '/api/classrooms/1/classroomdocuments/', { upload_max_size_bytes: Math.pow(10, 9), }, @@ -128,6 +131,7 @@ describe('', () => { modelName.CLASSROOM_DOCUMENTS, classroomDocument.id, file, + '1', ); }); @@ -143,7 +147,7 @@ describe('', () => { }); fetchMock.mock( - '/api/classroomdocuments/', + '/api/classrooms/1/classroomdocuments/', { upload_max_size_bytes: Math.pow(10, 9), }, @@ -191,7 +195,7 @@ describe('', () => { }); fetchMock.mock( - '/api/classroomdocuments/', + '/api/classrooms/1/classroomdocuments/', { upload_max_size_bytes: Math.pow(10, 9), }, @@ -236,7 +240,7 @@ describe('', () => { }); fetchMock.mock( - '/api/classroomdocuments/', + '/api/classrooms/1/classroomdocuments/', { upload_max_size_bytes: Math.pow(10, 9), }, @@ -274,7 +278,9 @@ describe('', () => { }); it('updates classroom documents defaults', async () => { + const classroom = classroomMockFactory(); const classroomDocument = classroomDocumentMockFactory({ + classroom_id: classroom.id, filename: 'file.txt', is_default: false, upload_state: READY, @@ -282,32 +288,39 @@ describe('', () => { url: 'https://example.com/file.txt', }); const classroomDocument2 = classroomDocumentMockFactory({ + classroom_id: classroom.id, filename: 'file2.txt', is_default: true, upload_state: READY, uploaded_on: '2020-01-01T00:00:00Z', url: 'https://example.com/file2.txt', }); - fetchMock.get('/api/classrooms/1/classroomdocuments/?limit=999', { - count: 2, - next: null, - previous: null, - results: [classroomDocument, classroomDocument2], - }); + fetchMock.get( + `/api/classrooms/${classroom.id}/classroomdocuments/?limit=999`, + { + count: 2, + next: null, + previous: null, + results: [classroomDocument, classroomDocument2], + }, + ); fetchMock.mock( - '/api/classroomdocuments/', + `/api/classrooms/${classroom.id}/classroomdocuments/`, { upload_max_size_bytes: Math.pow(10, 9), }, { method: 'OPTIONS' }, ); - fetchMock.patch(`/api/classroomdocuments/${classroomDocument.id}/`, { - status: 200, - }); + fetchMock.patch( + `/api/classrooms/${classroom.id}/classroomdocuments/${classroomDocument.id}/`, + { + status: 200, + }, + ); - render(); + render(); await screen.findByText('file.txt'); const setDefaultButton = screen.getByRole('button', { @@ -331,14 +344,18 @@ describe('', () => { uploaded_on: '2020-01-01T00:00:00Z', url: 'https://example.com/file.txt', }); - fetchMock.get('/api/classrooms/1/classroomdocuments/?limit=999', { - count: 1, - next: null, - previous: null, - results: [classroomDocument], - }); + const classroomId = classroomDocument.classroom_id; + fetchMock.get( + `/api/classrooms/${classroomId}/classroomdocuments/?limit=999`, + { + count: 1, + next: null, + previous: null, + results: [classroomDocument], + }, + ); fetchMock.mock( - '/api/classroomdocuments/', + `/api/classrooms/${classroomId}/classroomdocuments/`, { upload_max_size_bytes: Math.pow(10, 9), }, @@ -351,9 +368,12 @@ describe('', () => { uploadManagerState: {}, }); - fetchMock.delete(`/api/classroomdocuments/${classroomDocument.id}/`, 204); + fetchMock.delete( + `/api/classrooms/${classroomId}/classroomdocuments/${classroomDocument.id}/`, + 204, + ); - render(); + render(); await screen.findByRole('link', { name: 'file.txt' }); @@ -362,12 +382,12 @@ describe('', () => { }); await userEvent.click(deleteButton); - await waitFor(() => expect(fetchMock.calls()).toHaveLength(5)); + await waitFor(() => expect(fetchMock.calls()).toHaveLength(6)); const deleteCall = fetchMock.calls( - `/api/classroomdocuments/${classroomDocument.id}/`, + `/api/classrooms/${classroomId}/classroomdocuments/${classroomDocument.id}/`, ); expect(deleteCall[0][0]).toEqual( - `/api/classroomdocuments/${classroomDocument.id}/`, + `/api/classrooms/${classroomId}/classroomdocuments/${classroomDocument.id}/`, ); expect(deleteCall[0][1]).toEqual({ headers: { @@ -393,7 +413,7 @@ describe('', () => { results: [classroomDocument], }); fetchMock.mock( - '/api/classroomdocuments/', + '/api/classrooms/1/classroomdocuments/', { upload_max_size_bytes: Math.pow(10, 9), }, diff --git a/src/frontend/packages/lib_classroom/src/components/ClassroomWidgetProvider/widgets/SupportSharing/UploadDocuments/index.tsx b/src/frontend/packages/lib_classroom/src/components/ClassroomWidgetProvider/widgets/SupportSharing/UploadDocuments/index.tsx index 0d523b9479..9ed21ad7ea 100644 --- a/src/frontend/packages/lib_classroom/src/components/ClassroomWidgetProvider/widgets/SupportSharing/UploadDocuments/index.tsx +++ b/src/frontend/packages/lib_classroom/src/components/ClassroomWidgetProvider/widgets/SupportSharing/UploadDocuments/index.tsx @@ -80,7 +80,7 @@ export const UploadDocuments = ({ classroomId }: UploadDocumentsProps) => { const intl = useIntl(); const { data: classroomDocuments, refetch: refreshClassroomDocuments } = useClassroomDocuments(classroomId, {}); - const metadata = useClassroomDocumentMetadata(intl.locale); + const metadata = useClassroomDocumentMetadata(classroomId, intl.locale); const { addUpload, uploadManagerState } = useUploadManager(); const [filesToUpload, setFilesToUpload] = useState([]); @@ -125,9 +125,9 @@ export const UploadDocuments = ({ classroomId }: UploadDocumentsProps) => { const document = await createClassroomDocument({ filename: file.name, size: file.size, - classroom: classroomId, + classroom_id: classroomId, }); - addUpload(modelName.CLASSROOM_DOCUMENTS, document.id, file); + addUpload(modelName.CLASSROOM_DOCUMENTS, document.id, file, classroomId); refreshClassroomDocuments(); } catch (error) { if ((error as object).hasOwnProperty('size') && metadata.data) { diff --git a/src/frontend/packages/lib_classroom/src/components/DashboardClassroom/index.spec.tsx b/src/frontend/packages/lib_classroom/src/components/DashboardClassroom/index.spec.tsx index 8a97bda359..e92a1dee3f 100644 --- a/src/frontend/packages/lib_classroom/src/components/DashboardClassroom/index.spec.tsx +++ b/src/frontend/packages/lib_classroom/src/components/DashboardClassroom/index.spec.tsx @@ -90,7 +90,7 @@ describe('', () => { results: [], }); fetchMock.mock( - '/api/classroomdocuments/', + `/api/classrooms/${classroom.id}/classroomdocuments/`, { upload_max_size_bytes: Math.pow(10, 9), }, @@ -126,7 +126,7 @@ describe('', () => { results: [], }); fetchMock.mock( - '/api/classroomdocuments/', + `/api/classrooms/${classroom.id}/classroomdocuments/`, { upload_max_size_bytes: Math.pow(10, 9), }, @@ -293,7 +293,7 @@ describe('', () => { results: [], }); fetchMock.mock( - '/api/classroomdocuments/', + `/api/classrooms/${classroom.id}/classroomdocuments/`, { upload_max_size_bytes: Math.pow(10, 9), }, diff --git a/src/frontend/packages/lib_classroom/src/data/queries/index.spec.tsx b/src/frontend/packages/lib_classroom/src/data/queries/index.spec.tsx index 221446ac24..f94b3bfeef 100644 --- a/src/frontend/packages/lib_classroom/src/data/queries/index.spec.tsx +++ b/src/frontend/packages/lib_classroom/src/data/queries/index.spec.tsx @@ -538,12 +538,16 @@ describe('queries', () => { it('updates the resource', async () => { const classroomDocument = classroomDocumentMockFactory(); fetchMock.patch( - `/api/classroomdocuments/${classroomDocument.id}/`, + `/api/classrooms/${classroomDocument.classroom_id}/classroomdocuments/${classroomDocument.id}/`, classroomDocument, ); const { result } = renderHook( - () => useUpdateClassroomDocument(classroomDocument.id), + () => + useUpdateClassroomDocument( + classroomDocument.classroom_id, + classroomDocument.id, + ), { wrapper: WrapperReactQuery, }, @@ -556,7 +560,7 @@ describe('queries', () => { }); expect(fetchMock.lastCall()![0]).toEqual( - `/api/classroomdocuments/${classroomDocument.id}/`, + `/api/classrooms/${classroomDocument.classroom_id}/classroomdocuments/${classroomDocument.id}/`, ); expect(fetchMock.lastCall()![1]).toEqual({ headers: { @@ -574,10 +578,17 @@ describe('queries', () => { it('fails to update the resource', async () => { const classroomDocument = classroomDocumentMockFactory(); - fetchMock.patch(`/api/classroomdocuments/${classroomDocument.id}/`, 400); + fetchMock.patch( + `/api/classrooms/${classroomDocument.classroom_id}/classroomdocuments/${classroomDocument.id}/`, + 400, + ); const { result } = renderHook( - () => useUpdateClassroomDocument(classroomDocument.id), + () => + useUpdateClassroomDocument( + classroomDocument.classroom_id, + classroomDocument.id, + ), { wrapper: WrapperReactQuery, }, @@ -590,7 +601,7 @@ describe('queries', () => { }); expect(fetchMock.lastCall()![0]).toEqual( - `/api/classroomdocuments/${classroomDocument.id}/`, + `/api/classrooms/${classroomDocument.classroom_id}/classroomdocuments/${classroomDocument.id}/`, ); expect(fetchMock.lastCall()![1]).toEqual({ headers: { diff --git a/src/frontend/packages/lib_classroom/src/data/queries/index.tsx b/src/frontend/packages/lib_classroom/src/data/queries/index.tsx index db63eedca8..10d3e158a2 100644 --- a/src/frontend/packages/lib_classroom/src/data/queries/index.tsx +++ b/src/frontend/packages/lib_classroom/src/data/queries/index.tsx @@ -275,10 +275,12 @@ type UseUpdateClassroomDocumentOptions = UseMutationOptions< UseUpdateClassroomDocumentData >; export const useUpdateClassroomDocument = ( - id: string, + classroomId: Classroom['id'], + id: ClassroomDocument['id'], options?: UseUpdateClassroomDocumentOptions, ) => { const queryClient = useQueryClient(); + const urlPath = `${ClassroomModelName.CLASSROOMS}/${classroomId}/${ClassroomModelName.CLASSROOM_DOCUMENTS}`; return useMutation< ClassroomDocument, UseUpdateClassroomDocumentError, @@ -286,19 +288,19 @@ export const useUpdateClassroomDocument = ( >({ mutationFn: (updatedClassroomDocument) => updateOne({ - name: 'classroomdocuments', + name: urlPath, id, object: updatedClassroomDocument, }), ...options, onSuccess: (data, variables, context) => { - queryClient.invalidateQueries(['classroomdocuments']); + queryClient.invalidateQueries([urlPath]); if (options?.onSuccess) { options.onSuccess(data, variables, context); } }, onError: (error, variables, context) => { - queryClient.invalidateQueries(['classroomdocuments']); + queryClient.invalidateQueries([urlPath]); if (options?.onError) { options.onError(error, variables, context); } @@ -306,7 +308,10 @@ export const useUpdateClassroomDocument = ( }); }; -type UseDeleteClassroomDocumentData = string; +type UseDeleteClassroomDocumentData = { + classroomId: string; + classroomDocumentId: string; +}; type UseDeleteClassroomDocumentError = | { code: 'exception' } | { @@ -327,20 +332,24 @@ export const useDeleteClassroomDocument = ( UseDeleteClassroomDocumentError, UseDeleteClassroomDocumentData >({ - mutationFn: (classroomDocumentId) => + mutationFn: ({ classroomId, classroomDocumentId }) => deleteOne({ - name: 'classroomdocuments', + name: `${ClassroomModelName.CLASSROOMS}/${classroomId}/${ClassroomModelName.CLASSROOM_DOCUMENTS}`, id: classroomDocumentId, }), ...options, onSuccess: (data, variables, context) => { - queryClient.invalidateQueries(['classroomdocuments']); + queryClient.invalidateQueries([ + `${ClassroomModelName.CLASSROOMS}/${variables.classroomId}/${ClassroomModelName.CLASSROOM_DOCUMENTS}`, + ]); if (options?.onSuccess) { options.onSuccess(data, variables, context); } }, onError: (error, variables, context) => { - queryClient.invalidateQueries(['classroomdocuments']); + queryClient.invalidateQueries([ + `${ClassroomModelName.CLASSROOMS}/${variables.classroomId}/${ClassroomModelName.CLASSROOM_DOCUMENTS}`, + ]); if (options?.onError) { options.onError(error, variables, context); } @@ -417,6 +426,7 @@ export const useEndClassroomAction = classroomActionMutation< >(MutationClassroomAction.END); export const useClassroomDocumentMetadata = ( + classroomId: string, locale: string, queryConfig?: UseQueryOptions< ClassroomDocumentMetadata, @@ -425,7 +435,10 @@ export const useClassroomDocumentMetadata = ( string[] >, ) => { - const key = ['classroomdocuments', locale]; + const key = [ + `${ClassroomModelName.CLASSROOMS}/${classroomId}/${ClassroomModelName.CLASSROOM_DOCUMENTS}`, + locale, + ]; return useQuery< ClassroomDocumentMetadata, 'classroomdocuments', diff --git a/src/frontend/packages/lib_classroom/src/data/sideEffects/createClassroomDocument/index.spec.ts b/src/frontend/packages/lib_classroom/src/data/sideEffects/createClassroomDocument/index.spec.ts index fa3e1a1938..945d5cea60 100644 --- a/src/frontend/packages/lib_classroom/src/data/sideEffects/createClassroomDocument/index.spec.ts +++ b/src/frontend/packages/lib_classroom/src/data/sideEffects/createClassroomDocument/index.spec.ts @@ -19,12 +19,15 @@ describe('sideEffects/createClassroomDocument', () => { const classroomDocument = classroomDocumentMockFactory({ filename: file.name, }); - fetchMock.mock('/api/classroomdocuments/', classroomDocument); + fetchMock.mock( + `/api/classrooms/${classroomDocument.classroom_id}/classroomdocuments/`, + classroomDocument, + ); const createdClassroomDocument = await createClassroomDocument({ filename: file.name, size: file.size, - classroom: classroomDocument.classroom_id, + classroom_id: classroomDocument.classroom_id, }); const fetchArgs = fetchMock.lastCall()![1]!; @@ -38,30 +41,33 @@ describe('sideEffects/createClassroomDocument', () => { }); it('throws when it fails to create the deposited file (request failure)', async () => { + const file = new File(['anrusitanrsui tnarsuit narsuit'], 'TestFile.txt'); + const classroomDocument = classroomDocumentMockFactory(); fetchMock.mock( - '/api/classroomdocuments/', + `/api/classrooms/${classroomDocument.classroom_id}/classroomdocuments/`, Promise.reject(new Error('Failed to perform the request')), ); - const file = new File(['anrusitanrsui tnarsuit narsuit'], 'TestFile.txt'); - const classroomDocument = classroomDocumentMockFactory(); await expect( createClassroomDocument({ filename: file.name, size: file.size, - classroom: classroomDocument.classroom_id, + classroom_id: classroomDocument.classroom_id, }), ).rejects.toThrow('Failed to perform the request'); }); it('throws when it fails to create the deposited file (API error)', async () => { - fetchMock.mock('/api/classroomdocuments/', 400); const file = new File(['anrusitanrsui tnarsuit narsuit'], 'TestFile.txt'); const classroomDocument = classroomDocumentMockFactory(); + fetchMock.mock( + `/api/classrooms/${classroomDocument.classroom_id}/classroomdocuments/`, + 400, + ); await expect( createClassroomDocument({ filename: file.name, size: file.size, - classroom: classroomDocument.classroom_id, + classroom_id: classroomDocument.classroom_id, }), ).rejects.toThrow(); }); diff --git a/src/frontend/packages/lib_classroom/src/data/sideEffects/createClassroomDocument/index.ts b/src/frontend/packages/lib_classroom/src/data/sideEffects/createClassroomDocument/index.ts index a0881ee09d..3a2197a3dd 100644 --- a/src/frontend/packages/lib_classroom/src/data/sideEffects/createClassroomDocument/index.ts +++ b/src/frontend/packages/lib_classroom/src/data/sideEffects/createClassroomDocument/index.ts @@ -10,15 +10,17 @@ import { export const createClassroomDocument = async (file: { filename: string; size: number; - classroom: Classroom['id']; + classroom_id: Classroom['id']; }) => { const jwt = useJwt.getState().getJwt(); if (!jwt) { throw new Error('No JWT found'); } + const classroomModelName = ClassroomModelName.CLASSROOMS; + const classroomDocumentsModelName = ClassroomModelName.CLASSROOM_DOCUMENTS; const response = await fetchWrapper( - `${API_ENDPOINT}/${String(ClassroomModelName.CLASSROOM_DOCUMENTS)}/`, + `${API_ENDPOINT}/${classroomModelName}/${file.classroom_id}/${classroomDocumentsModelName}/`, { headers: { Authorization: `Bearer ${jwt}`, diff --git a/src/frontend/packages/lib_classroom/src/utils/tests/factories.ts b/src/frontend/packages/lib_classroom/src/utils/tests/factories.ts index 54067d5c41..0a242393e9 100644 --- a/src/frontend/packages/lib_classroom/src/utils/tests/factories.ts +++ b/src/frontend/packages/lib_classroom/src/utils/tests/factories.ts @@ -80,7 +80,7 @@ export const classroomDocumentMockFactory = ( classroomDocument: Partial = {}, ): ClassroomDocument => { return { - classroom_id: faker.datatype.uuid(), + classroom_id: faker.datatype.uuid().toString(), filename: faker.system.fileName(), id: faker.datatype.uuid(), is_default: false,