From d115976d85fc808633d79fb24487d0d57c314d6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20D=C4=9Bdi=C4=8D?= Date: Wed, 18 Dec 2024 23:05:12 +0100 Subject: [PATCH 1/9] Updated to Drive API v3 --- src/appsscript.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/appsscript.json b/src/appsscript.json index c367c0ed..e1702b62 100644 --- a/src/appsscript.json +++ b/src/appsscript.json @@ -5,7 +5,7 @@ "enabledAdvancedServices": [{ "userSymbol": "Drive", "serviceId": "drive", - "version": "v2" + "version": "v3" }] }, "webapp": { From 954babae32bf910ba316a1d4a786952c1a06caa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20D=C4=9Bdi=C4=8D?= Date: Thu, 19 Dec 2024 16:40:21 +0100 Subject: [PATCH 2/9] Updated backend to use v3 APIs --- src/backend/Drive-shim.d.ts | 2 - src/backend/listFolders.ts | 12 +- src/backend/listSharedDrives.ts | 2 +- src/backend/move/copyFileComments.ts | 15 +- src/backend/move/folderManagement.ts | 15 +- src/backend/move/moveFile.ts | 9 +- src/backend/move/moveFolder.ts | 2 +- src/backend/move/resolveDestinationFolder.ts | 10 +- src/backend/utils/DriveBackedValue.ts | 28 ++-- src/backend/utils/SafeDriveService.ts | 5 +- .../SafeCommentsCollection.ts | 40 +++-- .../SafeDriveService/SafeDrivesCollection.ts | 23 ++- .../SafeDriveService/SafeFilesCollection.ts | 87 +++++----- tests/backend/listFolders.test.ts | 4 +- .../test-utils/SafeDriveService-stub.ts | 8 +- tests/backend/test-utils/gas-stubs.ts | 153 +++++++++--------- 16 files changed, 197 insertions(+), 218 deletions(-) delete mode 100644 src/backend/Drive-shim.d.ts diff --git a/src/backend/Drive-shim.d.ts b/src/backend/Drive-shim.d.ts deleted file mode 100644 index 437afbb9..00000000 --- a/src/backend/Drive-shim.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -// eslint-disable-next-line no-var -- GAS global, needs var -declare var Drive: GoogleAppsScript.Drive_v2; diff --git a/src/backend/listFolders.ts b/src/backend/listFolders.ts index a2c5da50..a7a465ed 100644 --- a/src/backend/listFolders.ts +++ b/src/backend/listFolders.ts @@ -15,8 +15,8 @@ export function listFolders(parentID: google.script.Parameter): ListResponse { SafeFileList<{ id: true; mimeType: true; + name: true; shortcutDetails: { targetId: true }; - title: true; }>, NamedRecord >( @@ -25,8 +25,8 @@ export function listFolders(parentID: google.script.Parameter): ListResponse { { id: true, mimeType: true, + name: true, shortcutDetails: { targetId: true }, - title: true, }, { includeItemsFromAllDrives: true, @@ -37,10 +37,10 @@ export function listFolders(parentID: google.script.Parameter): ListResponse { }, ), (listResponse) => - listResponse.items + listResponse.files .sort((first, second) => - first.title.localeCompare( - second.title, + first.name.localeCompare( + second.name, Session.getActiveUserLocale(), ), ) @@ -49,7 +49,7 @@ export function listFolders(parentID: google.script.Parameter): ListResponse { item.mimeType === "application/vnd.google-apps.shortcut" ? (item.shortcutDetails?.targetId ?? item.id) : item.id; - return { id, name: item.title }; + return { id, name: item.name }; }), ); return { diff --git a/src/backend/listSharedDrives.ts b/src/backend/listSharedDrives.ts index af4de46c..b0c04d71 100644 --- a/src/backend/listSharedDrives.ts +++ b/src/backend/listSharedDrives.ts @@ -25,7 +25,7 @@ export function listSharedDrives(): ListResponse { }, ), (listResponse) => - listResponse.items.map((item) => ({ id: item.id, name: item.name })), + listResponse.drives.map((item) => ({ id: item.id, name: item.name })), ); return { response, diff --git a/src/backend/move/copyFileComments.ts b/src/backend/move/copyFileComments.ts index e0628a39..e709cd98 100644 --- a/src/backend/move/copyFileComments.ts +++ b/src/backend/move/copyFileComments.ts @@ -13,20 +13,17 @@ export function copyFileComments_( ): void { const comments = listFileComments_(sourceID, driveService); for (const comment of comments) { - if (!comment.author.isAuthenticatedUser) { + if (!comment.author.me) { comment.content = `*${comment.author.displayName}:*\n${comment.content}`; } const replies = comment.replies; comment.replies = []; - const commentId = driveService.Comments.insert( - comment, - destinationID, - ).commentId; + const commentId = driveService.Comments.create(comment, destinationID).id; for (const reply of replies) { - if (!reply.author.isAuthenticatedUser) { + if (!reply.author.me) { reply.content = `*${reply.author.displayName}:*\n${reply.content}`; } - driveService.Replies.insert(reply, destinationID, commentId); + driveService.Replies.create(reply, destinationID, commentId); } } } @@ -39,10 +36,10 @@ function listFileComments_( (pageToken) => driveService.Comments.list(fileID, { fields: - "nextPageToken, items(author(isAuthenticatedUser, displayName), content, status, context, anchor, replies(author(isAuthenticatedUser, displayName), content, verb))", + "nextPageToken, comments(author(me, displayName), content, resolved, quotedFileContent, anchor, replies(author(me, displayName), content, action))", maxResults: 100, pageToken, }), - (response) => response.items, + (response) => response.comments, ); } diff --git a/src/backend/move/folderManagement.ts b/src/backend/move/folderManagement.ts index ad553def..6161d72e 100644 --- a/src/backend/move/folderManagement.ts +++ b/src/backend/move/folderManagement.ts @@ -10,7 +10,7 @@ import { paginationHelper_ } from "../utils/paginationHelper"; export interface ListFolderContentsFields { capabilities: { canMoveItemOutOfDrive: true }; id: true; - title: true; + name: true; } export function deleteFolderIfEmpty_( @@ -21,12 +21,9 @@ export function deleteFolderIfEmpty_( return; } const response = driveService.Files.get(folderID, { - userPermission: { role: true }, + capabilities: { canDelete: true }, }); - if ( - response.userPermission.role === "owner" || - response.userPermission.role === "organizer" - ) { + if (response.capabilities.canDelete) { driveService.Files.remove(folderID); } } @@ -44,7 +41,7 @@ export function isFolderEmpty_( supportsAllDrives: true, }, ); - return response.items.length === 0; + return response.files.length === 0; } export function listFilesInFolder_( @@ -83,7 +80,7 @@ function listFolderContents_( { capabilities: { canMoveItemOutOfDrive: true }, id: true, - title: true, + name: true, }, { includeItemsFromAllDrives: true, @@ -93,6 +90,6 @@ function listFolderContents_( supportsAllDrives: true, }, ), - (response) => response.items, + (response) => response.files, ); } diff --git a/src/backend/move/moveFile.ts b/src/backend/move/moveFile.ts index fe8918b2..3c81c7b9 100644 --- a/src/backend/move/moveFile.ts +++ b/src/backend/move/moveFile.ts @@ -21,7 +21,7 @@ export function moveFile_( } moveFileByCopy_( file.id, - file.title, + file.name, state, context, copyComments, @@ -42,8 +42,8 @@ function moveFileByCopy_( () => { const copy = driveService.Files.copy( { - parents: [{ id: context.destinationID }], - title: name, + name, + parents: [context.destinationID], }, fileID, { id: true }, @@ -62,9 +62,8 @@ function moveFileDirectly_( context: MoveContext, driveService: SafeDriveService_, ): void { - driveService.Files.update({}, fileID, null, { + driveService.Files.update({}, fileID, {}, undefined, { addParents: context.destinationID, - fields: "", removeParents: context.sourceID, supportsAllDrives: true, }); diff --git a/src/backend/move/moveFolder.ts b/src/backend/move/moveFolder.ts index 33a3cca1..776befd4 100644 --- a/src/backend/move/moveFolder.ts +++ b/src/backend/move/moveFolder.ts @@ -29,7 +29,7 @@ export function moveFolder_( state.addPath( folder.id, destinationFolder.id, - context.path.concat([folder.title]), + context.path.concat([folder.name]), ); } } diff --git a/src/backend/move/resolveDestinationFolder.ts b/src/backend/move/resolveDestinationFolder.ts index e7a9f45c..963c8149 100644 --- a/src/backend/move/resolveDestinationFolder.ts +++ b/src/backend/move/resolveDestinationFolder.ts @@ -19,22 +19,22 @@ export function resolveDestinationFolder_( const existingFoldersWithSameName = listFoldersInFolder_( context.destinationID, driveService, - ).filter((folder) => folder.title === sourceFolder.title); + ).filter((folder) => folder.name === sourceFolder.name); if (existingFoldersWithSameName.length === 1) { return existingFoldersWithSameName[0]; } if (existingFoldersWithSameName.length > 1) { state.logError( - context.path.concat([sourceFolder.title]), + context.path.concat([sourceFolder.name]), "Coudn't merge with existing folder as there are multiple existing directories with the same name", ); } } - return driveService.Files.insert( + return driveService.Files.create( { mimeType: "application/vnd.google-apps.folder", - parents: [{ id: context.destinationID }], - title: sourceFolder.title, + name: sourceFolder.name, + parents: [context.destinationID], }, { id: true }, undefined, diff --git a/src/backend/utils/DriveBackedValue.ts b/src/backend/utils/DriveBackedValue.ts index fc63cade..50b03077 100644 --- a/src/backend/utils/DriveBackedValue.ts +++ b/src/backend/utils/DriveBackedValue.ts @@ -50,10 +50,10 @@ export class DriveBackedValue_ { } private createDriveFolder(): string { - const response = this.driveService.Files.insert( + const response = this.driveService.Files.create( { mimeType: "application/vnd.google-apps.folder", - title: DriveBackedValue_.driveFolderName, + name: DriveBackedValue_.driveFolderName, }, { id: true, @@ -85,14 +85,14 @@ export class DriveBackedValue_ { { id: true }, { maxResults: 1, - q: `title = "${this.getFileName()}" and "${folderId}" in parents and trashed = false`, + q: `name = "${this.getFileName()}" and "${folderId}" in parents and trashed = false`, }, ); if ( - response.items.length === 1 && - typeof response.items[0].id === "string" + response.files.length === 1 && + typeof response.files[0].id === "string" ) { - return response.items[0].id; + return response.files[0].id; } return null; } @@ -102,14 +102,14 @@ export class DriveBackedValue_ { { id: true }, { maxResults: 1, - q: `title = "${DriveBackedValue_.driveFolderName}" and "root" in parents and mimeType = "application/vnd.google-apps.folder" and trashed = false`, + q: `name = "${DriveBackedValue_.driveFolderName}" and "root" in parents and mimeType = "application/vnd.google-apps.folder" and trashed = false`, }, ); if ( - response.items.length === 1 && - typeof response.items[0].id === "string" + response.files.length === 1 && + typeof response.files[0].id === "string" ) { - return response.items[0].id; + return response.files[0].id; } return null; } @@ -126,15 +126,15 @@ export class DriveBackedValue_ { q: `"${folderId}" in parents and trashed = false`, }, ); - return response.items.length === 0; + return response.files.length === 0; } private saveAsNewDriveFile(folderId: string, value: T): void { - this.driveService.Files.insert( + this.driveService.Files.create( { mimeType: "application/json", - parents: [{ id: folderId }], - title: this.getFileName(), + name: this.getFileName(), + parents: [folderId], }, {}, Utilities.newBlob(JSON.stringify(value), "application/json"), diff --git a/src/backend/utils/SafeDriveService.ts b/src/backend/utils/SafeDriveService.ts index 1449cb45..90173ebd 100644 --- a/src/backend/utils/SafeDriveService.ts +++ b/src/backend/utils/SafeDriveService.ts @@ -19,12 +19,9 @@ export class SafeDriveService_ { public readonly Comments: SafeCommentsCollection_; public readonly Drives: SafeDrivesCollection_; public readonly Files: SafeFilesCollection_; - public readonly Replies: GoogleAppsScript.Drive.Collection.RepliesCollection; + public readonly Replies: GoogleAppsScript.Drive_v3.Drive.V3.Collection.RepliesCollection; public constructor() { - if (Drive.Replies === undefined) { - throw new Error(); - } this.Comments = new SafeCommentsCollection_(); this.Drives = new SafeDrivesCollection_(); this.Files = new SafeFilesCollection_(); diff --git a/src/backend/utils/SafeDriveService/SafeCommentsCollection.ts b/src/backend/utils/SafeDriveService/SafeCommentsCollection.ts index 090828d1..ec250ff7 100644 --- a/src/backend/utils/SafeDriveService/SafeCommentsCollection.ts +++ b/src/backend/utils/SafeDriveService/SafeCommentsCollection.ts @@ -1,42 +1,40 @@ export interface SafeComment { author: SafeUser; - commentId: string; content: string; - replies: Array; + id: string; + replies: Array; } export interface SafeCommentList { - items: Array; + comments: Array; nextPageToken?: string | undefined; } -interface SafeCommentReply { +interface SafeReply { author: SafeUser; content: string; } interface SafeUser { displayName: string; - isAuthenticatedUser: boolean; + me: boolean; } export class SafeCommentsCollection_ { - private readonly unsafeComments: GoogleAppsScript.Drive.Collection.CommentsCollection; + private readonly unsafeComments: GoogleAppsScript.Drive_v3.Drive.V3.Collection.CommentsCollection; public constructor() { - if (Drive.Comments === undefined) { - throw new Error(); - } + // TODO: Remove and access directly this.unsafeComments = Drive.Comments; } private static commentIsSafe( - comment: GoogleAppsScript.Drive.Schema.Comment, + comment: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Comment, ): comment is SafeComment { return ( comment.author !== undefined && SafeCommentsCollection_.userIsSafe(comment.author) && - comment.commentId !== undefined && + comment.id !== undefined && comment.content !== undefined && comment.replies?.every((reply) => SafeCommentsCollection_.commentReplyIsSafe(reply), @@ -45,18 +43,18 @@ export class SafeCommentsCollection_ { } private static commentListIsSafe( - commentList: GoogleAppsScript.Drive.Schema.CommentList, + commentList: GoogleAppsScript.Drive_v3.Drive.V3.Schema.CommentList, ): commentList is SafeCommentList { return ( - commentList.items?.every((comment) => + commentList.comments?.every((comment) => SafeCommentsCollection_.commentIsSafe(comment), ) === true ); } private static commentReplyIsSafe( - commentReply: GoogleAppsScript.Drive.Schema.CommentReply, - ): commentReply is SafeCommentReply { + commentReply: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Reply, + ): commentReply is SafeReply { return ( commentReply.author !== undefined && SafeCommentsCollection_.userIsSafe(commentReply.author) && @@ -65,18 +63,16 @@ export class SafeCommentsCollection_ { } private static userIsSafe( - user: GoogleAppsScript.Drive.Schema.User, + user: GoogleAppsScript.Drive_v3.Drive.V3.Schema.User, ): user is SafeUser { - return ( - user.isAuthenticatedUser !== undefined && user.displayName !== undefined - ); + return user.me !== undefined && user.displayName !== undefined; } - public insert( - resource: GoogleAppsScript.Drive.Schema.Comment, + public create( + resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Comment, fileId: string, ): SafeComment { - const ret = this.unsafeComments.insert(resource, fileId); + const ret = this.unsafeComments.create(resource, fileId); if (!SafeCommentsCollection_.commentIsSafe(ret)) { throw new Error(""); } diff --git a/src/backend/utils/SafeDriveService/SafeDrivesCollection.ts b/src/backend/utils/SafeDriveService/SafeDrivesCollection.ts index 89cd8447..f51ea5ef 100644 --- a/src/backend/utils/SafeDriveService/SafeDrivesCollection.ts +++ b/src/backend/utils/SafeDriveService/SafeDrivesCollection.ts @@ -9,7 +9,7 @@ export interface SafeDrive { } export interface SafeDriveList> { - items: Array>; + drives: Array>; nextPageToken?: string; } @@ -19,17 +19,15 @@ const safeDriveKeys: DeepKeyof = { }; export class SafeDrivesCollection_ { - private readonly unsafeDrives: GoogleAppsScript.Drive.Collection.DrivesCollection; + private readonly unsafeDrives: GoogleAppsScript.Drive_v3.Drive.V3.Collection.DrivesCollection; public constructor() { - if (Drive.Drives === undefined) { - throw new Error(); - } + // TODO: Remove and access directly this.unsafeDrives = Drive.Drives; } private static driveIsSafe>( - drive: GoogleAppsScript.Drive.Schema.Drive, + drive: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Drive, keys: F | null, ): drive is typeof keys extends null ? SafeDrive : DeepPick { if (keys === null) { @@ -47,14 +45,13 @@ export class SafeDrivesCollection_ { } private static driveListIsSafe>( - driveList: GoogleAppsScript.Drive.Schema.DriveList, + driveList: GoogleAppsScript.Drive_v3.Drive.V3.Schema.DriveList, keys: F | null, ): driveList is SafeDriveList { - if (driveList.items === undefined) { - return false; - } - return driveList.items.every((file) => - SafeDrivesCollection_.driveIsSafe(file, keys), + return ( + driveList.drives?.every((file) => + SafeDrivesCollection_.driveIsSafe(file, keys), + ) === true ); } @@ -69,7 +66,7 @@ export class SafeDrivesCollection_ { const ret = this.unsafeDrives.list({ ...optionalArgs, ...(fields !== null && { - fields: `nextPageToken, items(${stringifyFields_(fields)})`, + fields: `nextPageToken, drives(${stringifyFields_(fields)})`, }), }); if (!SafeDrivesCollection_.driveListIsSafe(ret, fields)) { diff --git a/src/backend/utils/SafeDriveService/SafeFilesCollection.ts b/src/backend/utils/SafeDriveService/SafeFilesCollection.ts index 532d5e52..f106ea4e 100644 --- a/src/backend/utils/SafeDriveService/SafeFilesCollection.ts +++ b/src/backend/utils/SafeDriveService/SafeFilesCollection.ts @@ -5,6 +5,7 @@ import { stringifyFields_ } from "./stringifyFields"; export interface SafeFile { capabilities: { + canDelete: boolean; canMoveItemOutOfDrive: boolean; }; id: string; @@ -12,19 +13,17 @@ export interface SafeFile { aperture: number; }; mimeType: string; + name: string; shortcutDetails?: { targetId: string; }; - title: string; - userPermission: { - role: "fileOrganizer" | "organizer" | "owner" | "reader" | "writer"; - }; } const safeFileOptionalKeys = ["imageMediaMetadata", "shortcutDetails"]; const safeFileKeys: DeepKeyof = { capabilities: { + canDelete: true, canMoveItemOutOfDrive: true, }, id: true, @@ -32,17 +31,14 @@ const safeFileKeys: DeepKeyof = { aperture: true, }, mimeType: true, + name: true, shortcutDetails: { targetId: true, }, - title: true, - userPermission: { - role: true, - }, }; export interface SafeFileList> { - items: Array>; + files: Array>; nextPageToken?: string | undefined; } interface GetArg { @@ -56,17 +52,15 @@ type GetReturn, A extends GetArg> = A extends { : DeepPick; export class SafeFilesCollection_ { - private readonly unsafeFiles: GoogleAppsScript.Drive.Collection.FilesCollection; + private readonly unsafeFiles: GoogleAppsScript.Drive_v3.Drive.V3.Collection.FilesCollection; public constructor() { - if (Drive.Files === undefined) { - throw new Error(); - } + // TODO: Remove and access directly this.unsafeFiles = Drive.Files; } private static fileIsSafe>( - file: GoogleAppsScript.Drive.Schema.File, + file: GoogleAppsScript.Drive_v3.Drive.V3.Schema.File, keys: F | null, ): file is typeof keys extends null ? SafeFile : DeepPick { if (keys === null) { @@ -99,19 +93,18 @@ export class SafeFilesCollection_ { } private static fileListIsSafe>( - fileList: GoogleAppsScript.Drive.Schema.FileList, + fileList: GoogleAppsScript.Drive_v3.Drive.V3.Schema.FileList, keys: F | null, ): fileList is SafeFileList { - if (fileList.items === undefined) { - return false; - } - return fileList.items.every((file) => - SafeFilesCollection_.fileIsSafe(file, keys), + return ( + fileList.files?.every((file) => + SafeFilesCollection_.fileIsSafe(file, keys), + ) === true ); } public copy>( - resource: GoogleAppsScript.Drive.Schema.File, + resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.File, fileId: string, fields: F | null, optionalArgs: { @@ -130,45 +123,45 @@ export class SafeFilesCollection_ { return ret; } - public get, A extends GetArg>( - fileId: string, + public create>( + resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.File, fields: F | null, - optionalArgs: A = {} as A, - ): GetReturn { - const ret = this.unsafeFiles.get(fileId, { + mediaData?: GoogleAppsScript.Base.Blob, + optionalArgs: { + supportsAllDrives?: boolean; + } = {}, + ): DeepPick { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- Due to strange optional arguments on upstream types + const ret = this.unsafeFiles.create(resource, mediaData!, { ...optionalArgs, ...(fields !== null && { fields: stringifyFields_(fields), }), }); - if ( - typeof ret !== "string" && - !SafeFilesCollection_.fileIsSafe(ret, fields) - ) { + if (!SafeFilesCollection_.fileIsSafe(ret, fields)) { throw new Error(""); } - return ret as unknown as GetReturn; + return ret; } - public insert>( - resource: GoogleAppsScript.Drive.Schema.File, + public get, A extends GetArg>( + fileId: string, fields: F | null, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- Required by the Drive API - mediaData?: any, - optionalArgs: { - supportsAllDrives?: boolean; - } = {}, - ): DeepPick { - const ret = this.unsafeFiles.insert(resource, mediaData, { + optionalArgs: A = {} as A, + ): GetReturn { + const ret = this.unsafeFiles.get(fileId, { ...optionalArgs, ...(fields !== null && { fields: stringifyFields_(fields), }), }); - if (!SafeFilesCollection_.fileIsSafe(ret, fields)) { + if ( + typeof ret !== "string" && + !SafeFilesCollection_.fileIsSafe(ret, fields) + ) { throw new Error(""); } - return ret; + return ret as unknown as GetReturn; } public list>( @@ -184,7 +177,7 @@ export class SafeFilesCollection_ { const ret = this.unsafeFiles.list({ ...optionalArgs, ...(fields !== null && { - fields: `nextPageToken, items(${stringifyFields_(fields)})`, + fields: `nextPageToken, files(${stringifyFields_(fields)})`, }), }); if (!SafeFilesCollection_.fileListIsSafe(ret, fields)) { @@ -198,18 +191,18 @@ export class SafeFilesCollection_ { } public update>( - resource: GoogleAppsScript.Drive.Schema.File, + resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.File, fileId: string, fields: F | null, - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any -- Required by the Drive API - mediaData?: any, + mediaData?: GoogleAppsScript.Base.Blob, optionalArgs: { addParents?: string; removeParents?: string; supportsAllDrives?: boolean; } = {}, ): DeepPick { - const ret = this.unsafeFiles.update(resource, fileId, mediaData, { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- Strange behaviour with optional arguments + const ret = this.unsafeFiles.update(resource, fileId, mediaData!, { ...optionalArgs, ...(fields !== null && { fields: stringifyFields_(fields), diff --git a/tests/backend/listFolders.test.ts b/tests/backend/listFolders.test.ts index 003ad634..d8b2bd33 100644 --- a/tests/backend/listFolders.test.ts +++ b/tests/backend/listFolders.test.ts @@ -17,7 +17,7 @@ test("listFolders works correctly", () => { } const rawResponse = { - items: [ + files: [ { id: "ID1", title: "FOLDER1" }, { id: "ID2", title: "FOLDER2" }, ], @@ -75,7 +75,7 @@ test("listFolders works correctly with shortcuts", () => { } const rawResponse = { - items: [ + files: [ { id: "ID1", mimeType: "application/vnd.google-apps.shortcut", diff --git a/tests/backend/test-utils/SafeDriveService-stub.ts b/tests/backend/test-utils/SafeDriveService-stub.ts index 522d5873..b5d8df0d 100644 --- a/tests/backend/test-utils/SafeDriveService-stub.ts +++ b/tests/backend/test-utils/SafeDriveService-stub.ts @@ -23,7 +23,7 @@ export function mockedSafeDriveService< insert: vi.fn< ( - resource: GoogleAppsScript.Drive.Schema.Comment, + resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Comment, fileId: string, ) => SafeComment >(), @@ -46,7 +46,7 @@ export function mockedSafeDriveService< Files: { copy: vi.fn< ( - resource: GoogleAppsScript.Drive.Schema.File, + resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.File, fileId: string, fields: F | null, optionalArgs?: { supportsAllDrives?: boolean }, @@ -61,7 +61,7 @@ export function mockedSafeDriveService< >(), insert: vi.fn< ( - resource: GoogleAppsScript.Drive.Schema.File, + resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.File, fields: F | null, // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Required by the Drive API mediaData?: any, @@ -85,7 +85,7 @@ export function mockedSafeDriveService< remove: vi.fn<(fileId: string) => void>(), update: vi.fn< ( - resource: GoogleAppsScript.Drive.Schema.File, + resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.File, fileId: string, fields: F | null, // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Required by the Drive API diff --git a/tests/backend/test-utils/gas-stubs.ts b/tests/backend/test-utils/gas-stubs.ts index d89fabce..8e5965f0 100644 --- a/tests/backend/test-utils/gas-stubs.ts +++ b/tests/backend/test-utils/gas-stubs.ts @@ -1,133 +1,138 @@ import { vi } from "vitest"; -export function mockedCommentsCollection(): GoogleAppsScript.Drive.Collection.CommentsCollection { +export function mockedCommentsCollection(): GoogleAppsScript.Drive_v3.Drive.V3.Collection.CommentsCollection { return { get: vi.fn< ( fileId: string, commentId: string, - ) => GoogleAppsScript.Drive.Schema.Comment + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Comment >(), insert: vi.fn< ( - resource: GoogleAppsScript.Drive.Schema.Comment, + resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Comment, fileId: string, - ) => GoogleAppsScript.Drive.Schema.Comment + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Comment >(), list: vi.fn< - (fileId: string) => GoogleAppsScript.Drive.Schema.CommentList + (fileId: string) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.CommentList >(), patch: vi.fn< ( - resource: GoogleAppsScript.Drive.Schema.Comment, + resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Comment, fileId: string, commentId: string, - ) => GoogleAppsScript.Drive.Schema.Comment + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Comment >(), remove: vi.fn<(fileId: string, commentId: string) => void>(), update: vi.fn< ( - resource: GoogleAppsScript.Drive.Schema.Comment, + resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Comment, fileId: string, commentId: string, - ) => GoogleAppsScript.Drive.Schema.Comment + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Comment >(), }; } -export function mockedDrive(): GoogleAppsScript.Drive_v2 { +export function mockedDrive(): GoogleAppsScript.Drive { return { - newChannel: vi.fn<() => GoogleAppsScript.Drive.Schema.Channel>(), + newChannel: vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Channel>(), newChildReference: - vi.fn<() => GoogleAppsScript.Drive.Schema.ChildReference>(), - newComment: vi.fn<() => GoogleAppsScript.Drive.Schema.Comment>(), + vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.ChildReference>(), + newComment: vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Comment>(), newCommentContext: - vi.fn<() => GoogleAppsScript.Drive.Schema.CommentContext>(), - newCommentReply: vi.fn<() => GoogleAppsScript.Drive.Schema.CommentReply>(), - newDrive: vi.fn<() => GoogleAppsScript.Drive.Schema.Drive>(), + vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.CommentContext>(), + newCommentReply: + vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.CommentReply>(), + newDrive: vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Drive>(), newDriveBackgroundImageFile: - vi.fn<() => GoogleAppsScript.Drive.Schema.DriveBackgroundImageFile>(), + vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.DriveBackgroundImageFile>(), newDriveCapabilities: - vi.fn<() => GoogleAppsScript.Drive.Schema.DriveCapabilities>(), + vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.DriveCapabilities>(), newDriveRestrictions: - vi.fn<() => GoogleAppsScript.Drive.Schema.DriveRestrictions>(), - newFile: vi.fn<() => GoogleAppsScript.Drive.Schema.File>(), + vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.DriveRestrictions>(), + newFile: vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.File>(), newFileCapabilities: - vi.fn<() => GoogleAppsScript.Drive.Schema.FileCapabilities>(), + vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.FileCapabilities>(), newFileImageMediaMetadata: - vi.fn<() => GoogleAppsScript.Drive.Schema.FileImageMediaMetadata>(), + vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.FileImageMediaMetadata>(), newFileImageMediaMetadataLocation: vi.fn< - () => GoogleAppsScript.Drive.Schema.FileImageMediaMetadataLocation + () => GoogleAppsScript.Drive_v3.Drive.V3.Schema.FileImageMediaMetadataLocation >(), newFileIndexableText: - vi.fn<() => GoogleAppsScript.Drive.Schema.FileIndexableText>(), - newFileLabels: vi.fn<() => GoogleAppsScript.Drive.Schema.FileLabels>(), + vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.FileIndexableText>(), + newFileLabels: vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.FileLabels>(), newFileThumbnail: - vi.fn<() => GoogleAppsScript.Drive.Schema.FileThumbnail>(), + vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.FileThumbnail>(), newFileVideoMediaMetadata: - vi.fn<() => GoogleAppsScript.Drive.Schema.FileVideoMediaMetadata>(), + vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.FileVideoMediaMetadata>(), newParentReference: - vi.fn<() => GoogleAppsScript.Drive.Schema.ParentReference>(), - newPermission: vi.fn<() => GoogleAppsScript.Drive.Schema.Permission>(), + vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.ParentReference>(), + newPermission: vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Permission>(), newPermissionPermissionDetails: - vi.fn<() => GoogleAppsScript.Drive.Schema.PermissionPermissionDetails>(), + vi.fn< + () => GoogleAppsScript.Drive_v3.Drive.V3.Schema.PermissionPermissionDetails + >(), newPermissionTeamDrivePermissionDetails: vi.fn< - () => GoogleAppsScript.Drive.Schema.PermissionTeamDrivePermissionDetails + () => GoogleAppsScript.Drive_v3.Drive.V3.Schema.PermissionTeamDrivePermissionDetails >(), - newProperty: vi.fn<() => GoogleAppsScript.Drive.Schema.Property>(), - newRevision: vi.fn<() => GoogleAppsScript.Drive.Schema.Revision>(), - newTeamDrive: vi.fn<() => GoogleAppsScript.Drive.Schema.TeamDrive>(), + newProperty: vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Property>(), + newRevision: vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Revision>(), + newTeamDrive: vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.TeamDrive>(), newTeamDriveBackgroundImageFile: - vi.fn<() => GoogleAppsScript.Drive.Schema.TeamDriveBackgroundImageFile>(), + vi.fn< + () => GoogleAppsScript.Drive_v3.Drive.V3.Schema.TeamDriveBackgroundImageFile + >(), newTeamDriveCapabilities: - vi.fn<() => GoogleAppsScript.Drive.Schema.TeamDriveCapabilities>(), + vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.TeamDriveCapabilities>(), newTeamDriveRestrictions: - vi.fn<() => GoogleAppsScript.Drive.Schema.TeamDriveRestrictions>(), - newUser: vi.fn<() => GoogleAppsScript.Drive.Schema.User>(), - newUserPicture: vi.fn<() => GoogleAppsScript.Drive.Schema.UserPicture>(), + vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.TeamDriveRestrictions>(), + newUser: vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.User>(), + newUserPicture: vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.UserPicture>(), }; } -export function mockedDrivesCollection(): GoogleAppsScript.Drive.Collection.DrivesCollection { +export function mockedDrivesCollection(): GoogleAppsScript.Drive_v3.Drive.V3.Collection.DrivesCollection { return { - get: vi.fn<(driveId: string) => GoogleAppsScript.Drive.Schema.Drive>(), - hide: vi.fn<(driveId: string) => GoogleAppsScript.Drive.Schema.Drive>(), + get: vi.fn<(driveId: string) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Drive>(), + hide: vi.fn<(driveId: string) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Drive>(), insert: vi.fn< ( - resource: GoogleAppsScript.Drive.Schema.Drive, + resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Drive, requestId: string, - ) => GoogleAppsScript.Drive.Schema.Drive + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Drive >(), - list: vi.fn<() => GoogleAppsScript.Drive.Schema.DriveList>(), + list: vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.DriveList>(), remove: vi.fn<(driveId: string) => void>(), - unhide: vi.fn<(driveId: string) => GoogleAppsScript.Drive.Schema.Drive>(), + unhide: vi.fn<(driveId: string) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Drive>(), update: vi.fn< ( - resource: GoogleAppsScript.Drive.Schema.Drive, + resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Drive, driveId: string, - ) => GoogleAppsScript.Drive.Schema.Drive + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Drive >(), }; } -export function mockedFilesCollection(): GoogleAppsScript.Drive.Collection.FilesCollection { +export function mockedFilesCollection(): GoogleAppsScript.Drive_v3.Drive.V3.Collection.FilesCollection { return { copy: vi.fn< ( - resource: GoogleAppsScript.Drive.Schema.File, + resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.File, fileId: string, - ) => GoogleAppsScript.Drive.Schema.File + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.File >(), emptyTrash: vi.fn<() => void>(), export: vi.fn<(fileId: string, mimeType: string) => void>(), - generateIds: vi.fn<() => GoogleAppsScript.Drive.Schema.GeneratedIds>(), + generateIds: vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.GeneratedIds>(), get: vi.fn() as { ( fileId: string, @@ -138,41 +143,41 @@ export function mockedFilesCollection(): GoogleAppsScript.Drive.Collection.Files fileId: string, // eslint-disable-next-line @typescript-eslint/no-explicit-any -- From upstream types optionalArgs?: Record, - ): GoogleAppsScript.Drive.Schema.File; + ): GoogleAppsScript.Drive_v3.Drive.V3.Schema.File; }, insert: vi.fn< ( - resource: GoogleAppsScript.Drive.Schema.File, + resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.File, mediaData?: Blob, - ) => GoogleAppsScript.Drive.Schema.File + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.File >(), - list: vi.fn<() => GoogleAppsScript.Drive.Schema.FileList>(), + list: vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.FileList>(), patch: vi.fn< ( - resource: GoogleAppsScript.Drive.Schema.File, + resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.File, fileId: string, - ) => GoogleAppsScript.Drive.Schema.File + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.File >(), remove: vi.fn<(fileId: string) => void>(), - touch: vi.fn<(fileId: string) => GoogleAppsScript.Drive.Schema.File>(), - trash: vi.fn<(fileId: string) => GoogleAppsScript.Drive.Schema.File>(), - untrash: vi.fn<(fileId: string) => GoogleAppsScript.Drive.Schema.File>(), + touch: vi.fn<(fileId: string) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.File>(), + trash: vi.fn<(fileId: string) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.File>(), + untrash: vi.fn<(fileId: string) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.File>(), update: vi.fn< ( - resource: GoogleAppsScript.Drive.Schema.File, + resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.File, fileId: string, mediaData?: Blob, - ) => GoogleAppsScript.Drive.Schema.File + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.File >(), watch: vi.fn< ( - resource: GoogleAppsScript.Drive.Schema.Channel, + resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Channel, fileId: string, - ) => GoogleAppsScript.Drive.Schema.Channel + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Channel >(), }; } @@ -251,48 +256,48 @@ export function mockedHtmlTemplate(): GoogleAppsScript.HTML.HtmlTemplate { }; } -export function mockedRepliesCollection(): GoogleAppsScript.Drive.Collection.RepliesCollection { +export function mockedRepliesCollection(): GoogleAppsScript.Drive_v3.Drive.V3.Collection.RepliesCollection { return { get: vi.fn< ( fileId: string, commentId: string, replyId: string, - ) => GoogleAppsScript.Drive.Schema.CommentReply + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.CommentReply >(), insert: vi.fn< ( - resource: GoogleAppsScript.Drive.Schema.CommentReply, + resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.CommentReply, fileId: string, commentId: string, - ) => GoogleAppsScript.Drive.Schema.CommentReply + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.CommentReply >(), list: vi.fn< ( fileId: string, commentId: string, - ) => GoogleAppsScript.Drive.Schema.CommentReplyList + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.CommentReplyList >(), patch: vi.fn< ( - resource: GoogleAppsScript.Drive.Schema.CommentReply, + resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.CommentReply, fileId: string, commentId: string, replyId: string, - ) => GoogleAppsScript.Drive.Schema.CommentReply + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.CommentReply >(), remove: vi.fn<(fileId: string, commentId: string, replyId: string) => void>(), update: vi.fn< ( - resource: GoogleAppsScript.Drive.Schema.CommentReply, + resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.CommentReply, fileId: string, commentId: string, replyId: string, - ) => GoogleAppsScript.Drive.Schema.CommentReply + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.CommentReply >(), }; } From aece0e5b01557797e8f9d0348901c23471176307 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20D=C4=9Bdi=C4=8D?= Date: Fri, 27 Dec 2024 15:12:08 +0100 Subject: [PATCH 3/9] Updated GAS stubs for Drive v3 --- tests/backend/test-utils/gas-stubs.ts | 438 ++++++++++++++++++++------ 1 file changed, 348 insertions(+), 90 deletions(-) diff --git a/tests/backend/test-utils/gas-stubs.ts b/tests/backend/test-utils/gas-stubs.ts index 8e5965f0..70c43e9b 100644 --- a/tests/backend/test-utils/gas-stubs.ts +++ b/tests/backend/test-utils/gas-stubs.ts @@ -2,30 +2,26 @@ import { vi } from "vitest"; export function mockedCommentsCollection(): GoogleAppsScript.Drive_v3.Drive.V3.Collection.CommentsCollection { return { - get: vi.fn< - ( - fileId: string, - commentId: string, - ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Comment - >(), - insert: + create: vi.fn< ( resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Comment, fileId: string, ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Comment >(), + get: vi.fn< + ( + fileId: string, + commentId: string, + optionalArgs?: Record, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Comment + >(), list: vi.fn< - (fileId: string) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.CommentList + ( + fileId: string, + optionalArgs?: Record, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.CommentList >(), - patch: - vi.fn< - ( - resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Comment, - fileId: string, - commentId: string, - ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Comment - >(), remove: vi.fn<(fileId: string, commentId: string) => void>(), update: vi.fn< @@ -40,40 +36,84 @@ export function mockedCommentsCollection(): GoogleAppsScript.Drive_v3.Drive.V3.C export function mockedDrive(): GoogleAppsScript.Drive { return { - newChannel: vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Channel>(), - newChildReference: - vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.ChildReference>(), - newComment: vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Comment>(), - newCommentContext: - vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.CommentContext>(), - newCommentReply: - vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.CommentReply>(), + About: mockedAboutCollection(), + Apps: mockedAppsCollection(), + Changes: mockedChangesCollection(), + Channels: mockedChannelsCollection(), + Comments: mockedCommentsCollection(), + Drives: mockedDrivesCollection(), + Files: mockedFilesCollection(), + newChannel: + vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Channel>(), + newComment: + vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Comment>(), + newCommentQuotedFileContent: + vi.fn< + () => GoogleAppsScript.Drive_v3.Drive.V3.Schema.CommentQuotedFileContent + >(), + newContentRestriction: + vi.fn< + () => GoogleAppsScript.Drive_v3.Drive.V3.Schema.ContentRestriction + >(), newDrive: vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Drive>(), newDriveBackgroundImageFile: - vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.DriveBackgroundImageFile>(), + vi.fn< + () => GoogleAppsScript.Drive_v3.Drive.V3.Schema.DriveBackgroundImageFile + >(), newDriveCapabilities: - vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.DriveCapabilities>(), + vi.fn< + () => GoogleAppsScript.Drive_v3.Drive.V3.Schema.DriveCapabilities + >(), newDriveRestrictions: - vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.DriveRestrictions>(), + vi.fn< + () => GoogleAppsScript.Drive_v3.Drive.V3.Schema.DriveRestrictions + >(), newFile: vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.File>(), newFileCapabilities: vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.FileCapabilities>(), + newFileContentHints: + vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.FileContentHints>(), + newFileContentHintsThumbnail: + vi.fn< + () => GoogleAppsScript.Drive_v3.Drive.V3.Schema.FileContentHintsThumbnail + >(), newFileImageMediaMetadata: - vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.FileImageMediaMetadata>(), + vi.fn< + () => GoogleAppsScript.Drive_v3.Drive.V3.Schema.FileImageMediaMetadata + >(), newFileImageMediaMetadataLocation: vi.fn< () => GoogleAppsScript.Drive_v3.Drive.V3.Schema.FileImageMediaMetadataLocation >(), - newFileIndexableText: - vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.FileIndexableText>(), - newFileLabels: vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.FileLabels>(), - newFileThumbnail: - vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.FileThumbnail>(), + newFileLabelInfo: + vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.FileLabelInfo>(), + newFileLinkShareMetadata: + vi.fn< + () => GoogleAppsScript.Drive_v3.Drive.V3.Schema.FileLinkShareMetadata + >(), + newFileShortcutDetails: + vi.fn< + () => GoogleAppsScript.Drive_v3.Drive.V3.Schema.FileShortcutDetails + >(), newFileVideoMediaMetadata: - vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.FileVideoMediaMetadata>(), - newParentReference: - vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.ParentReference>(), - newPermission: vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Permission>(), + vi.fn< + () => GoogleAppsScript.Drive_v3.Drive.V3.Schema.FileVideoMediaMetadata + >(), + newLabel: vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Label>(), + newLabelFieldModification: + vi.fn< + () => GoogleAppsScript.Drive_v3.Drive.V3.Schema.LabelFieldModification + >(), + newLabelModification: + vi.fn< + () => GoogleAppsScript.Drive_v3.Drive.V3.Schema.LabelModification + >(), + newModifyLabelsRequest: + vi.fn< + () => GoogleAppsScript.Drive_v3.Drive.V3.Schema.ModifyLabelsRequest + >(), + newPermission: + vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Permission>(), newPermissionPermissionDetails: vi.fn< () => GoogleAppsScript.Drive_v3.Drive.V3.Schema.PermissionPermissionDetails @@ -82,41 +122,68 @@ export function mockedDrive(): GoogleAppsScript.Drive { vi.fn< () => GoogleAppsScript.Drive_v3.Drive.V3.Schema.PermissionTeamDrivePermissionDetails >(), - newProperty: vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Property>(), - newRevision: vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Revision>(), - newTeamDrive: vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.TeamDrive>(), + newReply: vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Reply>(), + newRevision: + vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Revision>(), + newTeamDrive: + vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.TeamDrive>(), newTeamDriveBackgroundImageFile: vi.fn< () => GoogleAppsScript.Drive_v3.Drive.V3.Schema.TeamDriveBackgroundImageFile >(), newTeamDriveCapabilities: - vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.TeamDriveCapabilities>(), + vi.fn< + () => GoogleAppsScript.Drive_v3.Drive.V3.Schema.TeamDriveCapabilities + >(), newTeamDriveRestrictions: - vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.TeamDriveRestrictions>(), + vi.fn< + () => GoogleAppsScript.Drive_v3.Drive.V3.Schema.TeamDriveRestrictions + >(), newUser: vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.User>(), - newUserPicture: vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.UserPicture>(), + Operation: mockedOperationCollection(), + Operations: mockedOperationsCollection(), + Permissions: mockedPermissionsCollection(), + Replies: mockedRepliesCollection(), + Revisions: mockedRevisionsCollection(), + Teamdrives: mockedTeamdrivesCollection(), }; } export function mockedDrivesCollection(): GoogleAppsScript.Drive_v3.Drive.V3.Collection.DrivesCollection { return { - get: vi.fn<(driveId: string) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Drive>(), - hide: vi.fn<(driveId: string) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Drive>(), - insert: + create: vi.fn< ( resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Drive, requestId: string, ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Drive >(), - list: vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.DriveList>(), - remove: vi.fn<(driveId: string) => void>(), - unhide: vi.fn<(driveId: string) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Drive>(), + get: vi.fn< + ( + driveId: string, + optionalArgs?: Record, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Drive + >(), + hide: vi.fn< + (driveId: string) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Drive + >(), + list: vi.fn< + ( + optionalArgs?: Record, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.DriveList + >(), + remove: + vi.fn<(driveId: string, optionalArgs?: Record) => void>(), + unhide: + vi.fn< + (driveId: string) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Drive + >(), update: vi.fn< ( resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Drive, driveId: string, + optionalArgs?: Record, ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Drive >(), }; @@ -128,48 +195,70 @@ export function mockedFilesCollection(): GoogleAppsScript.Drive_v3.Drive.V3.Coll ( resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.File, fileId: string, + optionalArgs?: Record, ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.File >(), - emptyTrash: vi.fn<() => void>(), + create: + vi.fn< + ( + resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.File, + mediaData?: GoogleAppsScript.Base.Blob, + optionalArgs?: Record, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.File + >(), + download: + vi.fn< + ( + fileId: string, + optionalArgs?: Record, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Operation + >(), + emptyTrash: vi.fn<(optionalArgs?: Record) => void>(), export: vi.fn<(fileId: string, mimeType: string) => void>(), - generateIds: vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.GeneratedIds>(), + generateIds: + vi.fn< + ( + optionalArgs?: Record, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.GeneratedIds + >(), get: vi.fn() as { ( fileId: string, - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- From upstream types optionalArgs?: Record & { alt: "media" }, ): string; ( fileId: string, - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- From upstream types optionalArgs?: Record, ): GoogleAppsScript.Drive_v3.Drive.V3.Schema.File; }, - insert: + list: vi.fn< + ( + optionalArgs?: Record, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.FileList + >(), + listLabels: vi.fn< ( - resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.File, - mediaData?: Blob, - ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.File + fileId: string, + optionalArgs?: Record, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.LabelList >(), - list: vi.fn<() => GoogleAppsScript.Drive_v3.Drive.V3.Schema.FileList>(), - patch: + modifyLabels: vi.fn< ( - resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.File, + resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.ModifyLabelsRequest, fileId: string, - ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.File + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.ModifyLabelsResponse >(), - remove: vi.fn<(fileId: string) => void>(), - touch: vi.fn<(fileId: string) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.File>(), - trash: vi.fn<(fileId: string) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.File>(), - untrash: vi.fn<(fileId: string) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.File>(), + remove: + vi.fn<(fileId: string, optionalArgs?: Record) => void>(), update: vi.fn< ( resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.File, fileId: string, - mediaData?: Blob, + mediaData?: GoogleAppsScript.Base.Blob, + optionalArgs?: Record, ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.File >(), watch: @@ -177,6 +266,7 @@ export function mockedFilesCollection(): GoogleAppsScript.Drive_v3.Drive.V3.Coll ( resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Channel, fileId: string, + optionalArgs?: Record, ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Channel >(), }; @@ -258,46 +348,39 @@ export function mockedHtmlTemplate(): GoogleAppsScript.HTML.HtmlTemplate { export function mockedRepliesCollection(): GoogleAppsScript.Drive_v3.Drive.V3.Collection.RepliesCollection { return { + create: + vi.fn< + ( + resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Reply, + fileId: string, + commentId: string, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Reply + >(), get: vi.fn< ( fileId: string, commentId: string, replyId: string, - ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.CommentReply + optionalArgs?: Record, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Reply >(), - insert: - vi.fn< - ( - resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.CommentReply, - fileId: string, - commentId: string, - ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.CommentReply - >(), list: vi.fn< ( fileId: string, commentId: string, - ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.CommentReplyList + optionalArgs?: Record, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.ReplyList >(), - patch: - vi.fn< - ( - resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.CommentReply, - fileId: string, - commentId: string, - replyId: string, - ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.CommentReply - >(), remove: vi.fn<(fileId: string, commentId: string, replyId: string) => void>(), update: vi.fn< ( - resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.CommentReply, + resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Reply, fileId: string, commentId: string, replyId: string, - ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.CommentReply + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Reply >(), }; } @@ -411,7 +494,6 @@ export function mockedUtilities(): GoogleAppsScript.Utilities.Utilities { format: string, ) => string >(), - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- From Google apps script types formatString: vi.fn<(template: string, ...args: Array) => string>(), getUuid: vi.fn<() => string>(), gzip: vi.fn< @@ -420,9 +502,7 @@ export function mockedUtilities(): GoogleAppsScript.Utilities.Utilities { name?: string, ) => GoogleAppsScript.Base.Blob >(), - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- From Google apps script types jsonParse: vi.fn<(jsonString: string) => any>(), - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- From Google apps script types jsonStringify: vi.fn<(obj: any) => string>(), MacAlgorithm: { HMAC_MD5: 0, @@ -465,3 +545,181 @@ export function mockedUtilities(): GoogleAppsScript.Utilities.Utilities { >(), }; } + +function mockedAboutCollection(): GoogleAppsScript.Drive_v3.Drive.V3.Collection.AboutCollection { + return { + get: vi.fn< + ( + optionalArgs: Record, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.About + >(), + }; +} + +function mockedAppsCollection(): GoogleAppsScript.Drive_v3.Drive.V3.Collection.AppsCollection { + return { + get: vi.fn< + (appId: string) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.App + >(), + list: vi.fn< + ( + optionalArgs?: Record, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.AppList + >(), + }; +} + +function mockedChangesCollection(): GoogleAppsScript.Drive_v3.Drive.V3.Collection.ChangesCollection { + return { + getStartPageToken: + vi.fn< + ( + optionalArgs?: Record, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.StartPageToken + >(), + list: vi.fn< + ( + pageToken: string, + optionalArgs?: Record, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.ChangeList + >(), + watch: + vi.fn< + ( + resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Channel, + pageToken: string, + optionalArgs?: Record, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Channel + >(), + }; +} + +function mockedChannelsCollection(): GoogleAppsScript.Drive_v3.Drive.V3.Collection.ChannelsCollection { + return { + stop: vi.fn< + (resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Channel) => void + >(), + }; +} + +function mockedOperationCollection(): GoogleAppsScript.Drive_v3.Drive.V3.Collection.OperationCollection { + return { + cancel: vi.fn<(name: string) => void>(), + remove: vi.fn<(name: string) => void>(), + }; +} + +function mockedOperationsCollection(): GoogleAppsScript.Drive_v3.Drive.V3.Collection.OperationsCollection { + return { + get: vi.fn< + (name: string) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Operation + >(), + list: vi.fn< + ( + optionalArgs?: Record, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.ListOperationsResponse + >(), + }; +} + +function mockedPermissionsCollection(): GoogleAppsScript.Drive_v3.Drive.V3.Collection.PermissionsCollection { + return { + create: + vi.fn< + ( + resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Permission, + fileId: string, + optionalArgs?: Record, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Permission + >(), + get: vi.fn< + ( + fileId: string, + permissionId: string, + optionalArgs?: Record, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Permission + >(), + list: vi.fn< + ( + fileId: string, + optionalArgs?: Record, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.PermissionList + >(), + remove: + vi.fn< + ( + fileId: string, + permissionId: string, + optionalArgs?: Record, + ) => void + >(), + update: + vi.fn< + ( + resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Permission, + fileId: string, + permissionId: string, + optionalArgs?: Record, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Permission + >(), + }; +} + +function mockedRevisionsCollection(): GoogleAppsScript.Drive_v3.Drive.V3.Collection.RevisionsCollection { + return { + get: vi.fn< + ( + fileId: string, + revisionId: string, + optionalArgs?: Record, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Revision + >(), + list: vi.fn< + ( + fileId: string, + optionalArgs?: Record, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.RevisionList + >(), + remove: vi.fn<(fileId: string, revisionId: string) => void>(), + update: + vi.fn< + ( + resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Revision, + fileId: string, + revisionId: string, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Revision + >(), + }; +} + +function mockedTeamdrivesCollection(): GoogleAppsScript.Drive_v3.Drive.V3.Collection.TeamdrivesCollection { + return { + create: + vi.fn< + ( + resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.TeamDrive, + requestId: string, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.TeamDrive + >(), + get: vi.fn< + ( + teamDriveId: string, + optionalArgs?: Record, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.TeamDrive + >(), + list: vi.fn< + ( + optionalArgs?: Record, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.TeamDriveList + >(), + remove: vi.fn<(teamDriveId: string) => void>(), + update: + vi.fn< + ( + resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.TeamDrive, + teamDriveId: string, + optionalArgs?: Record, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.TeamDrive + >(), + }; +} From ff89c266bf032802a68fbf2ea3ebcd7862b035c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20D=C4=9Bdi=C4=8D?= Date: Fri, 27 Dec 2024 15:45:53 +0100 Subject: [PATCH 4/9] Updated tests for Drive v3 --- tests/backend/listFolders.test.ts | 7 +- tests/backend/listSharedDrives.test.ts | 2 +- tests/backend/move/copyFileComments.test.ts | 74 ++--- tests/backend/move/folderManagement.test.ts | 260 ++++++++---------- tests/backend/move/moveFile.test.ts | 48 ++-- tests/backend/move/moveFolder.test.ts | 24 +- .../move/resolveDestinationFolder.test.ts | 110 ++++---- .../test-utils/SafeDriveService-stub.ts | 18 +- tests/backend/utils/DriveBackedValue.test.ts | 118 ++++---- tests/backend/utils/SafeDriveService.test.ts | 52 ---- .../SafeCommentsCollection.test.ts | 136 +++++---- .../SafeDrivesCollection.test.ts | 32 +-- .../SafeFilesCollection.test.ts | 189 +++++-------- 13 files changed, 472 insertions(+), 598 deletions(-) diff --git a/tests/backend/listFolders.test.ts b/tests/backend/listFolders.test.ts index d8b2bd33..95681035 100644 --- a/tests/backend/listFolders.test.ts +++ b/tests/backend/listFolders.test.ts @@ -18,8 +18,8 @@ test("listFolders works correctly", () => { const rawResponse = { files: [ - { id: "ID1", title: "FOLDER1" }, - { id: "ID2", title: "FOLDER2" }, + { id: "ID1", name: "FOLDER1" }, + { id: "ID2", name: "FOLDER2" }, ], nextPageToken: undefined, }; @@ -79,12 +79,13 @@ test("listFolders works correctly with shortcuts", () => { { id: "ID1", mimeType: "application/vnd.google-apps.shortcut", + name: "FOLDER1", shortcutDetails: { targetId: "TRUE_ID1", }, title: "FOLDER1", }, - { id: "ID2", title: "FOLDER2" }, + { id: "ID2", name: "FOLDER2" }, ], nextPageToken: undefined, }; diff --git a/tests/backend/listSharedDrives.test.ts b/tests/backend/listSharedDrives.test.ts index 09b64579..d21b91ec 100644 --- a/tests/backend/listSharedDrives.test.ts +++ b/tests/backend/listSharedDrives.test.ts @@ -18,7 +18,7 @@ test("listSharedDrives works correctly", () => { { id: "ID2", name: "DRIVE2" }, ]; const rawResponse = { - items: response, + drives: response, }; const driveServiceMock = mockedSafeDriveService(); vi.mocked(driveServiceMock.Drives.list).mockReturnValueOnce(rawResponse); diff --git a/tests/backend/move/copyFileComments.test.ts b/tests/backend/move/copyFileComments.test.ts index ea1ae56c..364d9eee 100644 --- a/tests/backend/move/copyFileComments.test.ts +++ b/tests/backend/move/copyFileComments.test.ts @@ -11,34 +11,34 @@ test("copyFileComments works correctly", () => { } const rawResponse = { - items: [ + comments: [ { - author: { displayName: "COM1_AUTH", isAuthenticatedUser: false }, - commentId: "SRC_COM1_ID", + author: { displayName: "COM1_AUTH", me: false }, content: "COM1_CONTENT", + id: "SRC_COM1_ID", replies: [], }, { - author: { displayName: "COM2_AUTH", isAuthenticatedUser: true }, - commentId: "SRC_COM2_ID", + author: { displayName: "COM2_AUTH", me: true }, content: "COM2_CONTENT", + id: "SRC_COM2_ID", replies: [], }, ], nextPageToken: undefined, }; const driveServiceMock = mockedSafeDriveService(); - vi.mocked(driveServiceMock.Comments.insert) + vi.mocked(driveServiceMock.Comments.create) .mockReturnValueOnce({ - author: { displayName: "COM2_AUTH", isAuthenticatedUser: true }, - commentId: "DEST_COM1_ID", + author: { displayName: "COM2_AUTH", me: true }, content: "*COM1_AUTH:*\nCOM1_CONTENT", + id: "DEST_COM1_ID", replies: [], }) .mockReturnValueOnce({ - author: { displayName: "COM2_AUTH", isAuthenticatedUser: true }, - commentId: "DEST_COM2_ID", + author: { displayName: "COM2_AUTH", me: true }, content: "COM2_CONTENT", + id: "DEST_COM2_ID", replies: [], }); vi.mocked(driveServiceMock.Comments.list).mockReturnValueOnce(rawResponse); @@ -72,25 +72,25 @@ test("copyFileComments works correctly", () => { ?.split(",") .map((s) => s.trim()), ).toContain("nextPageToken"); - expect(vi.mocked(driveServiceMock.Comments.insert).mock.calls).toHaveLength( + expect(vi.mocked(driveServiceMock.Comments.create).mock.calls).toHaveLength( 2, ); expect( - vi.mocked(driveServiceMock.Comments.insert).mock.calls[0][0].content, + vi.mocked(driveServiceMock.Comments.create).mock.calls[0][0].content, ).toBe("*COM1_AUTH:*\nCOM1_CONTENT"); expect( - vi.mocked(driveServiceMock.Comments.insert).mock.calls[0][0].replies, + vi.mocked(driveServiceMock.Comments.create).mock.calls[0][0].replies, ).toStrictEqual([]); - expect(vi.mocked(driveServiceMock.Comments.insert).mock.calls[0][1]).toBe( + expect(vi.mocked(driveServiceMock.Comments.create).mock.calls[0][1]).toBe( "DEST_FILE_ID", ); expect( - vi.mocked(driveServiceMock.Comments.insert).mock.calls[1][0].content, + vi.mocked(driveServiceMock.Comments.create).mock.calls[1][0].content, ).toBe("COM2_CONTENT"); expect( - vi.mocked(driveServiceMock.Comments.insert).mock.calls[1][0].replies, + vi.mocked(driveServiceMock.Comments.create).mock.calls[1][0].replies, ).toStrictEqual([]); - expect(vi.mocked(driveServiceMock.Comments.insert).mock.calls[1][1]).toBe( + expect(vi.mocked(driveServiceMock.Comments.create).mock.calls[1][1]).toBe( "DEST_FILE_ID", ); }); @@ -103,18 +103,18 @@ test("copyFileComments works correctly with replies", () => { } const rawResponse = { - items: [ + comments: [ { - author: { displayName: "COM_AUTH", isAuthenticatedUser: true }, - commentId: "SRC_COM_ID", + author: { displayName: "COM_AUTH", me: true }, content: "COM_CONTENT", + id: "SRC_COM_ID", replies: [ { - author: { displayName: "REPLY1_AUTH", isAuthenticatedUser: false }, + author: { displayName: "REPLY1_AUTH", me: false }, content: "REPLY1_CONTENT", }, { - author: { displayName: "REPLY2_AUTH", isAuthenticatedUser: true }, + author: { displayName: "REPLY2_AUTH", me: true }, content: "REPLY2_CONTENT", }, ], @@ -123,14 +123,14 @@ test("copyFileComments works correctly with replies", () => { nextPageToken: undefined, }; const driveServiceMock = mockedSafeDriveService(); - vi.mocked(driveServiceMock.Comments.insert).mockReturnValueOnce({ - author: { displayName: "COM_AUTH", isAuthenticatedUser: true }, - commentId: "DEST_COM_ID", + vi.mocked(driveServiceMock.Comments.create).mockReturnValueOnce({ + author: { displayName: "COM_AUTH", me: true }, content: "COM_CONTENT", + id: "DEST_COM_ID", replies: [], }); vi.mocked(driveServiceMock.Comments.list).mockReturnValueOnce(rawResponse); - vi.mocked(driveServiceMock.Replies.insert).mockReturnValueOnce({}); + vi.mocked(driveServiceMock.Replies.create).mockReturnValueOnce({}); copyFileComments_("SRC_FILE_ID", "DEST_FILE_ID", driveServiceMock); @@ -161,35 +161,35 @@ test("copyFileComments works correctly with replies", () => { ?.split(",") .map((s) => s.trim()), ).toContain("nextPageToken"); - expect(vi.mocked(driveServiceMock.Comments.insert).mock.calls).toHaveLength( + expect(vi.mocked(driveServiceMock.Comments.create).mock.calls).toHaveLength( 1, ); expect( - vi.mocked(driveServiceMock.Comments.insert).mock.calls[0][0].content, + vi.mocked(driveServiceMock.Comments.create).mock.calls[0][0].content, ).toBe("COM_CONTENT"); expect( - vi.mocked(driveServiceMock.Comments.insert).mock.calls[0][0].replies, + vi.mocked(driveServiceMock.Comments.create).mock.calls[0][0].replies, ).toStrictEqual([]); - expect(vi.mocked(driveServiceMock.Comments.insert).mock.calls[0][1]).toBe( + expect(vi.mocked(driveServiceMock.Comments.create).mock.calls[0][1]).toBe( "DEST_FILE_ID", ); - expect(vi.mocked(driveServiceMock.Replies.insert).mock.calls).toHaveLength(2); + expect(vi.mocked(driveServiceMock.Replies.create).mock.calls).toHaveLength(2); expect( - vi.mocked(driveServiceMock.Replies.insert).mock.calls[0][0].content, + vi.mocked(driveServiceMock.Replies.create).mock.calls[0][0].content, ).toBe("*REPLY1_AUTH:*\nREPLY1_CONTENT"); - expect(vi.mocked(driveServiceMock.Replies.insert).mock.calls[0][1]).toBe( + expect(vi.mocked(driveServiceMock.Replies.create).mock.calls[0][1]).toBe( "DEST_FILE_ID", ); - expect(vi.mocked(driveServiceMock.Replies.insert).mock.calls[0][2]).toBe( + expect(vi.mocked(driveServiceMock.Replies.create).mock.calls[0][2]).toBe( "DEST_COM_ID", ); expect( - vi.mocked(driveServiceMock.Replies.insert).mock.calls[1][0].content, + vi.mocked(driveServiceMock.Replies.create).mock.calls[1][0].content, ).toBe("REPLY2_CONTENT"); - expect(vi.mocked(driveServiceMock.Replies.insert).mock.calls[1][1]).toBe( + expect(vi.mocked(driveServiceMock.Replies.create).mock.calls[1][1]).toBe( "DEST_FILE_ID", ); - expect(vi.mocked(driveServiceMock.Replies.insert).mock.calls[1][2]).toBe( + expect(vi.mocked(driveServiceMock.Replies.create).mock.calls[1][2]).toBe( "DEST_COM_ID", ); }); diff --git a/tests/backend/move/folderManagement.test.ts b/tests/backend/move/folderManagement.test.ts index e48d78c0..066ddc9d 100644 --- a/tests/backend/move/folderManagement.test.ts +++ b/tests/backend/move/folderManagement.test.ts @@ -17,27 +17,27 @@ test("listFilesInFolder works correctly", () => { supportsAllDrives?: boolean; } - const items = [ + const files = [ { capabilities: { canMoveItemOutOfDrive: true }, id: "FILE1_ID", - title: "FILE1_TITLE", + name: "FILE1_TITLE", }, { capabilities: { canMoveItemOutOfDrive: false }, id: "FILE2_ID", - title: "FILE2_TITLE", + name: "FILE2_TITLE", }, ]; const rawResponse = { - items, + files, nextPageToken: undefined, }; const driveServiceMock = mockedSafeDriveService(); vi.mocked(driveServiceMock.Files.list).mockReturnValueOnce(rawResponse); expect(listFilesInFolder_("FOLDER_ID", driveServiceMock)).toStrictEqual( - items, + files, ); expect(vi.mocked(driveServiceMock.Files.list).mock.calls).toHaveLength(1); @@ -76,7 +76,7 @@ test("listFilesInFolder works correctly", () => { { capabilities: { canMoveItemOutOfDrive: true }, id: true, - title: true, + name: true, }, ); }); @@ -90,27 +90,27 @@ test("listFoldersInFolder works correctly", () => { supportsAllDrives?: boolean; } - const items = [ + const files = [ { capabilities: { canMoveItemOutOfDrive: true }, id: "FILE1_ID", - title: "FILE1_TITLE", + name: "FILE1_TITLE", }, { capabilities: { canMoveItemOutOfDrive: false }, id: "FILE2_ID", - title: "FILE2_TITLE", + name: "FILE2_TITLE", }, ]; const rawResponse = { - items, + files, nextPageToken: undefined, }; const driveServiceMock = mockedSafeDriveService(); vi.mocked(driveServiceMock.Files.list).mockReturnValueOnce(rawResponse); expect(listFoldersInFolder_("FOLDER_ID", driveServiceMock)).toStrictEqual( - items, + files, ); expect(vi.mocked(driveServiceMock.Files.list).mock.calls).toHaveLength(1); @@ -149,7 +149,7 @@ test("listFoldersInFolder works correctly", () => { { capabilities: { canMoveItemOutOfDrive: true }, id: true, - title: true, + name: true, }, ); }); @@ -163,7 +163,7 @@ test("isFolderEmpty works correctly with an empty folder", () => { } const rawResponse = { - items: [], + files: [], }; const driveServiceMock = mockedSafeDriveService(); vi.mocked(driveServiceMock.Files.list).mockReturnValueOnce(rawResponse); @@ -200,7 +200,7 @@ test("isFolderEmpty works correctly with a non-empty folder", () => { } const rawResponse = { - items: [{ id: "ID_FILE" }], + files: [{ id: "ID_FILE" }], }; const driveServiceMock = mockedSafeDriveService(); vi.mocked(driveServiceMock.Files.list).mockReturnValueOnce(rawResponse); @@ -228,72 +228,63 @@ test("isFolderEmpty works correctly with a non-empty folder", () => { ).toBe(true); }); -test.each(["owner", "organizer"] as Array< - "fileOrganizer" | "organizer" | "owner" | "reader" | "writer" ->)( - "deleteFolderIfEmpty works correctly", - (role: "fileOrganizer" | "organizer" | "owner" | "reader" | "writer") => { - interface ListFilesOptions { - includeItemsFromAllDrives?: boolean; - maxResults?: number; - pageToken?: string; - q?: string; - supportsAllDrives?: boolean; - } +test("deleteFolderIfEmpty works correctly", () => { + interface ListFilesOptions { + includeItemsFromAllDrives?: boolean; + maxResults?: number; + pageToken?: string; + q?: string; + supportsAllDrives?: boolean; + } - const getResponse = { - userPermission: { role }, - }; - const listResponse = { - items: [], - nextPageToken: undefined, - }; - const driveServiceMock = mockedSafeDriveService(); - vi.mocked(driveServiceMock.Files.get).mockReturnValueOnce(getResponse); - vi.mocked(driveServiceMock.Files.list).mockReturnValueOnce(listResponse); + const getResponse = { + capabilities: { + canDelete: true, + }, + }; + const listResponse = { + files: [], + nextPageToken: undefined, + }; + const driveServiceMock = mockedSafeDriveService(); + vi.mocked(driveServiceMock.Files.get).mockReturnValueOnce(getResponse); + vi.mocked(driveServiceMock.Files.list).mockReturnValueOnce(listResponse); - deleteFolderIfEmpty_("FOLDER_ID", driveServiceMock); + deleteFolderIfEmpty_("FOLDER_ID", driveServiceMock); - expect(vi.mocked(driveServiceMock.Files.list).mock.calls).toHaveLength(1); - expect( - vi.mocked(driveServiceMock.Files.list).mock.calls[0][0], - ).toBeDefined(); - expect( - ( - vi.mocked(driveServiceMock.Files.list).mock - .calls[0][1] as ListFilesOptions - ).q, - ).toContain('"FOLDER_ID" in parents'); - expect( - ( - vi.mocked(driveServiceMock.Files.list).mock - .calls[0][1] as ListFilesOptions - ).includeItemsFromAllDrives, - ).toBe(true); - expect( - ( - vi.mocked(driveServiceMock.Files.list).mock - .calls[0][1] as ListFilesOptions - ).supportsAllDrives, - ).toBe(true); - expect(vi.mocked(driveServiceMock.Files.get).mock.calls).toHaveLength(1); - expect(vi.mocked(driveServiceMock.Files.get).mock.calls[0][0]).toBe( - "FOLDER_ID", - ); - expect( - vi.mocked(driveServiceMock.Files.get).mock.calls[0][1], - ).toBeDefined(); - expect( - vi.mocked(driveServiceMock.Files.get).mock.calls[0][1], - ).toStrictEqual({ - userPermission: { role: true }, - }); - expect(vi.mocked(driveServiceMock.Files.remove).mock.calls).toHaveLength(1); - expect(vi.mocked(driveServiceMock.Files.remove).mock.calls[0][0]).toBe( - "FOLDER_ID", - ); - }, -); + expect(vi.mocked(driveServiceMock.Files.list).mock.calls).toHaveLength(1); + expect(vi.mocked(driveServiceMock.Files.list).mock.calls[0][0]).toBeDefined(); + expect( + ( + vi.mocked(driveServiceMock.Files.list).mock + .calls[0][1] as ListFilesOptions + ).q, + ).toContain('"FOLDER_ID" in parents'); + expect( + ( + vi.mocked(driveServiceMock.Files.list).mock + .calls[0][1] as ListFilesOptions + ).includeItemsFromAllDrives, + ).toBe(true); + expect( + ( + vi.mocked(driveServiceMock.Files.list).mock + .calls[0][1] as ListFilesOptions + ).supportsAllDrives, + ).toBe(true); + expect(vi.mocked(driveServiceMock.Files.get).mock.calls).toHaveLength(1); + expect(vi.mocked(driveServiceMock.Files.get).mock.calls[0][0]).toBe( + "FOLDER_ID", + ); + expect(vi.mocked(driveServiceMock.Files.get).mock.calls[0][1]).toBeDefined(); + expect(vi.mocked(driveServiceMock.Files.get).mock.calls[0][1]).toStrictEqual({ + capabilities: { canDelete: true }, + }); + expect(vi.mocked(driveServiceMock.Files.remove).mock.calls).toHaveLength(1); + expect(vi.mocked(driveServiceMock.Files.remove).mock.calls[0][0]).toBe( + "FOLDER_ID", + ); +}); test("deleteFolderIfEmpty doesn't delete a non-empty folder", () => { interface ListFilesOptions { @@ -305,7 +296,7 @@ test("deleteFolderIfEmpty doesn't delete a non-empty folder", () => { } const listResponse = { - items: [{ userPermission: { role: "reader" } }], + files: [{ userPermission: { role: "reader" } }], nextPageToken: undefined, }; const driveServiceMock = mockedSafeDriveService(); @@ -337,66 +328,59 @@ test("deleteFolderIfEmpty doesn't delete a non-empty folder", () => { expect(vi.mocked(driveServiceMock.Files.remove).mock.calls).toHaveLength(0); }); -test.each(["fileOrganizer", "reader", "writer"] as Array< - "fileOrganizer" | "organizer" | "owner" | "reader" | "writer" ->)( - "deleteFolderIfEmpty doesn't try to delete a folder without permissions", - (role: "fileOrganizer" | "organizer" | "owner" | "reader" | "writer") => { - interface ListFilesOptions { - includeItemsFromAllDrives?: boolean; - maxResults?: number; - pageToken?: string; - q?: string; - supportsAllDrives?: boolean; - } +test("deleteFolderIfEmpty doesn't try to delete a folder without permissions", () => { + interface ListFilesOptions { + includeItemsFromAllDrives?: boolean; + maxResults?: number; + pageToken?: string; + q?: string; + supportsAllDrives?: boolean; + } - const getResponse = { - userPermission: { role }, - }; - const listResponse = { - items: [], - nextPageToken: undefined, - }; - const driveServiceMock = mockedSafeDriveService(); - vi.mocked(driveServiceMock.Files.get).mockReturnValueOnce(getResponse); - vi.mocked(driveServiceMock.Files.list).mockReturnValueOnce(listResponse); + const getResponse = { + capabilities: { + canDelete: false, + }, + }; + const listResponse = { + files: [], + nextPageToken: undefined, + }; + const driveServiceMock = mockedSafeDriveService(); + vi.mocked(driveServiceMock.Files.get).mockReturnValueOnce(getResponse); + vi.mocked(driveServiceMock.Files.list).mockReturnValueOnce(listResponse); - deleteFolderIfEmpty_("FOLDER_ID", driveServiceMock); + deleteFolderIfEmpty_("FOLDER_ID", driveServiceMock); - expect(vi.mocked(driveServiceMock.Files.list).mock.calls).toHaveLength(1); - expect( - vi.mocked(driveServiceMock.Files.list).mock.calls[0][0], - ).toBeDefined(); - expect( - ( - vi.mocked(driveServiceMock.Files.list).mock - .calls[0][1] as ListFilesOptions - ).q, - ).toContain('"FOLDER_ID" in parents'); - expect( - ( - vi.mocked(driveServiceMock.Files.list).mock - .calls[0][1] as ListFilesOptions - ).includeItemsFromAllDrives, - ).toBe(true); - expect( - ( - vi.mocked(driveServiceMock.Files.list).mock - .calls[0][1] as ListFilesOptions - ).supportsAllDrives, - ).toBe(true); - expect(vi.mocked(driveServiceMock.Files.get).mock.calls).toHaveLength(1); - expect(vi.mocked(driveServiceMock.Files.get).mock.calls[0][0]).toBe( - "FOLDER_ID", - ); - expect( - vi.mocked(driveServiceMock.Files.get).mock.calls[0][1], - ).toBeDefined(); - expect( - vi.mocked(driveServiceMock.Files.get).mock.calls[0][1], - ).toStrictEqual({ - userPermission: { role: true }, - }); - expect(vi.mocked(driveServiceMock.Files.remove).mock.calls).toHaveLength(0); - }, -); + expect(vi.mocked(driveServiceMock.Files.list).mock.calls).toHaveLength(1); + expect(vi.mocked(driveServiceMock.Files.list).mock.calls[0][0]).toBeDefined(); + expect( + ( + vi.mocked(driveServiceMock.Files.list).mock + .calls[0][1] as ListFilesOptions + ).q, + ).toContain('"FOLDER_ID" in parents'); + expect( + ( + vi.mocked(driveServiceMock.Files.list).mock + .calls[0][1] as ListFilesOptions + ).includeItemsFromAllDrives, + ).toBe(true); + expect( + ( + vi.mocked(driveServiceMock.Files.list).mock + .calls[0][1] as ListFilesOptions + ).supportsAllDrives, + ).toBe(true); + expect(vi.mocked(driveServiceMock.Files.get).mock.calls).toHaveLength(1); + expect(vi.mocked(driveServiceMock.Files.get).mock.calls[0][0]).toBe( + "FOLDER_ID", + ); + expect(vi.mocked(driveServiceMock.Files.get).mock.calls[0][1]).toBeDefined(); + expect(vi.mocked(driveServiceMock.Files.get).mock.calls[0][1]).toStrictEqual({ + capabilities: { + canDelete: true, + }, + }); + expect(vi.mocked(driveServiceMock.Files.remove).mock.calls).toHaveLength(0); +}); diff --git a/tests/backend/move/moveFile.test.ts b/tests/backend/move/moveFile.test.ts index e33151ac..605ddc32 100644 --- a/tests/backend/move/moveFile.test.ts +++ b/tests/backend/move/moveFile.test.ts @@ -29,7 +29,7 @@ test("moveFile works correctly with a file that can be moved directly", () => { { capabilities: { canMoveItemOutOfDrive: true }, id: "SRC_FILE_ID", - title: "FILE_NAME", + name: "FILE_NAME", }, state, { @@ -46,24 +46,24 @@ test("moveFile works correctly with a file that can be moved directly", () => { "SRC_FILE_ID", ); expect( - vi.mocked(driveServiceMock.Files.update).mock.calls[0][3], + vi.mocked(driveServiceMock.Files.update).mock.calls[0][4], ).toBeDefined(); expect( ( vi.mocked(driveServiceMock.Files.update).mock - .calls[0][3] as UpdateFileOptions + .calls[0][4] as UpdateFileOptions ).addParents, ).toContain("DEST_PARENT_ID"); expect( ( vi.mocked(driveServiceMock.Files.update).mock - .calls[0][3] as UpdateFileOptions + .calls[0][4] as UpdateFileOptions ).removeParents, ).toContain("SRC_PARENT_ID"); expect( ( vi.mocked(driveServiceMock.Files.update).mock - .calls[0][3] as UpdateFileOptions + .calls[0][4] as UpdateFileOptions ).supportsAllDrives, ).toBe(true); }); @@ -99,7 +99,7 @@ test("moveFile works correctly with a file that can be moved out of drive, yet c { capabilities: { canMoveItemOutOfDrive: true }, id: "SRC_FILE_ID", - title: "FILE_NAME", + name: "FILE_NAME", }, state, { @@ -116,24 +116,24 @@ test("moveFile works correctly with a file that can be moved out of drive, yet c "SRC_FILE_ID", ); expect( - vi.mocked(driveServiceMock.Files.update).mock.calls[0][3], + vi.mocked(driveServiceMock.Files.update).mock.calls[0][4], ).toBeDefined(); expect( ( vi.mocked(driveServiceMock.Files.update).mock - .calls[0][3] as UpdateFileOptions + .calls[0][4] as UpdateFileOptions ).addParents, ).toContain("DEST_PARENT_ID"); expect( ( vi.mocked(driveServiceMock.Files.update).mock - .calls[0][3] as UpdateFileOptions + .calls[0][4] as UpdateFileOptions ).removeParents, ).toContain("SRC_PARENT_ID"); expect( ( vi.mocked(driveServiceMock.Files.update).mock - .calls[0][3] as UpdateFileOptions + .calls[0][4] as UpdateFileOptions ).supportsAllDrives, ).toBe(true); expect(vi.mocked(driveServiceMock.Files.copy).mock.calls).toHaveLength(1); @@ -141,9 +141,9 @@ test("moveFile works correctly with a file that can be moved out of drive, yet c vi.mocked(driveServiceMock.Files.copy).mock.calls[0][0].parents, ).toHaveLength(1); expect( - vi.mocked(driveServiceMock.Files.copy).mock.calls[0][0].parents?.[0].id, + vi.mocked(driveServiceMock.Files.copy).mock.calls[0][0].parents?.[0], ).toBe("DEST_PARENT_ID"); - expect(vi.mocked(driveServiceMock.Files.copy).mock.calls[0][0].title).toBe( + expect(vi.mocked(driveServiceMock.Files.copy).mock.calls[0][0].name).toBe( "FILE_NAME", ); expect(vi.mocked(driveServiceMock.Files.copy).mock.calls[0][1]).toBe( @@ -179,7 +179,7 @@ test("moveFile works correctly with a file that cannot be moved out of drive", ( { capabilities: { canMoveItemOutOfDrive: false }, id: "SRC_FILE_ID", - title: "FILE_NAME", + name: "FILE_NAME", }, state, { @@ -196,9 +196,9 @@ test("moveFile works correctly with a file that cannot be moved out of drive", ( vi.mocked(driveServiceMock.Files.copy).mock.calls[0][0].parents, ).toHaveLength(1); expect( - vi.mocked(driveServiceMock.Files.copy).mock.calls[0][0].parents?.[0].id, + vi.mocked(driveServiceMock.Files.copy).mock.calls[0][0].parents?.[0], ).toBe("DEST_PARENT_ID"); - expect(vi.mocked(driveServiceMock.Files.copy).mock.calls[0][0].title).toBe( + expect(vi.mocked(driveServiceMock.Files.copy).mock.calls[0][0].name).toBe( "FILE_NAME", ); expect(vi.mocked(driveServiceMock.Files.copy).mock.calls[0][1]).toBe( @@ -232,7 +232,7 @@ test("moveFile works correctly with a file that can be moved directly with comme { capabilities: { canMoveItemOutOfDrive: true }, id: "SRC_FILE_ID", - title: "FILE_NAME", + name: "FILE_NAME", }, state, { @@ -249,24 +249,24 @@ test("moveFile works correctly with a file that can be moved directly with comme "SRC_FILE_ID", ); expect( - vi.mocked(driveServiceMock.Files.update).mock.calls[0][3], + vi.mocked(driveServiceMock.Files.update).mock.calls[0][4], ).toBeDefined(); expect( ( vi.mocked(driveServiceMock.Files.update).mock - .calls[0][3] as UpdateFileOptions + .calls[0][4] as UpdateFileOptions ).addParents, ).toContain("DEST_PARENT_ID"); expect( ( vi.mocked(driveServiceMock.Files.update).mock - .calls[0][3] as UpdateFileOptions + .calls[0][4] as UpdateFileOptions ).removeParents, ).toContain("SRC_PARENT_ID"); expect( ( vi.mocked(driveServiceMock.Files.update).mock - .calls[0][3] as UpdateFileOptions + .calls[0][4] as UpdateFileOptions ).supportsAllDrives, ).toBe(true); }); @@ -295,7 +295,7 @@ test("moveFile works correctly with a file that cannot be moved out of drive wit { capabilities: { canMoveItemOutOfDrive: false }, id: "SRC_FILE_ID", - title: "FILE_NAME", + name: "FILE_NAME", }, state, { @@ -312,9 +312,9 @@ test("moveFile works correctly with a file that cannot be moved out of drive wit vi.mocked(driveServiceMock.Files.copy).mock.calls[0][0].parents, ).toHaveLength(1); expect( - vi.mocked(driveServiceMock.Files.copy).mock.calls[0][0].parents?.[0].id, + vi.mocked(driveServiceMock.Files.copy).mock.calls[0][0].parents?.[0], ).toBe("DEST_PARENT_ID"); - expect(vi.mocked(driveServiceMock.Files.copy).mock.calls[0][0].title).toBe( + expect(vi.mocked(driveServiceMock.Files.copy).mock.calls[0][0].name).toBe( "FILE_NAME", ); expect(vi.mocked(driveServiceMock.Files.copy).mock.calls[0][1]).toBe( @@ -363,7 +363,7 @@ test("moveFile fails gracefully on error", () => { { capabilities: { canMoveItemOutOfDrive: true }, id: "SRC_FILE_ID", - title: "FILE_NAME", + name: "FILE_NAME", }, state, { diff --git a/tests/backend/move/moveFolder.test.ts b/tests/backend/move/moveFolder.test.ts index 8826f54f..cf0397c2 100644 --- a/tests/backend/move/moveFolder.test.ts +++ b/tests/backend/move/moveFolder.test.ts @@ -54,12 +54,12 @@ test("moveFolder moves files correctly", () => { { capabilities: { canMoveItemOutOfDrive: true }, id: "FILE1_ID", - title: "FILE1_TITLE", + name: "FILE1_TITLE", }, { capabilities: { canMoveItemOutOfDrive: true }, id: "FILE2_ID", - title: "FILE2_TITLE", + name: "FILE2_TITLE", }, ]); const listFoldersInFolder = vi @@ -115,12 +115,12 @@ test("moveFolder adds subfolders to the state correctly", () => { { capabilities: { canMoveItemOutOfDrive: true }, id: "SRC_SUBFOLDER1_ID", - title: "SUBFOLDER1_NAME", + name: "SUBFOLDER1_NAME", }, { capabilities: { canMoveItemOutOfDrive: true }, id: "SRC_SUBFOLDER2_ID", - title: "SUBFOLDER2_NAME", + name: "SUBFOLDER2_NAME", }, ]); const resolveDestinationFolderFn = vi @@ -192,12 +192,12 @@ test("moveFolder moves files correctly, even when listing folders throws", () => { capabilities: { canMoveItemOutOfDrive: true }, id: "FILE1_ID", - title: "FILE1_TITLE", + name: "FILE1_TITLE", }, { capabilities: { canMoveItemOutOfDrive: true }, id: "FILE2_ID", - title: "FILE2_TITLE", + name: "FILE2_TITLE", }, ]); const listFoldersInFolder = vi @@ -265,12 +265,12 @@ test("moveFolder adds subfolders to the state correctly, even when listing files { capabilities: { canMoveItemOutOfDrive: true }, id: "SRC_SUBFOLDER1_ID", - title: "SUBFOLDER1_NAME", + name: "SUBFOLDER1_NAME", }, { capabilities: { canMoveItemOutOfDrive: true }, id: "SRC_SUBFOLDER2_ID", - title: "SUBFOLDER2_NAME", + name: "SUBFOLDER2_NAME", }, ]); const resolveDestinationFolderFn = vi @@ -347,12 +347,12 @@ test("moveFolder passes copyComments correctly", () => { { capabilities: { canMoveItemOutOfDrive: true }, id: "FILE1_ID", - title: "FILE1_TITLE", + name: "FILE1_TITLE", }, { capabilities: { canMoveItemOutOfDrive: true }, id: "FILE2_ID", - title: "FILE2_TITLE", + name: "FILE2_TITLE", }, ]); const listFoldersInFolder = vi @@ -409,12 +409,12 @@ test("moveFolder passes mergeFolders correctly", () => { { capabilities: { canMoveItemOutOfDrive: true }, id: "SRC_SUBFOLDER1_ID", - title: "SUBFOLDER1_NAME", + name: "SUBFOLDER1_NAME", }, { capabilities: { canMoveItemOutOfDrive: true }, id: "SRC_SUBFOLDER2_ID", - title: "SUBFOLDER2_NAME", + name: "SUBFOLDER2_NAME", }, ]); const resolveDestinationFolderFn = vi diff --git a/tests/backend/move/resolveDestinationFolder.test.ts b/tests/backend/move/resolveDestinationFolder.test.ts index 5af4070e..caf959d0 100644 --- a/tests/backend/move/resolveDestinationFolder.test.ts +++ b/tests/backend/move/resolveDestinationFolder.test.ts @@ -14,9 +14,9 @@ test("resolveDestinationFolder corretly creates new folder", () => { } const driveServiceMock = mockedSafeDriveService(); - vi.mocked(driveServiceMock.Files.insert).mockReturnValueOnce({ + vi.mocked(driveServiceMock.Files.create).mockReturnValueOnce({ id: "NEWLY_CREATED_FOLDER_ID", - title: "FOLDER_NAME", + name: "FOLDER_NAME", }); const state = new MoveState_( @@ -32,7 +32,7 @@ test("resolveDestinationFolder corretly creates new folder", () => { { capabilities: { canMoveItemOutOfDrive: true }, id: "SRC_FOLDER_ID", - title: "FOLDER_NAME", + name: "FOLDER_NAME", }, state, { @@ -43,24 +43,24 @@ test("resolveDestinationFolder corretly creates new folder", () => { false, driveServiceMock, ), - ).toStrictEqual({ id: "NEWLY_CREATED_FOLDER_ID", title: "FOLDER_NAME" }); + ).toStrictEqual({ id: "NEWLY_CREATED_FOLDER_ID", name: "FOLDER_NAME" }); - expect(vi.mocked(driveServiceMock.Files.insert).mock.calls).toHaveLength(1); + expect(vi.mocked(driveServiceMock.Files.create).mock.calls).toHaveLength(1); expect( - vi.mocked(driveServiceMock.Files.insert).mock.calls[0][0].mimeType, + vi.mocked(driveServiceMock.Files.create).mock.calls[0][0].mimeType, ).toBe("application/vnd.google-apps.folder"); expect( - vi.mocked(driveServiceMock.Files.insert).mock.calls[0][0].parents, - ).toStrictEqual([{ id: "DEST_PARENT_ID" }]); - expect(vi.mocked(driveServiceMock.Files.insert).mock.calls[0][0].title).toBe( + vi.mocked(driveServiceMock.Files.create).mock.calls[0][0].parents, + ).toStrictEqual(["DEST_PARENT_ID"]); + expect(vi.mocked(driveServiceMock.Files.create).mock.calls[0][0].name).toBe( "FOLDER_NAME", ); expect( - vi.mocked(driveServiceMock.Files.insert).mock.calls[0][3], + vi.mocked(driveServiceMock.Files.create).mock.calls[0][3], ).toBeDefined(); expect( ( - vi.mocked(driveServiceMock.Files.insert).mock + vi.mocked(driveServiceMock.Files.create).mock .calls[0][3] as InsertFileOptions ).supportsAllDrives, ).toBe(true); @@ -76,13 +76,13 @@ test("resolveDestinationFolder corretly creates new folder when set not to merge { capabilities: { canMoveItemOutOfDrive: true }, id: "EXISTING_FOLDER_ID", - title: "FOLDER_NAME", + name: "FOLDER_NAME", }, ]); const driveServiceMock = mockedSafeDriveService(); - vi.mocked(driveServiceMock.Files.insert).mockReturnValueOnce({ + vi.mocked(driveServiceMock.Files.create).mockReturnValueOnce({ id: "NEWLY_CREATED_FOLDER_ID", - title: "FOLDER_NAME", + name: "FOLDER_NAME", }); const state = new MoveState_( @@ -98,7 +98,7 @@ test("resolveDestinationFolder corretly creates new folder when set not to merge { capabilities: { canMoveItemOutOfDrive: true }, id: "SRC_FOLDER_ID", - title: "FOLDER_NAME", + name: "FOLDER_NAME", }, state, { @@ -109,24 +109,24 @@ test("resolveDestinationFolder corretly creates new folder when set not to merge false, driveServiceMock, ), - ).toStrictEqual({ id: "NEWLY_CREATED_FOLDER_ID", title: "FOLDER_NAME" }); + ).toStrictEqual({ id: "NEWLY_CREATED_FOLDER_ID", name: "FOLDER_NAME" }); - expect(vi.mocked(driveServiceMock.Files.insert).mock.calls).toHaveLength(1); + expect(vi.mocked(driveServiceMock.Files.create).mock.calls).toHaveLength(1); expect( - vi.mocked(driveServiceMock.Files.insert).mock.calls[0][0].mimeType, + vi.mocked(driveServiceMock.Files.create).mock.calls[0][0].mimeType, ).toBe("application/vnd.google-apps.folder"); expect( - vi.mocked(driveServiceMock.Files.insert).mock.calls[0][0].parents, - ).toStrictEqual([{ id: "DEST_PARENT_ID" }]); - expect(vi.mocked(driveServiceMock.Files.insert).mock.calls[0][0].title).toBe( + vi.mocked(driveServiceMock.Files.create).mock.calls[0][0].parents, + ).toStrictEqual(["DEST_PARENT_ID"]); + expect(vi.mocked(driveServiceMock.Files.create).mock.calls[0][0].name).toBe( "FOLDER_NAME", ); expect( - vi.mocked(driveServiceMock.Files.insert).mock.calls[0][3], + vi.mocked(driveServiceMock.Files.create).mock.calls[0][3], ).toBeDefined(); expect( ( - vi.mocked(driveServiceMock.Files.insert).mock + vi.mocked(driveServiceMock.Files.create).mock .calls[0][3] as InsertFileOptions ).supportsAllDrives, ).toBe(true); @@ -140,9 +140,9 @@ test("resolveDestinationFolder corretly creates new folder when set to merge fol vi.mocked(folderManagement).listFoldersInFolder_.mockReturnValueOnce([]); const driveServiceMock = mockedSafeDriveService(); - vi.mocked(driveServiceMock.Files.insert).mockReturnValueOnce({ + vi.mocked(driveServiceMock.Files.create).mockReturnValueOnce({ id: "NEWLY_CREATED_FOLDER_ID", - title: "FOLDER_NAME", + name: "FOLDER_NAME", }); const state = new MoveState_( @@ -158,7 +158,7 @@ test("resolveDestinationFolder corretly creates new folder when set to merge fol { capabilities: { canMoveItemOutOfDrive: true }, id: "SRC_FOLDER_ID", - title: "FOLDER_NAME", + name: "FOLDER_NAME", }, state, { @@ -169,24 +169,24 @@ test("resolveDestinationFolder corretly creates new folder when set to merge fol true, driveServiceMock, ), - ).toStrictEqual({ id: "NEWLY_CREATED_FOLDER_ID", title: "FOLDER_NAME" }); + ).toStrictEqual({ id: "NEWLY_CREATED_FOLDER_ID", name: "FOLDER_NAME" }); - expect(vi.mocked(driveServiceMock.Files.insert).mock.calls).toHaveLength(1); + expect(vi.mocked(driveServiceMock.Files.create).mock.calls).toHaveLength(1); expect( - vi.mocked(driveServiceMock.Files.insert).mock.calls[0][0].mimeType, + vi.mocked(driveServiceMock.Files.create).mock.calls[0][0].mimeType, ).toBe("application/vnd.google-apps.folder"); expect( - vi.mocked(driveServiceMock.Files.insert).mock.calls[0][0].parents, - ).toStrictEqual([{ id: "DEST_PARENT_ID" }]); - expect(vi.mocked(driveServiceMock.Files.insert).mock.calls[0][0].title).toBe( + vi.mocked(driveServiceMock.Files.create).mock.calls[0][0].parents, + ).toStrictEqual(["DEST_PARENT_ID"]); + expect(vi.mocked(driveServiceMock.Files.create).mock.calls[0][0].name).toBe( "FOLDER_NAME", ); expect( - vi.mocked(driveServiceMock.Files.insert).mock.calls[0][3], + vi.mocked(driveServiceMock.Files.create).mock.calls[0][3], ).toBeDefined(); expect( ( - vi.mocked(driveServiceMock.Files.insert).mock + vi.mocked(driveServiceMock.Files.create).mock .calls[0][3] as InsertFileOptions ).supportsAllDrives, ).toBe(true); @@ -198,17 +198,17 @@ test("resolveDestinationFolder corretly uses an existing folder when set to merg { capabilities: { canMoveItemOutOfDrive: true }, id: "EXISTING_WRONG_FOLDER1_ID", - title: "DIFFERENT_FOLDER_NAME1", + name: "DIFFERENT_FOLDER_NAME1", }, { capabilities: { canMoveItemOutOfDrive: true }, id: "EXISTING_FOLDER_ID", - title: "FOLDER_NAME", + name: "FOLDER_NAME", }, { capabilities: { canMoveItemOutOfDrive: true }, id: "EXISTING_WRONG_FOLDER2_ID", - title: "DIFFERENT_FOLDER_NAME2", + name: "DIFFERENT_FOLDER_NAME2", }, ]); const driveServiceMock = mockedSafeDriveService(); @@ -226,7 +226,7 @@ test("resolveDestinationFolder corretly uses an existing folder when set to merg { capabilities: { canMoveItemOutOfDrive: true }, id: "SRC_FOLDER_ID", - title: "FOLDER_NAME", + name: "FOLDER_NAME", }, state, { @@ -240,10 +240,10 @@ test("resolveDestinationFolder corretly uses an existing folder when set to merg ).toStrictEqual({ capabilities: { canMoveItemOutOfDrive: true }, id: "EXISTING_FOLDER_ID", - title: "FOLDER_NAME", + name: "FOLDER_NAME", }); - expect(vi.mocked(driveServiceMock.Files.insert).mock.calls).toHaveLength(0); + expect(vi.mocked(driveServiceMock.Files.create).mock.calls).toHaveLength(0); expect(vi.mocked(state).logError.mock.calls).toHaveLength(0); }); @@ -256,28 +256,28 @@ test("resolveDestinationFolder fails gracefully on multiple existing folders wit { capabilities: { canMoveItemOutOfDrive: true }, id: "EXISTING_WRONG_FOLDER1_ID", - title: "DIFFERENT_FOLDER_NAME1", + name: "DIFFERENT_FOLDER_NAME1", }, { capabilities: { canMoveItemOutOfDrive: true }, id: "EXISTING_FOLDER_ID1", - title: "FOLDER_NAME", + name: "FOLDER_NAME", }, { capabilities: { canMoveItemOutOfDrive: true }, id: "EXISTING_FOLDER_ID2", - title: "FOLDER_NAME", + name: "FOLDER_NAME", }, { capabilities: { canMoveItemOutOfDrive: true }, id: "EXISTING_WRONG_FOLDER2_ID", - title: "DIFFERENT_FOLDER_NAME2", + name: "DIFFERENT_FOLDER_NAME2", }, ]); const driveServiceMock = mockedSafeDriveService(); - vi.mocked(driveServiceMock.Files.insert).mockReturnValueOnce({ + vi.mocked(driveServiceMock.Files.create).mockReturnValueOnce({ id: "NEWLY_CREATED_FOLDER_ID", - title: "FOLDER_NAME", + name: "FOLDER_NAME", }); const state = new MoveState_( @@ -293,7 +293,7 @@ test("resolveDestinationFolder fails gracefully on multiple existing folders wit { capabilities: { canMoveItemOutOfDrive: true }, id: "SRC_FOLDER_ID", - title: "FOLDER_NAME", + name: "FOLDER_NAME", }, state, { @@ -306,25 +306,25 @@ test("resolveDestinationFolder fails gracefully on multiple existing folders wit ), ).toStrictEqual({ id: "NEWLY_CREATED_FOLDER_ID", - title: "FOLDER_NAME", + name: "FOLDER_NAME", }); - expect(vi.mocked(driveServiceMock.Files.insert).mock.calls).toHaveLength(1); + expect(vi.mocked(driveServiceMock.Files.create).mock.calls).toHaveLength(1); expect( - vi.mocked(driveServiceMock.Files.insert).mock.calls[0][0].mimeType, + vi.mocked(driveServiceMock.Files.create).mock.calls[0][0].mimeType, ).toBe("application/vnd.google-apps.folder"); expect( - vi.mocked(driveServiceMock.Files.insert).mock.calls[0][0].parents, - ).toStrictEqual([{ id: "DEST_PARENT_ID" }]); - expect(vi.mocked(driveServiceMock.Files.insert).mock.calls[0][0].title).toBe( + vi.mocked(driveServiceMock.Files.create).mock.calls[0][0].parents, + ).toStrictEqual(["DEST_PARENT_ID"]); + expect(vi.mocked(driveServiceMock.Files.create).mock.calls[0][0].name).toBe( "FOLDER_NAME", ); expect( - vi.mocked(driveServiceMock.Files.insert).mock.calls[0][3], + vi.mocked(driveServiceMock.Files.create).mock.calls[0][3], ).toBeDefined(); expect( ( - vi.mocked(driveServiceMock.Files.insert).mock + vi.mocked(driveServiceMock.Files.create).mock .calls[0][3] as InsertFileOptions ).supportsAllDrives, ).toBe(true); diff --git a/tests/backend/test-utils/SafeDriveService-stub.ts b/tests/backend/test-utils/SafeDriveService-stub.ts index b5d8df0d..77ec8e12 100644 --- a/tests/backend/test-utils/SafeDriveService-stub.ts +++ b/tests/backend/test-utils/SafeDriveService-stub.ts @@ -20,7 +20,7 @@ export function mockedSafeDriveService< // eslint-disable-next-line vitest/prefer-vi-mocked -- Acceptable as return value return { Comments: { - insert: + create: vi.fn< ( resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Comment, @@ -52,14 +52,7 @@ export function mockedSafeDriveService< optionalArgs?: { supportsAllDrives?: boolean }, ) => DeepPick >(), - get: vi.fn< - ( - fileId: string, - fields: F | null, - optionalArgs?: { alt?: string }, - ) => DeepPick - >(), - insert: vi.fn< + create: vi.fn< ( resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.File, fields: F | null, @@ -70,6 +63,13 @@ export function mockedSafeDriveService< }, ) => DeepPick >(), + get: vi.fn< + ( + fileId: string, + fields: F | null, + optionalArgs?: { alt?: string }, + ) => DeepPick + >(), list: vi.fn< ( fields: F | null, diff --git a/tests/backend/utils/DriveBackedValue.test.ts b/tests/backend/utils/DriveBackedValue.test.ts index 1dd959ea..f3eb9e06 100644 --- a/tests/backend/utils/DriveBackedValue.test.ts +++ b/tests/backend/utils/DriveBackedValue.test.ts @@ -43,14 +43,14 @@ test("DriveBackedValue saves a value - the folder exists, the value exists", () "BLOB" as unknown as GoogleAppsScript.Base.Blob, ); const response1 = { - items: [ + files: [ { id: "FOLDER_ID", }, ], }; const response2 = { - items: [ + files: [ { id: "FILE_ID", }, @@ -71,7 +71,7 @@ test("DriveBackedValue saves a value - the folder exists, the value exists", () vi.mocked(driveServiceMock.Files.list).mock .calls[0][1] as ListFilesOptions ).q, - ).toContain('title = "Shared drive mover cache"'); + ).toContain('name = "Shared drive mover cache"'); expect( ( vi.mocked(driveServiceMock.Files.list).mock @@ -96,7 +96,7 @@ test("DriveBackedValue saves a value - the folder exists, the value exists", () vi.mocked(driveServiceMock.Files.list).mock .calls[1][1] as ListFilesOptions ).q, - ).toContain(`title = "shared-drive-mover-state-${keySha256}.json"`); + ).toContain(`name = "shared-drive-mover-state-${keySha256}.json"`); expect( ( vi.mocked(driveServiceMock.Files.list).mock @@ -109,7 +109,7 @@ test("DriveBackedValue saves a value - the folder exists, the value exists", () .calls[1][1] as ListFilesOptions ).q, ).toContain("trashed = false"); - expect(vi.mocked(driveServiceMock.Files.insert).mock.calls).toHaveLength(0); + expect(vi.mocked(driveServiceMock.Files.create).mock.calls).toHaveLength(0); expect(vi.mocked(driveServiceMock.Files.update).mock.calls).toHaveLength(1); expect(vi.mocked(driveServiceMock.Files.update).mock.calls[0][1]).toBe( "FILE_ID", @@ -148,14 +148,14 @@ test("DriveBackedValue saves a value - the folder exists, the value doesn't", () "BLOB" as unknown as GoogleAppsScript.Base.Blob, ); const response1 = { - items: [ + files: [ { id: "FOLDER_ID", }, ], }; const response2 = { - items: [], + files: [], }; const driveServiceMock = mockedSafeDriveService(); vi.mocked(driveServiceMock.Files.list) @@ -172,7 +172,7 @@ test("DriveBackedValue saves a value - the folder exists, the value doesn't", () vi.mocked(driveServiceMock.Files.list).mock .calls[0][1] as ListFilesOptions ).q, - ).toContain('title = "Shared drive mover cache"'); + ).toContain('name = "Shared drive mover cache"'); expect( ( vi.mocked(driveServiceMock.Files.list).mock @@ -197,7 +197,7 @@ test("DriveBackedValue saves a value - the folder exists, the value doesn't", () vi.mocked(driveServiceMock.Files.list).mock .calls[1][1] as ListFilesOptions ).q, - ).toContain(`title = "shared-drive-mover-state-${keySha256}.json"`); + ).toContain(`name = "shared-drive-mover-state-${keySha256}.json"`); expect( ( vi.mocked(driveServiceMock.Files.list).mock @@ -210,17 +210,17 @@ test("DriveBackedValue saves a value - the folder exists, the value doesn't", () .calls[1][1] as ListFilesOptions ).q, ).toContain("trashed = false"); - expect(vi.mocked(driveServiceMock.Files.insert).mock.calls).toHaveLength(1); + expect(vi.mocked(driveServiceMock.Files.create).mock.calls).toHaveLength(1); expect( - vi.mocked(driveServiceMock.Files.insert).mock.calls[0][0].mimeType, + vi.mocked(driveServiceMock.Files.create).mock.calls[0][0].mimeType, ).toBe("application/json"); expect( - vi.mocked(driveServiceMock.Files.insert).mock.calls[0][0].parents, - ).toStrictEqual([{ id: "FOLDER_ID" }]); - expect(vi.mocked(driveServiceMock.Files.insert).mock.calls[0][0].title).toBe( + vi.mocked(driveServiceMock.Files.create).mock.calls[0][0].parents, + ).toStrictEqual(["FOLDER_ID"]); + expect(vi.mocked(driveServiceMock.Files.create).mock.calls[0][0].name).toBe( `shared-drive-mover-state-${keySha256}.json`, ); - expect(vi.mocked(driveServiceMock.Files.insert).mock.calls[0][2]).toBe( + expect(vi.mocked(driveServiceMock.Files.create).mock.calls[0][2]).toBe( "BLOB", ); expect(vi.mocked(global.Utilities).newBlob.mock.calls).toHaveLength(1); @@ -254,10 +254,10 @@ test("DriveBackedValue saves a value - the folder doesn't exists", () => { "BLOB" as unknown as GoogleAppsScript.Base.Blob, ); const response = { - items: [], + files: [], }; const driveServiceMock = mockedSafeDriveService(); - vi.mocked(driveServiceMock.Files.insert).mockReturnValueOnce({ + vi.mocked(driveServiceMock.Files.create).mockReturnValueOnce({ id: "FOLDER_ID", }); vi.mocked(driveServiceMock.Files.list) @@ -274,7 +274,7 @@ test("DriveBackedValue saves a value - the folder doesn't exists", () => { vi.mocked(driveServiceMock.Files.list).mock .calls[0][1] as ListFilesOptions ).q, - ).toContain('title = "Shared drive mover cache"'); + ).toContain('name = "Shared drive mover cache"'); expect( ( vi.mocked(driveServiceMock.Files.list).mock @@ -299,7 +299,7 @@ test("DriveBackedValue saves a value - the folder doesn't exists", () => { vi.mocked(driveServiceMock.Files.list).mock .calls[1][1] as ListFilesOptions ).q, - ).toContain(`title = "shared-drive-mover-state-${keySha256}.json"`); + ).toContain(`name = "shared-drive-mover-state-${keySha256}.json"`); expect( ( vi.mocked(driveServiceMock.Files.list).mock @@ -312,23 +312,23 @@ test("DriveBackedValue saves a value - the folder doesn't exists", () => { .calls[1][1] as ListFilesOptions ).q, ).toContain("trashed = false"); - expect(vi.mocked(driveServiceMock.Files.insert).mock.calls).toHaveLength(2); + expect(vi.mocked(driveServiceMock.Files.create).mock.calls).toHaveLength(2); expect( - vi.mocked(driveServiceMock.Files.insert).mock.calls[0][0].mimeType, + vi.mocked(driveServiceMock.Files.create).mock.calls[0][0].mimeType, ).toBe("application/vnd.google-apps.folder"); - expect(vi.mocked(driveServiceMock.Files.insert).mock.calls[0][0].title).toBe( + expect(vi.mocked(driveServiceMock.Files.create).mock.calls[0][0].name).toBe( "Shared drive mover cache", ); expect( - vi.mocked(driveServiceMock.Files.insert).mock.calls[1][0].mimeType, + vi.mocked(driveServiceMock.Files.create).mock.calls[1][0].mimeType, ).toBe("application/json"); expect( - vi.mocked(driveServiceMock.Files.insert).mock.calls[1][0].parents, - ).toStrictEqual([{ id: "FOLDER_ID" }]); - expect(vi.mocked(driveServiceMock.Files.insert).mock.calls[1][0].title).toBe( + vi.mocked(driveServiceMock.Files.create).mock.calls[1][0].parents, + ).toStrictEqual(["FOLDER_ID"]); + expect(vi.mocked(driveServiceMock.Files.create).mock.calls[1][0].name).toBe( `shared-drive-mover-state-${keySha256}.json`, ); - expect(vi.mocked(driveServiceMock.Files.insert).mock.calls[1][2]).toBe( + expect(vi.mocked(driveServiceMock.Files.create).mock.calls[1][2]).toBe( "BLOB", ); expect(vi.mocked(global.Utilities).newBlob.mock.calls).toHaveLength(1); @@ -363,14 +363,14 @@ test("DriveBackedValue loads a value - the folder exists, the value exists", () global.Utilities = mockedUtilities(); vi.mocked(global.Utilities).computeDigest.mockReturnValueOnce(keyEncoded); const response1 = { - items: [ + files: [ { id: "FOLDER_ID", }, ], }; const response2 = { - items: [ + files: [ { id: "FILE_ID", }, @@ -394,7 +394,7 @@ test("DriveBackedValue loads a value - the folder exists, the value exists", () vi.mocked(driveServiceMock.Files.list).mock .calls[0][1] as ListFilesOptions ).q, - ).toContain('title = "Shared drive mover cache"'); + ).toContain('name = "Shared drive mover cache"'); expect( ( vi.mocked(driveServiceMock.Files.list).mock @@ -419,7 +419,7 @@ test("DriveBackedValue loads a value - the folder exists, the value exists", () vi.mocked(driveServiceMock.Files.list).mock .calls[1][1] as ListFilesOptions ).q, - ).toContain(`title = "shared-drive-mover-state-${keySha256}.json"`); + ).toContain(`name = "shared-drive-mover-state-${keySha256}.json"`); expect( ( vi.mocked(driveServiceMock.Files.list).mock @@ -462,14 +462,14 @@ test("DriveBackedValue loads a value - the folder exists, the value doesn't", () global.Utilities = mockedUtilities(); vi.mocked(global.Utilities).computeDigest.mockReturnValueOnce(keyEncoded); const response1 = { - items: [ + files: [ { id: "FOLDER_ID", }, ], }; const response2 = { - items: [], + files: [], }; const driveServiceMock = mockedSafeDriveService(); vi.mocked(driveServiceMock.Files.list) @@ -486,7 +486,7 @@ test("DriveBackedValue loads a value - the folder exists, the value doesn't", () vi.mocked(driveServiceMock.Files.list).mock .calls[0][1] as ListFilesOptions ).q, - ).toContain('title = "Shared drive mover cache"'); + ).toContain('name = "Shared drive mover cache"'); expect( ( vi.mocked(driveServiceMock.Files.list).mock @@ -511,7 +511,7 @@ test("DriveBackedValue loads a value - the folder exists, the value doesn't", () vi.mocked(driveServiceMock.Files.list).mock .calls[1][1] as ListFilesOptions ).q, - ).toContain(`title = "shared-drive-mover-state-${keySha256}.json"`); + ).toContain(`name = "shared-drive-mover-state-${keySha256}.json"`); expect( ( vi.mocked(driveServiceMock.Files.list).mock @@ -544,7 +544,7 @@ test("DriveBackedValue loads a value - the folder doesn't exist", () => { global.Utilities = mockedUtilities(); vi.mocked(global.Utilities).computeDigest.mockReturnValueOnce(keyEncoded); const response1 = { - items: [], + files: [], }; const driveServiceMock = mockedSafeDriveService(); vi.mocked(driveServiceMock.Files.list).mockReturnValueOnce(response1); @@ -559,7 +559,7 @@ test("DriveBackedValue loads a value - the folder doesn't exist", () => { vi.mocked(driveServiceMock.Files.list).mock .calls[0][1] as ListFilesOptions ).q, - ).toContain('title = "Shared drive mover cache"'); + ).toContain('name = "Shared drive mover cache"'); expect( ( vi.mocked(driveServiceMock.Files.list).mock @@ -600,21 +600,21 @@ test("DriveBackedValue deletes a value - the folder exists, the value exists, th global.Utilities = mockedUtilities(); vi.mocked(global.Utilities).computeDigest.mockReturnValueOnce(keyEncoded); const response1 = { - items: [ + files: [ { id: "FOLDER_ID", }, ], }; const response2 = { - items: [ + files: [ { id: "FILE_ID", }, ], }; const response3 = { - items: [], + files: [], }; const driveServiceMock = mockedSafeDriveService(); vi.mocked(driveServiceMock.Files.list) @@ -632,7 +632,7 @@ test("DriveBackedValue deletes a value - the folder exists, the value exists, th vi.mocked(driveServiceMock.Files.list).mock .calls[0][1] as ListFilesOptions ).q, - ).toContain('title = "Shared drive mover cache"'); + ).toContain('name = "Shared drive mover cache"'); expect( ( vi.mocked(driveServiceMock.Files.list).mock @@ -657,7 +657,7 @@ test("DriveBackedValue deletes a value - the folder exists, the value exists, th vi.mocked(driveServiceMock.Files.list).mock .calls[1][1] as ListFilesOptions ).q, - ).toContain(`title = "shared-drive-mover-state-${keySha256}.json"`); + ).toContain(`name = "shared-drive-mover-state-${keySha256}.json"`); expect( ( vi.mocked(driveServiceMock.Files.list).mock @@ -711,21 +711,21 @@ test("DriveBackedValue deletes a value - the folder exists, the value exists, th global.Utilities = mockedUtilities(); vi.mocked(global.Utilities).computeDigest.mockReturnValueOnce(keyEncoded); const response1 = { - items: [ + files: [ { id: "FOLDER_ID", }, ], }; const response2 = { - items: [ + files: [ { id: "FILE_ID", }, ], }; const response3 = { - items: [ + files: [ { id: "OTHER_FILE_ID", }, @@ -747,7 +747,7 @@ test("DriveBackedValue deletes a value - the folder exists, the value exists, th vi.mocked(driveServiceMock.Files.list).mock .calls[0][1] as ListFilesOptions ).q, - ).toContain('title = "Shared drive mover cache"'); + ).toContain('name = "Shared drive mover cache"'); expect( ( vi.mocked(driveServiceMock.Files.list).mock @@ -772,7 +772,7 @@ test("DriveBackedValue deletes a value - the folder exists, the value exists, th vi.mocked(driveServiceMock.Files.list).mock .calls[1][1] as ListFilesOptions ).q, - ).toContain(`title = "shared-drive-mover-state-${keySha256}.json"`); + ).toContain(`name = "shared-drive-mover-state-${keySha256}.json"`); expect( ( vi.mocked(driveServiceMock.Files.list).mock @@ -823,17 +823,17 @@ test("DriveBackedValue deletes a value - the folder exists, the value doesn't, t global.Utilities = mockedUtilities(); vi.mocked(global.Utilities).computeDigest.mockReturnValueOnce(keyEncoded); const response1 = { - items: [ + files: [ { id: "FOLDER_ID", }, ], }; const response2 = { - items: [], + files: [], }; const response3 = { - items: [], + files: [], }; const driveServiceMock = mockedSafeDriveService(); vi.mocked(driveServiceMock.Files.list) @@ -851,7 +851,7 @@ test("DriveBackedValue deletes a value - the folder exists, the value doesn't, t vi.mocked(driveServiceMock.Files.list).mock .calls[0][1] as ListFilesOptions ).q, - ).toContain('title = "Shared drive mover cache"'); + ).toContain('name = "Shared drive mover cache"'); expect( ( vi.mocked(driveServiceMock.Files.list).mock @@ -876,7 +876,7 @@ test("DriveBackedValue deletes a value - the folder exists, the value doesn't, t vi.mocked(driveServiceMock.Files.list).mock .calls[1][1] as ListFilesOptions ).q, - ).toContain(`title = "shared-drive-mover-state-${keySha256}.json"`); + ).toContain(`name = "shared-drive-mover-state-${keySha256}.json"`); expect( ( vi.mocked(driveServiceMock.Files.list).mock @@ -927,17 +927,17 @@ test("DriveBackedValue deletes a value - the folder exists, the value doesn't, t global.Utilities = mockedUtilities(); vi.mocked(global.Utilities).computeDigest.mockReturnValueOnce(keyEncoded); const response1 = { - items: [ + files: [ { id: "FOLDER_ID", }, ], }; const response2 = { - items: [], + files: [], }; const response3 = { - items: [ + files: [ { id: "OTHER_FILE_ID", }, @@ -959,7 +959,7 @@ test("DriveBackedValue deletes a value - the folder exists, the value doesn't, t vi.mocked(driveServiceMock.Files.list).mock .calls[0][1] as ListFilesOptions ).q, - ).toContain('title = "Shared drive mover cache"'); + ).toContain('name = "Shared drive mover cache"'); expect( ( vi.mocked(driveServiceMock.Files.list).mock @@ -984,7 +984,7 @@ test("DriveBackedValue deletes a value - the folder exists, the value doesn't, t vi.mocked(driveServiceMock.Files.list).mock .calls[1][1] as ListFilesOptions ).q, - ).toContain(`title = "shared-drive-mover-state-${keySha256}.json"`); + ).toContain(`name = "shared-drive-mover-state-${keySha256}.json"`); expect( ( vi.mocked(driveServiceMock.Files.list).mock @@ -1030,7 +1030,7 @@ test("DriveBackedValue deletes a value - the folder doesn't exist", () => { global.Utilities = mockedUtilities(); vi.mocked(global.Utilities).computeDigest.mockReturnValueOnce(keyEncoded); const response = { - items: [], + files: [], }; const driveServiceMock = mockedSafeDriveService(); vi.mocked(driveServiceMock.Files.list).mockReturnValueOnce(response); @@ -1045,7 +1045,7 @@ test("DriveBackedValue deletes a value - the folder doesn't exist", () => { vi.mocked(driveServiceMock.Files.list).mock .calls[0][1] as ListFilesOptions ).q, - ).toContain('title = "Shared drive mover cache"'); + ).toContain('name = "Shared drive mover cache"'); expect( ( vi.mocked(driveServiceMock.Files.list).mock diff --git a/tests/backend/utils/SafeDriveService.test.ts b/tests/backend/utils/SafeDriveService.test.ts index 02140872..04e4995c 100644 --- a/tests/backend/utils/SafeDriveService.test.ts +++ b/tests/backend/utils/SafeDriveService.test.ts @@ -22,55 +22,3 @@ test("SafeDriveService constructs correctly", () => { new SafeDriveService_(); }).not.toThrow(); }); - -test("SafeDriveService throws an error without the Comments collection", () => { - global.Drive = { - ...mockedDrive(), - Drives: mockedDrivesCollection(), - Files: mockedFilesCollection(), - Replies: mockedRepliesCollection(), - }; - - expect(() => { - new SafeDriveService_(); - }).toThrow(""); -}); - -test("SafeDriveService throws an error without the Drives collection", () => { - global.Drive = { - ...mockedDrive(), - Comments: mockedCommentsCollection(), - Files: mockedFilesCollection(), - Replies: mockedRepliesCollection(), - }; - - expect(() => { - new SafeDriveService_(); - }).toThrow(""); -}); - -test("SafeDriveService throws an error without the Files collection", () => { - global.Drive = { - ...mockedDrive(), - Comments: mockedCommentsCollection(), - Drives: mockedDrivesCollection(), - Replies: mockedRepliesCollection(), - }; - - expect(() => { - new SafeDriveService_(); - }).toThrow(""); -}); - -test("SafeDriveService throws an error without the Replies collection", () => { - global.Drive = { - ...mockedDrive(), - Comments: mockedCommentsCollection(), - Drives: mockedDrivesCollection(), - Files: mockedFilesCollection(), - }; - - expect(() => { - new SafeDriveService_(); - }).toThrow(""); -}); diff --git a/tests/backend/utils/SafeDriveService/SafeCommentsCollection.test.ts b/tests/backend/utils/SafeDriveService/SafeCommentsCollection.test.ts index fa06f991..35791ffe 100644 --- a/tests/backend/utils/SafeDriveService/SafeCommentsCollection.test.ts +++ b/tests/backend/utils/SafeDriveService/SafeCommentsCollection.test.ts @@ -17,96 +17,86 @@ test("SafeCommentsCollection constructs correctly", () => { }).not.toThrow(); }); -test("SafeCommentsCollection throws an error without the Comments collection", () => { - global.Drive = { - ...mockedDrive(), - }; - - expect(() => { - new SafeCommentsCollection_(); - }).toThrow(""); -}); - -test("insert works", () => { +test("create works", () => { const comment = { author: { displayName: "COMMENT_AUTHOR", - isAuthenticatedUser: false, + me: false, }, - commentId: "COMMENT1", content: "COMMENT_CONTENT", + id: "COMMENT1", replies: [ { author: { displayName: "REPLY_AUTHOR", - isAuthenticatedUser: false, + me: false, }, content: "REPLY_CONTENT", }, ], }; - global.Drive.Comments = mockedCommentsCollection(); - const insert = vi + global.Drive = mockedDrive(); + const create = vi .mocked(global.Drive.Comments) - .insert.mockReturnValueOnce(comment); + .create.mockReturnValueOnce(comment); const commentsCollection = new SafeCommentsCollection_(); - expect(commentsCollection.insert(comment, "FILE_ID")).toStrictEqual(comment); + expect(commentsCollection.create(comment, "FILE_ID")).toStrictEqual(comment); - expect(insert.mock.calls).toHaveLength(1); - expect(insert.mock.calls[0][0]).toBe(comment); - expect(insert.mock.calls[0][1]).toBe("FILE_ID"); + expect(create.mock.calls).toHaveLength(1); + expect(create.mock.calls[0][0]).toBe(comment); + expect(create.mock.calls[0][1]).toBe("FILE_ID"); }); -test("insert throws an error on an invalid comment", () => { +test("create throws an error on an invalid comment", () => { const comment = { author: { displayName: "COMMENT_AUTHOR", - isAuthenticatedUser: false, + me: false, }, - commentId: "COMMENT1", + id: "COMMENT1", replies: [ { author: { displayName: "REPLY_AUTHOR", - isAuthenticatedUser: false, + me: false, }, content: "REPLY_CONTENT", }, ], }; - global.Drive.Comments = mockedCommentsCollection(); - const insert = vi + global.Drive = mockedDrive(); + const create = vi .mocked(global.Drive.Comments) - .insert.mockReturnValueOnce(comment); + .create.mockReturnValueOnce(comment); const commentsCollection = new SafeCommentsCollection_(); - expect(() => commentsCollection.insert(comment, "FILE_ID")).toThrow(""); + expect(() => commentsCollection.create(comment, "FILE_ID")).toThrow(""); - expect(insert.mock.calls).toHaveLength(1); - expect(insert.mock.calls[0][0]).toBe(comment); - expect(insert.mock.calls[0][1]).toBe("FILE_ID"); + expect(create.mock.calls).toHaveLength(1); + expect(create.mock.calls[0][0]).toBe(comment); + expect(create.mock.calls[0][1]).toBe("FILE_ID"); }); test("list works", () => { const commentList = { - items: [ + comments: [ { author: { displayName: "COMMENT1_AUTHOR", - isAuthenticatedUser: false, + me: false, }, - commentId: "COMMENT1", content: "COMMENT1_CONTENT", + id: "COMMENT1", replies: [ { author: { displayName: "REPLY_AUTHOR", - isAuthenticatedUser: false, + me: false, }, content: "REPLY1_CONTENT", }, @@ -115,15 +105,15 @@ test("list works", () => { { author: { displayName: "COMMENT1_AUTHOR", - isAuthenticatedUser: false, + me: false, }, - commentId: "COMMENT2", content: "COMMENT2_CONTENT", + id: "COMMENT2", replies: [ { author: { displayName: "REPLY_AUTHOR", - isAuthenticatedUser: false, + me: false, }, content: "REPLY2_CONTENT", }, @@ -132,7 +122,7 @@ test("list works", () => { ], }; - global.Drive.Comments = mockedCommentsCollection(); + global.Drive = mockedDrive(); const list = vi .mocked(global.Drive.Comments) .list.mockReturnValueOnce(commentList); @@ -148,19 +138,19 @@ test("list works", () => { test("list works with optional arguments", () => { const commentList = { - items: [ + comments: [ { author: { displayName: "COMMENT1_AUTHOR", - isAuthenticatedUser: false, + me: false, }, - commentId: "COMMENT1", content: "COMMENT1_CONTENT", + id: "COMMENT1", replies: [ { author: { displayName: "REPLY_AUTHOR", - isAuthenticatedUser: false, + me: false, }, content: "REPLY1_CONTENT", }, @@ -169,15 +159,15 @@ test("list works with optional arguments", () => { { author: { displayName: "COMMENT1_AUTHOR", - isAuthenticatedUser: false, + me: false, }, - commentId: "COMMENT2", content: "COMMENT2_CONTENT", + id: "COMMENT2", replies: [ { author: { displayName: "REPLY_AUTHOR", - isAuthenticatedUser: false, + me: false, }, content: "REPLY2_CONTENT", }, @@ -186,7 +176,7 @@ test("list works with optional arguments", () => { ], }; - global.Drive.Comments = mockedCommentsCollection(); + global.Drive = mockedDrive(); const list = vi .mocked(global.Drive.Comments) .list.mockReturnValueOnce(commentList); @@ -194,7 +184,7 @@ test("list works with optional arguments", () => { const commentsCollection = new SafeCommentsCollection_(); const optionalArgs = { - fields: "items(id)", + fields: "comments(id)", maxResults: 100, pageToken: "TOKEN", }; @@ -210,18 +200,18 @@ test("list works with optional arguments", () => { test("list throws an error on an invalid comment", () => { const commentList = { - items: [ + comments: [ { author: { displayName: "COMMENT1_AUTHOR", - isAuthenticatedUser: false, + me: false, }, - commentId: "COMMENT1", + id: "COMMENT1", replies: [ { author: { displayName: "REPLY_AUTHOR", - isAuthenticatedUser: false, + me: false, }, content: "REPLY1_CONTENT", }, @@ -230,15 +220,15 @@ test("list throws an error on an invalid comment", () => { { author: { displayName: "COMMENT1_AUTHOR", - isAuthenticatedUser: false, + me: false, }, - commentId: "COMMENT2", content: "COMMENT2_CONTENT", + id: "COMMENT2", replies: [ { author: { displayName: "REPLY_AUTHOR", - isAuthenticatedUser: false, + me: false, }, content: "REPLY2_CONTENT", }, @@ -247,7 +237,7 @@ test("list throws an error on an invalid comment", () => { ], }; - global.Drive.Comments = mockedCommentsCollection(); + global.Drive = mockedDrive(); const list = vi .mocked(global.Drive.Comments) .list.mockReturnValueOnce(commentList); @@ -266,7 +256,7 @@ test("list throws an error on an invalid comment list", () => { nextPageToken: "TOKEN", }; - global.Drive.Comments = mockedCommentsCollection(); + global.Drive = mockedDrive(); const list = vi .mocked(global.Drive.Comments) .list.mockReturnValueOnce(commentList); @@ -282,27 +272,27 @@ test("list throws an error on an invalid comment list", () => { test("list throws an error on missing replies", () => { const commentList = { - items: [ + comments: [ { author: { displayName: "COMMENT1_AUTHOR", - isAuthenticatedUser: false, + me: false, }, - commentId: "COMMENT1", content: "COMMENT1_CONTENT", + id: "COMMENT1", }, { author: { displayName: "COMMENT1_AUTHOR", - isAuthenticatedUser: false, + me: false, }, - commentId: "COMMENT2", content: "COMMENT2_CONTENT", + id: "COMMENT2", replies: [ { author: { displayName: "REPLY_AUTHOR", - isAuthenticatedUser: false, + me: false, }, content: "REPLY2_CONTENT", }, @@ -311,7 +301,7 @@ test("list throws an error on missing replies", () => { ], }; - global.Drive.Comments = mockedCommentsCollection(); + global.Drive = mockedDrive(); const list = vi .mocked(global.Drive.Comments) .list.mockReturnValueOnce(commentList); @@ -327,19 +317,19 @@ test("list throws an error on missing replies", () => { test("list throws an error on an invalid reply", () => { const commentList = { - items: [ + comments: [ { author: { displayName: "COMMENT1_AUTHOR", - isAuthenticatedUser: false, + me: false, }, - commentId: "COMMENT1", content: "COMMENT1_CONTENT", + id: "COMMENT1", replies: [ { author: { displayName: "REPLY_AUTHOR", - isAuthenticatedUser: false, + me: false, }, }, ], @@ -347,15 +337,15 @@ test("list throws an error on an invalid reply", () => { { author: { displayName: "COMMENT1_AUTHOR", - isAuthenticatedUser: false, + me: false, }, - commentId: "COMMENT2", content: "COMMENT2_CONTENT", + id: "COMMENT2", replies: [ { author: { displayName: "REPLY_AUTHOR", - isAuthenticatedUser: false, + me: false, }, content: "REPLY2_CONTENT", }, @@ -364,7 +354,7 @@ test("list throws an error on an invalid reply", () => { ], }; - global.Drive.Comments = mockedCommentsCollection(); + global.Drive = mockedDrive(); const list = vi .mocked(global.Drive.Comments) .list.mockReturnValueOnce(commentList); diff --git a/tests/backend/utils/SafeDriveService/SafeDrivesCollection.test.ts b/tests/backend/utils/SafeDriveService/SafeDrivesCollection.test.ts index 048f6f42..91009210 100644 --- a/tests/backend/utils/SafeDriveService/SafeDrivesCollection.test.ts +++ b/tests/backend/utils/SafeDriveService/SafeDrivesCollection.test.ts @@ -17,19 +17,9 @@ test("SafeDrivesCollection constructs correctly", () => { }).not.toThrow(); }); -test("SafeDrivesCollection throws an error without the Drives collection", () => { - global.Drive = { - ...mockedDrive(), - }; - - expect(() => { - new SafeDrivesCollection_(); - }).toThrow(""); -}); - test("list works", () => { const driveList = { - items: [ + drives: [ { id: "DRIVE1", name: "DRIVE1_NAME", @@ -41,7 +31,7 @@ test("list works", () => { ], }; - global.Drive.Drives = mockedDrivesCollection(); + global.Drive = mockedDrive(); const list = vi .mocked(global.Drive.Drives) .list.mockReturnValueOnce(driveList); @@ -56,7 +46,7 @@ test("list works", () => { test("list works with optional parameters", () => { const driveList = { - items: [ + drives: [ { id: "DRIVE1", name: "DRIVE1_NAME", @@ -68,7 +58,7 @@ test("list works with optional parameters", () => { ], }; - global.Drive.Drives = mockedDrivesCollection(); + global.Drive = mockedDrive(); const list = vi .mocked(global.Drive.Drives) .list.mockReturnValueOnce(driveList); @@ -89,7 +79,7 @@ test("list works with optional parameters", () => { test("list works with selective fields", () => { const driveList1 = { - items: [ + drives: [ { name: "DRIVE1_NAME", }, @@ -99,7 +89,7 @@ test("list works with selective fields", () => { ], }; const driveList2 = { - items: [ + drives: [ { id: "DRIVE1", name: "DRIVE1_NAME", @@ -111,7 +101,7 @@ test("list works with selective fields", () => { ], }; - global.Drive.Drives = mockedDrivesCollection(); + global.Drive = mockedDrive(); const list = vi .mocked(global.Drive.Drives) .list.mockReturnValueOnce(driveList1) @@ -126,16 +116,16 @@ test("list works with selective fields", () => { expect(list.mock.calls).toHaveLength(2); expect(list.mock.calls[0][0]).toStrictEqual({ - fields: "nextPageToken, items(name)", + fields: "nextPageToken, drives(name)", }); expect(list.mock.calls[1][0]).toStrictEqual({ - fields: "nextPageToken, items(id, name)", + fields: "nextPageToken, drives(id, name)", }); }); test("list throws an error on an invalid drive", () => { const driveList = { - items: [ + drives: [ { name: "DRIVE1_NAME", }, @@ -145,7 +135,7 @@ test("list throws an error on an invalid drive", () => { ], }; - global.Drive.Drives = mockedDrivesCollection(); + global.Drive = mockedDrive(); const list = vi .mocked(global.Drive.Drives) .list.mockReturnValueOnce(driveList); diff --git a/tests/backend/utils/SafeDriveService/SafeFilesCollection.test.ts b/tests/backend/utils/SafeDriveService/SafeFilesCollection.test.ts index 4c950c37..2dd1153d 100644 --- a/tests/backend/utils/SafeDriveService/SafeFilesCollection.test.ts +++ b/tests/backend/utils/SafeDriveService/SafeFilesCollection.test.ts @@ -14,27 +14,15 @@ test("SafeFilesCollection constructs correctly", () => { }).not.toThrow(); }); -test("SafeFilesCollection throws an error without the Files collection", () => { - global.Drive = { - ...mockedDrive(), - }; - - expect(() => { - new SafeFilesCollection_(); - }).toThrow(""); -}); - test("copy works", () => { const file = { capabilities: { + canDelete: false, canMoveItemOutOfDrive: true, }, id: "FILE_ID", mimeType: "text/plain", - title: "FILE_TITLE", - userPermission: { - role: "reader" as const, - }, + name: "FILE_TITLE", }; global.Drive.Files = mockedFilesCollection(); @@ -53,14 +41,12 @@ test("copy works", () => { test("copy works with optional arguments", () => { const file = { capabilities: { + canDelete: false, canMoveItemOutOfDrive: true, }, id: "FILE_ID", mimeType: "text/plain", - title: "FILE_TITLE", - userPermission: { - role: "reader" as const, - }, + name: "FILE_TITLE", }; global.Drive.Files = mockedFilesCollection(); @@ -111,12 +97,12 @@ test("copy works with selective fields", () => { test("copy throws and error on invalid file", () => { const file = { + capabilities: { + canDelete: false, + }, id: "FILE_ID", mimeType: "text/plain", - title: "FILE_TITLE", - userPermission: { - role: "reader" as const, - }, + name: "FILE_TITLE", }; global.Drive.Files = mockedFilesCollection(); @@ -135,14 +121,12 @@ test("copy throws and error on invalid file", () => { test("get works", () => { const file = { capabilities: { + canDelete: false, canMoveItemOutOfDrive: true, }, id: "FILE_ID", mimeType: "text/plain", - title: "FILE_TITLE", - userPermission: { - role: "reader" as const, - }, + name: "FILE_TITLE", }; global.Drive.Files = mockedFilesCollection(); @@ -160,14 +144,12 @@ test("get works", () => { test("get works with optional arguments", () => { const file = { capabilities: { + canDelete: false, canMoveItemOutOfDrive: true, }, id: "FILE_ID", mimeType: "text/plain", - title: "FILE_TITLE", - userPermission: { - role: "reader" as const, - }, + name: "FILE_TITLE", }; global.Drive.Files = mockedFilesCollection(); @@ -185,7 +167,7 @@ test("get works with optional arguments", () => { test("get works with selective fields", () => { const file = { id: "FILE_ID", - title: "FILE_TITLE", + name: "FILE_TITLE", }; global.Drive.Files = mockedFilesCollection(); @@ -193,23 +175,21 @@ test("get works with selective fields", () => { const filesCollection = new SafeFilesCollection_(); - expect(filesCollection.get("FILE_ID", { id: true, title: true })).toBe(file); + expect(filesCollection.get("FILE_ID", { id: true, name: true })).toBe(file); expect(get.mock.calls).toHaveLength(1); expect(get.mock.calls[0][0]).toBe("FILE_ID"); - expect(get.mock.calls[0][1]).toStrictEqual({ fields: "id, title" }); + expect(get.mock.calls[0][1]).toStrictEqual({ fields: "id, name" }); }); test("get throws an error on invalid file", () => { const file = { capabilities: { + canDelete: false, canMoveItemOutOfDrive: true, }, id: "FILE_ID", - title: "FILE_TITLE", - userPermission: { - role: "reader" as const, - }, + name: "FILE_TITLE", }; global.Drive.Files = mockedFilesCollection(); @@ -224,136 +204,127 @@ test("get throws an error on invalid file", () => { expect(get.mock.calls[0][1]).toStrictEqual({}); }); -test("insert works", () => { +test("create works", () => { const file = { capabilities: { + canDelete: false, canMoveItemOutOfDrive: true, }, id: "FILE_ID", mimeType: "text/plain", - title: "FILE_TITLE", - userPermission: { - role: "reader" as const, - }, + name: "FILE_TITLE", }; global.Drive.Files = mockedFilesCollection(); - const insert = vi.mocked(global.Drive.Files).insert.mockReturnValueOnce(file); + const create = vi.mocked(global.Drive.Files).create.mockReturnValueOnce(file); const filesCollection = new SafeFilesCollection_(); - expect(filesCollection.insert(file, null)).toBe(file); + expect(filesCollection.create(file, null)).toBe(file); - expect(insert.mock.calls).toHaveLength(1); - expect(insert.mock.calls[0][0]).toBe(file); - expect(insert.mock.calls[0][1]).toBeUndefined(); - expect(insert.mock.calls[0][2]).toStrictEqual({}); + expect(create.mock.calls).toHaveLength(1); + expect(create.mock.calls[0][0]).toBe(file); + expect(create.mock.calls[0][1]).toBeUndefined(); + expect(create.mock.calls[0][2]).toStrictEqual({}); }); -test("insert works with optional arguments", () => { +test("create works with optional arguments", () => { const file = { capabilities: { + canDelete: false, canMoveItemOutOfDrive: true, }, id: "FILE_ID", mimeType: "text/plain", - title: "FILE_TITLE", - userPermission: { - role: "reader" as const, - }, + name: "FILE_TITLE", }; global.Drive.Files = mockedFilesCollection(); - const insert = vi.mocked(global.Drive.Files).insert.mockReturnValueOnce(file); + const create = vi.mocked(global.Drive.Files).create.mockReturnValueOnce(file); const filesCollection = new SafeFilesCollection_(); expect( - filesCollection.insert(file, null, undefined, { supportsAllDrives: true }), + filesCollection.create(file, null, undefined, { supportsAllDrives: true }), ).toBe(file); - expect(insert.mock.calls).toHaveLength(1); - expect(insert.mock.calls[0][0]).toBe(file); - expect(insert.mock.calls[0][1]).toBeUndefined(); - expect(insert.mock.calls[0][2]).toStrictEqual({ supportsAllDrives: true }); + expect(create.mock.calls).toHaveLength(1); + expect(create.mock.calls[0][0]).toBe(file); + expect(create.mock.calls[0][1]).toBeUndefined(); + expect(create.mock.calls[0][2]).toStrictEqual({ supportsAllDrives: true }); }); -test("insert works with selective fields", () => { +test("create works with selective fields", () => { const file = { - title: "FILE_TITLE", - userPermission: { - role: "reader" as const, + capabilities: { + canDelete: false, }, + name: "FILE_TITLE", }; global.Drive.Files = mockedFilesCollection(); - const insert = vi.mocked(global.Drive.Files).insert.mockReturnValueOnce(file); + const create = vi.mocked(global.Drive.Files).create.mockReturnValueOnce(file); const filesCollection = new SafeFilesCollection_(); expect( - filesCollection.insert(file, { - title: true, - userPermission: { role: true }, + filesCollection.create(file, { + capabilities: { canDelete: true }, + name: true, }), ).toBe(file); - expect(insert.mock.calls).toHaveLength(1); - expect(insert.mock.calls[0][0]).toBe(file); - expect(insert.mock.calls[0][1]).toBeUndefined(); - expect(insert.mock.calls[0][2]).toStrictEqual({ - fields: "title, userPermission(role)", + expect(create.mock.calls).toHaveLength(1); + expect(create.mock.calls[0][0]).toBe(file); + expect(create.mock.calls[0][1]).toBeUndefined(); + expect(create.mock.calls[0][2]).toStrictEqual({ + fields: "capabilities(canDelete), name", }); }); -test("insert throws an error on invalid file", () => { +test("create throws an error on invalid file", () => { const file = { capabilities: { canMoveItemOutOfDrive: true, }, id: "FILE_ID", mimeType: "text/plain", - title: "FILE_TITLE", - userPermission: {}, + name: "FILE_TITLE", }; global.Drive.Files = mockedFilesCollection(); - const insert = vi.mocked(global.Drive.Files).insert.mockReturnValueOnce(file); + const create = vi.mocked(global.Drive.Files).create.mockReturnValueOnce(file); const filesCollection = new SafeFilesCollection_(); - expect(() => filesCollection.insert(file, null)).toThrow(""); + expect(() => filesCollection.create(file, null)).toThrow(""); - expect(insert.mock.calls).toHaveLength(1); - expect(insert.mock.calls[0][0]).toBe(file); - expect(insert.mock.calls[0][1]).toBeUndefined(); - expect(insert.mock.calls[0][2]).toStrictEqual({}); + expect(create.mock.calls).toHaveLength(1); + expect(create.mock.calls[0][0]).toBe(file); + expect(create.mock.calls[0][1]).toBeUndefined(); + expect(create.mock.calls[0][2]).toStrictEqual({}); }); test("list works", () => { const fileList = { - items: [ + files: [ { capabilities: { + canDelete: false, canMoveItemOutOfDrive: true, }, id: "FILE1_ID", mimeType: "text/plain", - title: "FILE1_TITLE", - userPermission: { - role: "reader" as const, - }, + name: "FILE1_TITLE", }, { capabilities: { + canDelete: true, canMoveItemOutOfDrive: false, }, id: "FILE2_ID", mimeType: "text/html", - title: "FILE2_TITLE", - userPermission: { - role: "owner" as const, - }, + name: "FILE2_TITLE", }, ], }; @@ -371,28 +342,24 @@ test("list works", () => { test("list works with optional arguments", () => { const fileList = { - items: [ + files: [ { capabilities: { + canDelete: false, canMoveItemOutOfDrive: true, }, id: "FILE1_ID", mimeType: "text/plain", - title: "FILE1_TITLE", - userPermission: { - role: "reader" as const, - }, + name: "FILE1_TITLE", }, { capabilities: { + canDelete: true, canMoveItemOutOfDrive: false, }, id: "FILE2_ID", mimeType: "text/html", - title: "FILE2_TITLE", - userPermission: { - role: "owner" as const, - }, + name: "FILE2_TITLE", }, ], }; @@ -418,7 +385,7 @@ test("list works with optional arguments", () => { test("list works with selective fields", () => { const fileList = { - items: [ + files: [ { capabilities: { canMoveItemOutOfDrive: true, @@ -448,13 +415,13 @@ test("list works with selective fields", () => { expect(list.mock.calls).toHaveLength(1); expect(list.mock.calls[0][0]).toStrictEqual({ - fields: "nextPageToken, items(capabilities(canMoveItemOutOfDrive), id)", + fields: "nextPageToken, files(capabilities(canMoveItemOutOfDrive), id)", }); }); test("list throws an error on invalid file", () => { const fileList = { - items: [ + files: [ { capabilities: { canMoveItemOutOfDrive: true, @@ -463,14 +430,12 @@ test("list throws an error on invalid file", () => { }, { capabilities: { + canDelete: true, canMoveItemOutOfDrive: false, }, id: "FILE2_ID", mimeType: "text/html", - title: "FILE2_TITLE", - userPermission: { - role: "owner" as const, - }, + name: "FILE2_TITLE", }, ], }; @@ -518,14 +483,12 @@ test("remove works", () => { test("update works", () => { const file = { capabilities: { + canDelete: false, canMoveItemOutOfDrive: true, }, id: "FILE_ID", mimeType: "text/plain", - title: "FILE_TITLE", - userPermission: { - role: "reader" as const, - }, + name: "FILE_TITLE", }; global.Drive.Files = mockedFilesCollection(); @@ -545,14 +508,12 @@ test("update works", () => { test("update works with optional arguments", () => { const file = { capabilities: { + canDelete: false, canMoveItemOutOfDrive: true, }, id: "FILE_ID", mimeType: "text/plain", - title: "FILE_TITLE", - userPermission: { - role: "reader" as const, - }, + name: "FILE_TITLE", }; global.Drive.Files = mockedFilesCollection(); From 4124254518fdfe27c309e954e93b7c267ac798a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20D=C4=9Bdi=C4=8D?= Date: Sun, 29 Dec 2024 15:51:12 +0100 Subject: [PATCH 5/9] Always mocking whole Drive in tests --- tests/backend/test-utils/gas-stubs.ts | 316 +++++++++--------- tests/backend/utils/SafeDriveService.test.ts | 16 +- .../SafeCommentsCollection.test.ts | 10 +- .../SafeDrivesCollection.test.ts | 12 +- .../SafeFilesCollection.test.ts | 51 ++- 5 files changed, 191 insertions(+), 214 deletions(-) diff --git a/tests/backend/test-utils/gas-stubs.ts b/tests/backend/test-utils/gas-stubs.ts index 70c43e9b..0a236b8a 100644 --- a/tests/backend/test-utils/gas-stubs.ts +++ b/tests/backend/test-utils/gas-stubs.ts @@ -1,38 +1,6 @@ import { vi } from "vitest"; -export function mockedCommentsCollection(): GoogleAppsScript.Drive_v3.Drive.V3.Collection.CommentsCollection { - return { - create: - vi.fn< - ( - resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Comment, - fileId: string, - ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Comment - >(), - get: vi.fn< - ( - fileId: string, - commentId: string, - optionalArgs?: Record, - ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Comment - >(), - list: vi.fn< - ( - fileId: string, - optionalArgs?: Record, - ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.CommentList - >(), - remove: vi.fn<(fileId: string, commentId: string) => void>(), - update: - vi.fn< - ( - resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Comment, - fileId: string, - commentId: string, - ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Comment - >(), - }; -} +/* eslint-disable @typescript-eslint/no-explicit-any -- These are stubs for external functions */ export function mockedDrive(): GoogleAppsScript.Drive { return { @@ -149,129 +117,6 @@ export function mockedDrive(): GoogleAppsScript.Drive { }; } -export function mockedDrivesCollection(): GoogleAppsScript.Drive_v3.Drive.V3.Collection.DrivesCollection { - return { - create: - vi.fn< - ( - resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Drive, - requestId: string, - ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Drive - >(), - get: vi.fn< - ( - driveId: string, - optionalArgs?: Record, - ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Drive - >(), - hide: vi.fn< - (driveId: string) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Drive - >(), - list: vi.fn< - ( - optionalArgs?: Record, - ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.DriveList - >(), - remove: - vi.fn<(driveId: string, optionalArgs?: Record) => void>(), - unhide: - vi.fn< - (driveId: string) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Drive - >(), - update: - vi.fn< - ( - resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Drive, - driveId: string, - optionalArgs?: Record, - ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Drive - >(), - }; -} - -export function mockedFilesCollection(): GoogleAppsScript.Drive_v3.Drive.V3.Collection.FilesCollection { - return { - copy: vi.fn< - ( - resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.File, - fileId: string, - optionalArgs?: Record, - ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.File - >(), - create: - vi.fn< - ( - resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.File, - mediaData?: GoogleAppsScript.Base.Blob, - optionalArgs?: Record, - ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.File - >(), - download: - vi.fn< - ( - fileId: string, - optionalArgs?: Record, - ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Operation - >(), - emptyTrash: vi.fn<(optionalArgs?: Record) => void>(), - export: vi.fn<(fileId: string, mimeType: string) => void>(), - generateIds: - vi.fn< - ( - optionalArgs?: Record, - ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.GeneratedIds - >(), - get: vi.fn() as { - ( - fileId: string, - optionalArgs?: Record & { alt: "media" }, - ): string; - ( - fileId: string, - optionalArgs?: Record, - ): GoogleAppsScript.Drive_v3.Drive.V3.Schema.File; - }, - list: vi.fn< - ( - optionalArgs?: Record, - ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.FileList - >(), - listLabels: - vi.fn< - ( - fileId: string, - optionalArgs?: Record, - ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.LabelList - >(), - modifyLabels: - vi.fn< - ( - resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.ModifyLabelsRequest, - fileId: string, - ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.ModifyLabelsResponse - >(), - remove: - vi.fn<(fileId: string, optionalArgs?: Record) => void>(), - update: - vi.fn< - ( - resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.File, - fileId: string, - mediaData?: GoogleAppsScript.Base.Blob, - optionalArgs?: Record, - ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.File - >(), - watch: - vi.fn< - ( - resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Channel, - fileId: string, - optionalArgs?: Record, - ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Channel - >(), - }; -} - export function mockedHtmlOutput(): GoogleAppsScript.HTML.HtmlOutput { return { addMetaTag: @@ -602,6 +447,163 @@ function mockedChannelsCollection(): GoogleAppsScript.Drive_v3.Drive.V3.Collecti }; } +function mockedCommentsCollection(): GoogleAppsScript.Drive_v3.Drive.V3.Collection.CommentsCollection { + return { + create: + vi.fn< + ( + resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Comment, + fileId: string, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Comment + >(), + get: vi.fn< + ( + fileId: string, + commentId: string, + optionalArgs?: Record, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Comment + >(), + list: vi.fn< + ( + fileId: string, + optionalArgs?: Record, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.CommentList + >(), + remove: vi.fn<(fileId: string, commentId: string) => void>(), + update: + vi.fn< + ( + resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Comment, + fileId: string, + commentId: string, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Comment + >(), + }; +} + +function mockedDrivesCollection(): GoogleAppsScript.Drive_v3.Drive.V3.Collection.DrivesCollection { + return { + create: + vi.fn< + ( + resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Drive, + requestId: string, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Drive + >(), + get: vi.fn< + ( + driveId: string, + optionalArgs?: Record, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Drive + >(), + hide: vi.fn< + (driveId: string) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Drive + >(), + list: vi.fn< + ( + optionalArgs?: Record, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.DriveList + >(), + remove: + vi.fn<(driveId: string, optionalArgs?: Record) => void>(), + unhide: + vi.fn< + (driveId: string) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Drive + >(), + update: + vi.fn< + ( + resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Drive, + driveId: string, + optionalArgs?: Record, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Drive + >(), + }; +} + +function mockedFilesCollection(): GoogleAppsScript.Drive_v3.Drive.V3.Collection.FilesCollection { + return { + copy: vi.fn< + ( + resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.File, + fileId: string, + optionalArgs?: Record, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.File + >(), + create: + vi.fn< + ( + resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.File, + mediaData?: GoogleAppsScript.Base.Blob, + optionalArgs?: Record, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.File + >(), + download: + vi.fn< + ( + fileId: string, + optionalArgs?: Record, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Operation + >(), + emptyTrash: vi.fn<(optionalArgs?: Record) => void>(), + export: vi.fn<(fileId: string, mimeType: string) => void>(), + generateIds: + vi.fn< + ( + optionalArgs?: Record, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.GeneratedIds + >(), + get: vi.fn() as { + ( + fileId: string, + optionalArgs?: Record & { alt: "media" }, + ): string; + ( + fileId: string, + optionalArgs?: Record, + ): GoogleAppsScript.Drive_v3.Drive.V3.Schema.File; + }, + list: vi.fn< + ( + optionalArgs?: Record, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.FileList + >(), + listLabels: + vi.fn< + ( + fileId: string, + optionalArgs?: Record, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.LabelList + >(), + modifyLabels: + vi.fn< + ( + resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.ModifyLabelsRequest, + fileId: string, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.ModifyLabelsResponse + >(), + remove: + vi.fn<(fileId: string, optionalArgs?: Record) => void>(), + update: + vi.fn< + ( + resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.File, + fileId: string, + mediaData?: GoogleAppsScript.Base.Blob, + optionalArgs?: Record, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.File + >(), + watch: + vi.fn< + ( + resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Channel, + fileId: string, + optionalArgs?: Record, + ) => GoogleAppsScript.Drive_v3.Drive.V3.Schema.Channel + >(), + }; +} + function mockedOperationCollection(): GoogleAppsScript.Drive_v3.Drive.V3.Collection.OperationCollection { return { cancel: vi.fn<(name: string) => void>(), @@ -723,3 +725,5 @@ function mockedTeamdrivesCollection(): GoogleAppsScript.Drive_v3.Drive.V3.Collec >(), }; } + +/* eslint-enable */ diff --git a/tests/backend/utils/SafeDriveService.test.ts b/tests/backend/utils/SafeDriveService.test.ts index 04e4995c..d030442b 100644 --- a/tests/backend/utils/SafeDriveService.test.ts +++ b/tests/backend/utils/SafeDriveService.test.ts @@ -1,22 +1,10 @@ import { expect, test } from "vitest"; import { SafeDriveService_ } from "../../../src/backend/utils/SafeDriveService"; -import { - mockedCommentsCollection, - mockedDrive, - mockedDrivesCollection, - mockedFilesCollection, - mockedRepliesCollection, -} from "../test-utils/gas-stubs"; +import { mockedDrive } from "../test-utils/gas-stubs"; test("SafeDriveService constructs correctly", () => { - global.Drive = { - ...mockedDrive(), - Comments: mockedCommentsCollection(), - Drives: mockedDrivesCollection(), - Files: mockedFilesCollection(), - Replies: mockedRepliesCollection(), - }; + global.Drive = mockedDrive(); expect(() => { new SafeDriveService_(); diff --git a/tests/backend/utils/SafeDriveService/SafeCommentsCollection.test.ts b/tests/backend/utils/SafeDriveService/SafeCommentsCollection.test.ts index 35791ffe..84b0432b 100644 --- a/tests/backend/utils/SafeDriveService/SafeCommentsCollection.test.ts +++ b/tests/backend/utils/SafeDriveService/SafeCommentsCollection.test.ts @@ -1,16 +1,10 @@ import { expect, test, vi } from "vitest"; import { SafeCommentsCollection_ } from "../../../../src/backend/utils/SafeDriveService/SafeCommentsCollection"; -import { - mockedCommentsCollection, - mockedDrive, -} from "../../test-utils/gas-stubs"; +import { mockedDrive } from "../../test-utils/gas-stubs"; test("SafeCommentsCollection constructs correctly", () => { - global.Drive = { - ...mockedDrive(), - Comments: mockedCommentsCollection(), - }; + global.Drive = mockedDrive(); expect(() => { new SafeCommentsCollection_(); diff --git a/tests/backend/utils/SafeDriveService/SafeDrivesCollection.test.ts b/tests/backend/utils/SafeDriveService/SafeDrivesCollection.test.ts index 91009210..2831ed1a 100644 --- a/tests/backend/utils/SafeDriveService/SafeDrivesCollection.test.ts +++ b/tests/backend/utils/SafeDriveService/SafeDrivesCollection.test.ts @@ -1,16 +1,10 @@ import { expect, test, vi } from "vitest"; import { SafeDrivesCollection_ } from "../../../../src/backend/utils/SafeDriveService/SafeDrivesCollection"; -import { - mockedDrive, - mockedDrivesCollection, -} from "../../test-utils/gas-stubs"; +import { mockedDrive } from "../../test-utils/gas-stubs"; test("SafeDrivesCollection constructs correctly", () => { - global.Drive = { - ...mockedDrive(), - Drives: mockedDrivesCollection(), - }; + global.Drive = mockedDrive(); expect(() => { new SafeDrivesCollection_(); @@ -149,7 +143,7 @@ test("list throws an error on an invalid drive", () => { }); test("list throws an error on an invalid drive list", () => { - global.Drive.Drives = mockedDrivesCollection(); + global.Drive = mockedDrive(); const list = vi.mocked(global.Drive.Drives).list.mockReturnValueOnce({}); const drivesCollection = new SafeDrivesCollection_(); diff --git a/tests/backend/utils/SafeDriveService/SafeFilesCollection.test.ts b/tests/backend/utils/SafeDriveService/SafeFilesCollection.test.ts index 2dd1153d..fdbd6317 100644 --- a/tests/backend/utils/SafeDriveService/SafeFilesCollection.test.ts +++ b/tests/backend/utils/SafeDriveService/SafeFilesCollection.test.ts @@ -1,13 +1,10 @@ import { expect, test, vi } from "vitest"; import { SafeFilesCollection_ } from "../../../../src/backend/utils/SafeDriveService/SafeFilesCollection"; -import { mockedDrive, mockedFilesCollection } from "../../test-utils/gas-stubs"; +import { mockedDrive } from "../../test-utils/gas-stubs"; test("SafeFilesCollection constructs correctly", () => { - global.Drive = { - ...mockedDrive(), - Files: mockedFilesCollection(), - }; + global.Drive = mockedDrive(); expect(() => { new SafeFilesCollection_(); @@ -25,7 +22,7 @@ test("copy works", () => { name: "FILE_TITLE", }; - global.Drive.Files = mockedFilesCollection(); + global.Drive = mockedDrive(); const copy = vi.mocked(global.Drive.Files).copy.mockReturnValueOnce(file); const filesCollection = new SafeFilesCollection_(); @@ -49,7 +46,7 @@ test("copy works with optional arguments", () => { name: "FILE_TITLE", }; - global.Drive.Files = mockedFilesCollection(); + global.Drive = mockedDrive(); const copy = vi.mocked(global.Drive.Files).copy.mockReturnValueOnce(file); const filesCollection = new SafeFilesCollection_(); @@ -72,7 +69,7 @@ test("copy works with selective fields", () => { mimeType: "text/plain", }; - global.Drive.Files = mockedFilesCollection(); + global.Drive = mockedDrive(); const copy = vi.mocked(global.Drive.Files).copy.mockReturnValueOnce(file); const filesCollection = new SafeFilesCollection_(); @@ -105,7 +102,7 @@ test("copy throws and error on invalid file", () => { name: "FILE_TITLE", }; - global.Drive.Files = mockedFilesCollection(); + global.Drive = mockedDrive(); const copy = vi.mocked(global.Drive.Files).copy.mockReturnValueOnce(file); const filesCollection = new SafeFilesCollection_(); @@ -129,7 +126,7 @@ test("get works", () => { name: "FILE_TITLE", }; - global.Drive.Files = mockedFilesCollection(); + global.Drive = mockedDrive(); const get = vi.mocked(global.Drive.Files).get.mockReturnValueOnce(file); const filesCollection = new SafeFilesCollection_(); @@ -152,7 +149,7 @@ test("get works with optional arguments", () => { name: "FILE_TITLE", }; - global.Drive.Files = mockedFilesCollection(); + global.Drive = mockedDrive(); const get = vi.mocked(global.Drive.Files).get.mockReturnValueOnce(file); const filesCollection = new SafeFilesCollection_(); @@ -170,7 +167,7 @@ test("get works with selective fields", () => { name: "FILE_TITLE", }; - global.Drive.Files = mockedFilesCollection(); + global.Drive = mockedDrive(); const get = vi.mocked(global.Drive.Files).get.mockReturnValueOnce(file); const filesCollection = new SafeFilesCollection_(); @@ -192,7 +189,7 @@ test("get throws an error on invalid file", () => { name: "FILE_TITLE", }; - global.Drive.Files = mockedFilesCollection(); + global.Drive = mockedDrive(); const get = vi.mocked(global.Drive.Files).get.mockReturnValueOnce(file); const filesCollection = new SafeFilesCollection_(); @@ -215,7 +212,7 @@ test("create works", () => { name: "FILE_TITLE", }; - global.Drive.Files = mockedFilesCollection(); + global.Drive = mockedDrive(); const create = vi.mocked(global.Drive.Files).create.mockReturnValueOnce(file); const filesCollection = new SafeFilesCollection_(); @@ -239,7 +236,7 @@ test("create works with optional arguments", () => { name: "FILE_TITLE", }; - global.Drive.Files = mockedFilesCollection(); + global.Drive = mockedDrive(); const create = vi.mocked(global.Drive.Files).create.mockReturnValueOnce(file); const filesCollection = new SafeFilesCollection_(); @@ -262,7 +259,7 @@ test("create works with selective fields", () => { name: "FILE_TITLE", }; - global.Drive.Files = mockedFilesCollection(); + global.Drive = mockedDrive(); const create = vi.mocked(global.Drive.Files).create.mockReturnValueOnce(file); const filesCollection = new SafeFilesCollection_(); @@ -292,7 +289,7 @@ test("create throws an error on invalid file", () => { name: "FILE_TITLE", }; - global.Drive.Files = mockedFilesCollection(); + global.Drive = mockedDrive(); const create = vi.mocked(global.Drive.Files).create.mockReturnValueOnce(file); const filesCollection = new SafeFilesCollection_(); @@ -329,7 +326,7 @@ test("list works", () => { ], }; - global.Drive.Files = mockedFilesCollection(); + global.Drive = mockedDrive(); const list = vi.mocked(global.Drive.Files).list.mockReturnValueOnce(fileList); const filesCollection = new SafeFilesCollection_(); @@ -364,7 +361,7 @@ test("list works with optional arguments", () => { ], }; - global.Drive.Files = mockedFilesCollection(); + global.Drive = mockedDrive(); const list = vi.mocked(global.Drive.Files).list.mockReturnValueOnce(fileList); const filesCollection = new SafeFilesCollection_(); @@ -401,7 +398,7 @@ test("list works with selective fields", () => { ], }; - global.Drive.Files = mockedFilesCollection(); + global.Drive = mockedDrive(); const list = vi.mocked(global.Drive.Files).list.mockReturnValueOnce(fileList); const filesCollection = new SafeFilesCollection_(); @@ -440,7 +437,7 @@ test("list throws an error on invalid file", () => { ], }; - global.Drive.Files = mockedFilesCollection(); + global.Drive = mockedDrive(); const list = vi.mocked(global.Drive.Files).list.mockReturnValueOnce(fileList); const filesCollection = new SafeFilesCollection_(); @@ -454,7 +451,7 @@ test("list throws an error on invalid file", () => { test("list throws an error on invalid file list", () => { const fileList = {}; - global.Drive.Files = mockedFilesCollection(); + global.Drive = mockedDrive(); const list = vi.mocked(global.Drive.Files).list.mockReturnValueOnce(fileList); const filesCollection = new SafeFilesCollection_(); @@ -466,7 +463,7 @@ test("list throws an error on invalid file list", () => { }); test("remove works", () => { - global.Drive.Files = mockedFilesCollection(); + global.Drive = mockedDrive(); const remove = vi.mocked(global.Drive.Files).remove.mockImplementationOnce( // eslint-disable-next-line @typescript-eslint/no-empty-function -- Implementation needed so the function is bound to local this () => {}, @@ -491,7 +488,7 @@ test("update works", () => { name: "FILE_TITLE", }; - global.Drive.Files = mockedFilesCollection(); + global.Drive = mockedDrive(); const update = vi.mocked(global.Drive.Files).update.mockReturnValueOnce(file); const filesCollection = new SafeFilesCollection_(); @@ -516,7 +513,7 @@ test("update works with optional arguments", () => { name: "FILE_TITLE", }; - global.Drive.Files = mockedFilesCollection(); + global.Drive = mockedDrive(); const update = vi.mocked(global.Drive.Files).update.mockReturnValueOnce(file); const filesCollection = new SafeFilesCollection_(); @@ -545,7 +542,7 @@ test("update works with selective fields", () => { }, }; - global.Drive.Files = mockedFilesCollection(); + global.Drive = mockedDrive(); const update = vi.mocked(global.Drive.Files).update.mockReturnValueOnce(file); const filesCollection = new SafeFilesCollection_(); @@ -570,7 +567,7 @@ test("update throws an error on invalid file", () => { id: "FILE_ID", }; - global.Drive.Files = mockedFilesCollection(); + global.Drive = mockedDrive(); const update = vi.mocked(global.Drive.Files).update.mockReturnValueOnce(file); const filesCollection = new SafeFilesCollection_(); From 39c29fc9c037b9e5c10267c55100276ebfe43265 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20D=C4=9Bdi=C4=8D?= Date: Thu, 16 Jan 2025 11:02:10 +0100 Subject: [PATCH 6/9] Not wrapping now safe Drive collections --- src/backend/utils/SafeDriveService.ts | 12 +- .../SafeCommentsCollection.ts | 99 ++++++------- .../SafeDriveService/SafeDrivesCollection.ts | 63 ++++---- .../SafeDriveService/SafeFilesCollection.ts | 138 ++++++++---------- .../SafeCommentsCollection.test.ts | 42 ++---- .../SafeDrivesCollection.test.ts | 32 +--- .../SafeFilesCollection.test.ts | 102 ++++--------- 7 files changed, 184 insertions(+), 304 deletions(-) diff --git a/src/backend/utils/SafeDriveService.ts b/src/backend/utils/SafeDriveService.ts index 90173ebd..9f0dc1a5 100644 --- a/src/backend/utils/SafeDriveService.ts +++ b/src/backend/utils/SafeDriveService.ts @@ -16,15 +16,15 @@ export type { } from "./SafeDriveService/SafeFilesCollection"; export class SafeDriveService_ { - public readonly Comments: SafeCommentsCollection_; - public readonly Drives: SafeDrivesCollection_; - public readonly Files: SafeFilesCollection_; + public readonly Comments: typeof SafeCommentsCollection_; + public readonly Drives: typeof SafeDrivesCollection_; + public readonly Files: typeof SafeFilesCollection_; public readonly Replies: GoogleAppsScript.Drive_v3.Drive.V3.Collection.RepliesCollection; public constructor() { - this.Comments = new SafeCommentsCollection_(); - this.Drives = new SafeDrivesCollection_(); - this.Files = new SafeFilesCollection_(); + this.Comments = SafeCommentsCollection_; + this.Drives = SafeDrivesCollection_; + this.Files = SafeFilesCollection_; this.Replies = Drive.Replies; } } diff --git a/src/backend/utils/SafeDriveService/SafeCommentsCollection.ts b/src/backend/utils/SafeDriveService/SafeCommentsCollection.ts index ec250ff7..f428abe0 100644 --- a/src/backend/utils/SafeDriveService/SafeCommentsCollection.ts +++ b/src/backend/utils/SafeDriveService/SafeCommentsCollection.ts @@ -20,77 +20,66 @@ interface SafeUser { me: boolean; } -export class SafeCommentsCollection_ { - private readonly unsafeComments: GoogleAppsScript.Drive_v3.Drive.V3.Collection.CommentsCollection; - - public constructor() { - // TODO: Remove and access directly - this.unsafeComments = Drive.Comments; - } - - private static commentIsSafe( - comment: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Comment, - ): comment is SafeComment { - return ( - comment.author !== undefined && - SafeCommentsCollection_.userIsSafe(comment.author) && - comment.id !== undefined && - comment.content !== undefined && - comment.replies?.every((reply) => - SafeCommentsCollection_.commentReplyIsSafe(reply), - ) === true - ); - } +function commentIsSafe_( + comment: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Comment, +): comment is SafeComment { + return ( + comment.author !== undefined && + userIsSafe_(comment.author) && + comment.id !== undefined && + comment.content !== undefined && + comment.replies?.every((reply) => commentReplyIsSafe_(reply)) === true + ); +} - private static commentListIsSafe( - commentList: GoogleAppsScript.Drive_v3.Drive.V3.Schema.CommentList, - ): commentList is SafeCommentList { - return ( - commentList.comments?.every((comment) => - SafeCommentsCollection_.commentIsSafe(comment), - ) === true - ); - } +function commentListIsSafe_( + commentList: GoogleAppsScript.Drive_v3.Drive.V3.Schema.CommentList, +): commentList is SafeCommentList { + return ( + commentList.comments?.every((comment) => commentIsSafe_(comment)) === true + ); +} - private static commentReplyIsSafe( - commentReply: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Reply, - ): commentReply is SafeReply { - return ( - commentReply.author !== undefined && - SafeCommentsCollection_.userIsSafe(commentReply.author) && - commentReply.content !== undefined - ); - } +function commentReplyIsSafe_( + commentReply: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Reply, +): commentReply is SafeReply { + return ( + commentReply.author !== undefined && + userIsSafe_(commentReply.author) && + commentReply.content !== undefined + ); +} - private static userIsSafe( - user: GoogleAppsScript.Drive_v3.Drive.V3.Schema.User, - ): user is SafeUser { - return user.me !== undefined && user.displayName !== undefined; - } +function userIsSafe_( + user: GoogleAppsScript.Drive_v3.Drive.V3.Schema.User, +): user is SafeUser { + return user.me !== undefined && user.displayName !== undefined; +} - public create( +export const SafeCommentsCollection_ = { + create: ( resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Comment, fileId: string, - ): SafeComment { - const ret = this.unsafeComments.create(resource, fileId); - if (!SafeCommentsCollection_.commentIsSafe(ret)) { + ): SafeComment => { + const ret = Drive.Comments.create(resource, fileId); + if (!commentIsSafe_(ret)) { throw new Error(""); } return ret; - } + }, - public list( + list: ( fileId: string, optionalArgs: { fields?: string; maxResults?: number; pageToken?: string | undefined; } = {}, - ): SafeCommentList { - const ret = this.unsafeComments.list(fileId, optionalArgs); - if (!SafeCommentsCollection_.commentListIsSafe(ret)) { + ): SafeCommentList => { + const ret = Drive.Comments.list(fileId, optionalArgs); + if (!commentListIsSafe_(ret)) { throw new Error(""); } return ret; - } -} + }, +}; diff --git a/src/backend/utils/SafeDriveService/SafeDrivesCollection.ts b/src/backend/utils/SafeDriveService/SafeDrivesCollection.ts index f51ea5ef..0aa259c5 100644 --- a/src/backend/utils/SafeDriveService/SafeDrivesCollection.ts +++ b/src/backend/utils/SafeDriveService/SafeDrivesCollection.ts @@ -18,60 +18,49 @@ const safeDriveKeys: DeepKeyof = { name: true, }; -export class SafeDrivesCollection_ { - private readonly unsafeDrives: GoogleAppsScript.Drive_v3.Drive.V3.Collection.DrivesCollection; - - public constructor() { - // TODO: Remove and access directly - this.unsafeDrives = Drive.Drives; +function driveIsSafe_>( + drive: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Drive, + keys: F | null, +): drive is typeof keys extends null ? SafeDrive : DeepPick { + if (keys === null) { + return driveIsSafe_(drive, safeDriveKeys); } - - private static driveIsSafe>( - drive: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Drive, - keys: F | null, - ): drive is typeof keys extends null ? SafeDrive : DeepPick { - if (keys === null) { - return SafeDrivesCollection_.driveIsSafe(drive, safeDriveKeys); + for (const key in keys) { + if (!Object.prototype.hasOwnProperty.call(keys, key)) { + continue; } - for (const key in keys) { - if (!Object.prototype.hasOwnProperty.call(keys, key)) { - continue; - } - if (drive[key as keyof DeepKeyof] === undefined) { - return false; - } + if (drive[key as keyof DeepKeyof] === undefined) { + return false; } - return true; } + return true; +} - private static driveListIsSafe>( - driveList: GoogleAppsScript.Drive_v3.Drive.V3.Schema.DriveList, - keys: F | null, - ): driveList is SafeDriveList { - return ( - driveList.drives?.every((file) => - SafeDrivesCollection_.driveIsSafe(file, keys), - ) === true - ); - } +function driveListIsSafe_>( + driveList: GoogleAppsScript.Drive_v3.Drive.V3.Schema.DriveList, + keys: F | null, +): driveList is SafeDriveList { + return driveList.drives?.every((file) => driveIsSafe_(file, keys)) === true; +} - public list>( +export const SafeDrivesCollection_ = { + list: >( fields: F | null, optionalArgs: { maxResults?: number; orderBy?: string; pageToken?: string | undefined; } = {}, - ): SafeDriveList { - const ret = this.unsafeDrives.list({ + ): SafeDriveList => { + const ret = Drive.Drives.list({ ...optionalArgs, ...(fields !== null && { fields: `nextPageToken, drives(${stringifyFields_(fields)})`, }), }); - if (!SafeDrivesCollection_.driveListIsSafe(ret, fields)) { + if (!driveListIsSafe_(ret, fields)) { throw new Error(""); } return ret; - } -} + }, +}; diff --git a/src/backend/utils/SafeDriveService/SafeFilesCollection.ts b/src/backend/utils/SafeDriveService/SafeFilesCollection.ts index f106ea4e..51dd24da 100644 --- a/src/backend/utils/SafeDriveService/SafeFilesCollection.ts +++ b/src/backend/utils/SafeDriveService/SafeFilesCollection.ts @@ -51,120 +51,106 @@ type GetReturn, A extends GetArg> = A extends { ? string : DeepPick; -export class SafeFilesCollection_ { - private readonly unsafeFiles: GoogleAppsScript.Drive_v3.Drive.V3.Collection.FilesCollection; - - public constructor() { - // TODO: Remove and access directly - this.unsafeFiles = Drive.Files; +function fileIsSafe_>( + file: GoogleAppsScript.Drive_v3.Drive.V3.Schema.File, + keys: F | null, +): file is typeof keys extends null ? SafeFile : DeepPick { + if (keys === null) { + return fileIsSafe_(file, safeFileKeys); } - - private static fileIsSafe>( - file: GoogleAppsScript.Drive_v3.Drive.V3.Schema.File, - keys: F | null, - ): file is typeof keys extends null ? SafeFile : DeepPick { - if (keys === null) { - return SafeFilesCollection_.fileIsSafe(file, safeFileKeys); + for (const key in keys) { + if ( + !Object.prototype.hasOwnProperty.call(keys, key) || + safeFileOptionalKeys.indexOf(key) > -1 + ) { + continue; } - for (const key in keys) { - if ( - !Object.prototype.hasOwnProperty.call(keys, key) || - safeFileOptionalKeys.indexOf(key) > -1 - ) { - continue; - } - if (file[key as keyof DeepKeyof] === undefined) { - return false; - } - if (typeof keys[key] === "object") { - for (const innerKey in keys[key]) { - if ( - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- On purpose, we want to support arbitrary objects - (file[key as keyof DeepKeyof] as Record)[ - innerKey - ] === undefined - ) { - return false; - } + if (file[key as keyof DeepKeyof] === undefined) { + return false; + } + if (typeof keys[key] === "object") { + for (const innerKey in keys[key]) { + if ( + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- On purpose, we want to support arbitrary objects + (file[key as keyof DeepKeyof] as Record)[ + innerKey + ] === undefined + ) { + return false; } } } - return true; } + return true; +} - private static fileListIsSafe>( - fileList: GoogleAppsScript.Drive_v3.Drive.V3.Schema.FileList, - keys: F | null, - ): fileList is SafeFileList { - return ( - fileList.files?.every((file) => - SafeFilesCollection_.fileIsSafe(file, keys), - ) === true - ); - } +function fileListIsSafe_>( + fileList: GoogleAppsScript.Drive_v3.Drive.V3.Schema.FileList, + keys: F | null, +): fileList is SafeFileList { + return fileList.files?.every((file) => fileIsSafe_(file, keys)) === true; +} - public copy>( +export const SafeFilesCollection_ = { + copy: >( resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.File, fileId: string, fields: F | null, optionalArgs: { supportsAllDrives?: boolean; } = {}, - ): DeepPick { - const ret = this.unsafeFiles.copy(resource, fileId, { + ): DeepPick => { + const ret = Drive.Files.copy(resource, fileId, { ...optionalArgs, ...(fields !== null && { fields: stringifyFields_(fields), }), }); - if (!SafeFilesCollection_.fileIsSafe(ret, fields)) { + if (!fileIsSafe_(ret, fields)) { throw new Error(""); } return ret; - } + }, - public create>( + create: >( resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.File, fields: F | null, mediaData?: GoogleAppsScript.Base.Blob, optionalArgs: { supportsAllDrives?: boolean; } = {}, - ): DeepPick { + ): DeepPick => { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- Due to strange optional arguments on upstream types - const ret = this.unsafeFiles.create(resource, mediaData!, { + const ret = Drive.Files.create(resource, mediaData!, { ...optionalArgs, ...(fields !== null && { fields: stringifyFields_(fields), }), }); - if (!SafeFilesCollection_.fileIsSafe(ret, fields)) { + if (!fileIsSafe_(ret, fields)) { throw new Error(""); } return ret; - } + }, - public get, A extends GetArg>( + get: , A extends GetArg>( fileId: string, fields: F | null, optionalArgs: A = {} as A, - ): GetReturn { - const ret = this.unsafeFiles.get(fileId, { + ): GetReturn => { + const ret = Drive.Files.get(fileId, { ...optionalArgs, ...(fields !== null && { fields: stringifyFields_(fields), }), }); - if ( - typeof ret !== "string" && - !SafeFilesCollection_.fileIsSafe(ret, fields) - ) { + if (typeof ret !== "string" && !fileIsSafe_(ret, fields)) { throw new Error(""); } return ret as unknown as GetReturn; - } + }, - public list>( + list: >( fields: F | null, optionalArgs: { includeItemsFromAllDrives?: boolean; @@ -173,24 +159,24 @@ export class SafeFilesCollection_ { q?: string; supportsAllDrives?: boolean; } = {}, - ): SafeFileList { - const ret = this.unsafeFiles.list({ + ): SafeFileList => { + const ret = Drive.Files.list({ ...optionalArgs, ...(fields !== null && { fields: `nextPageToken, files(${stringifyFields_(fields)})`, }), }); - if (!SafeFilesCollection_.fileListIsSafe(ret, fields)) { + if (!fileListIsSafe_(ret, fields)) { throw new Error(""); } return ret; - } + }, - public remove(fileId: string): void { - this.unsafeFiles.remove(fileId); - } + remove: (fileId: string): void => { + Drive.Files.remove(fileId); + }, - public update>( + update: >( resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.File, fileId: string, fields: F | null, @@ -200,17 +186,17 @@ export class SafeFilesCollection_ { removeParents?: string; supportsAllDrives?: boolean; } = {}, - ): DeepPick { + ): DeepPick => { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- Strange behaviour with optional arguments - const ret = this.unsafeFiles.update(resource, fileId, mediaData!, { + const ret = Drive.Files.update(resource, fileId, mediaData!, { ...optionalArgs, ...(fields !== null && { fields: stringifyFields_(fields), }), }); - if (!SafeFilesCollection_.fileIsSafe(ret, fields)) { + if (!fileIsSafe_(ret, fields)) { throw new Error(""); } return ret; - } -} + }, +}; diff --git a/tests/backend/utils/SafeDriveService/SafeCommentsCollection.test.ts b/tests/backend/utils/SafeDriveService/SafeCommentsCollection.test.ts index 84b0432b..f0939ddd 100644 --- a/tests/backend/utils/SafeDriveService/SafeCommentsCollection.test.ts +++ b/tests/backend/utils/SafeDriveService/SafeCommentsCollection.test.ts @@ -3,14 +3,6 @@ import { expect, test, vi } from "vitest"; import { SafeCommentsCollection_ } from "../../../../src/backend/utils/SafeDriveService/SafeCommentsCollection"; import { mockedDrive } from "../../test-utils/gas-stubs"; -test("SafeCommentsCollection constructs correctly", () => { - global.Drive = mockedDrive(); - - expect(() => { - new SafeCommentsCollection_(); - }).not.toThrow(); -}); - test("create works", () => { const comment = { author: { @@ -35,9 +27,9 @@ test("create works", () => { .mocked(global.Drive.Comments) .create.mockReturnValueOnce(comment); - const commentsCollection = new SafeCommentsCollection_(); - - expect(commentsCollection.create(comment, "FILE_ID")).toStrictEqual(comment); + expect(SafeCommentsCollection_.create(comment, "FILE_ID")).toStrictEqual( + comment, + ); expect(create.mock.calls).toHaveLength(1); expect(create.mock.calls[0][0]).toBe(comment); @@ -67,9 +59,7 @@ test("create throws an error on an invalid comment", () => { .mocked(global.Drive.Comments) .create.mockReturnValueOnce(comment); - const commentsCollection = new SafeCommentsCollection_(); - - expect(() => commentsCollection.create(comment, "FILE_ID")).toThrow(""); + expect(() => SafeCommentsCollection_.create(comment, "FILE_ID")).toThrow(""); expect(create.mock.calls).toHaveLength(1); expect(create.mock.calls[0][0]).toBe(comment); @@ -121,9 +111,7 @@ test("list works", () => { .mocked(global.Drive.Comments) .list.mockReturnValueOnce(commentList); - const commentsCollection = new SafeCommentsCollection_(); - - expect(commentsCollection.list("FILE_ID")).toStrictEqual(commentList); + expect(SafeCommentsCollection_.list("FILE_ID")).toStrictEqual(commentList); expect(list.mock.calls).toHaveLength(1); expect(list.mock.calls[0][0]).toBe("FILE_ID"); @@ -175,15 +163,13 @@ test("list works with optional arguments", () => { .mocked(global.Drive.Comments) .list.mockReturnValueOnce(commentList); - const commentsCollection = new SafeCommentsCollection_(); - const optionalArgs = { fields: "comments(id)", maxResults: 100, pageToken: "TOKEN", }; - expect(commentsCollection.list("FILE_ID", optionalArgs)).toStrictEqual( + expect(SafeCommentsCollection_.list("FILE_ID", optionalArgs)).toStrictEqual( commentList, ); @@ -236,9 +222,7 @@ test("list throws an error on an invalid comment", () => { .mocked(global.Drive.Comments) .list.mockReturnValueOnce(commentList); - const commentsCollection = new SafeCommentsCollection_(); - - expect(() => commentsCollection.list("FILE_ID")).toThrow(""); + expect(() => SafeCommentsCollection_.list("FILE_ID")).toThrow(""); expect(list.mock.calls).toHaveLength(1); expect(list.mock.calls[0][0]).toBe("FILE_ID"); @@ -255,9 +239,7 @@ test("list throws an error on an invalid comment list", () => { .mocked(global.Drive.Comments) .list.mockReturnValueOnce(commentList); - const commentsCollection = new SafeCommentsCollection_(); - - expect(() => commentsCollection.list("FILE_ID")).toThrow(""); + expect(() => SafeCommentsCollection_.list("FILE_ID")).toThrow(""); expect(list.mock.calls).toHaveLength(1); expect(list.mock.calls[0][0]).toBe("FILE_ID"); @@ -300,9 +282,7 @@ test("list throws an error on missing replies", () => { .mocked(global.Drive.Comments) .list.mockReturnValueOnce(commentList); - const commentsCollection = new SafeCommentsCollection_(); - - expect(() => commentsCollection.list("FILE_ID")).toThrow(""); + expect(() => SafeCommentsCollection_.list("FILE_ID")).toThrow(""); expect(list.mock.calls).toHaveLength(1); expect(list.mock.calls[0][0]).toBe("FILE_ID"); @@ -353,9 +333,7 @@ test("list throws an error on an invalid reply", () => { .mocked(global.Drive.Comments) .list.mockReturnValueOnce(commentList); - const commentsCollection = new SafeCommentsCollection_(); - - expect(() => commentsCollection.list("FILE_ID")).toThrow(""); + expect(() => SafeCommentsCollection_.list("FILE_ID")).toThrow(""); expect(list.mock.calls).toHaveLength(1); expect(list.mock.calls[0][0]).toBe("FILE_ID"); diff --git a/tests/backend/utils/SafeDriveService/SafeDrivesCollection.test.ts b/tests/backend/utils/SafeDriveService/SafeDrivesCollection.test.ts index 2831ed1a..a1dbbd35 100644 --- a/tests/backend/utils/SafeDriveService/SafeDrivesCollection.test.ts +++ b/tests/backend/utils/SafeDriveService/SafeDrivesCollection.test.ts @@ -3,14 +3,6 @@ import { expect, test, vi } from "vitest"; import { SafeDrivesCollection_ } from "../../../../src/backend/utils/SafeDriveService/SafeDrivesCollection"; import { mockedDrive } from "../../test-utils/gas-stubs"; -test("SafeDrivesCollection constructs correctly", () => { - global.Drive = mockedDrive(); - - expect(() => { - new SafeDrivesCollection_(); - }).not.toThrow(); -}); - test("list works", () => { const driveList = { drives: [ @@ -30,9 +22,7 @@ test("list works", () => { .mocked(global.Drive.Drives) .list.mockReturnValueOnce(driveList); - const drivesCollection = new SafeDrivesCollection_(); - - expect(drivesCollection.list(null)).toStrictEqual(driveList); + expect(SafeDrivesCollection_.list(null)).toStrictEqual(driveList); expect(list.mock.calls).toHaveLength(1); expect(list.mock.calls[0][0]).toStrictEqual({}); @@ -57,15 +47,15 @@ test("list works with optional parameters", () => { .mocked(global.Drive.Drives) .list.mockReturnValueOnce(driveList); - const drivesCollection = new SafeDrivesCollection_(); - const optionalArgs = { maxResults: 100, orderBy: "name", pageToken: "TOKEN", }; - expect(drivesCollection.list(null, optionalArgs)).toStrictEqual(driveList); + expect(SafeDrivesCollection_.list(null, optionalArgs)).toStrictEqual( + driveList, + ); expect(list.mock.calls).toHaveLength(1); expect(list.mock.calls[0][0]).toStrictEqual(optionalArgs); @@ -101,10 +91,8 @@ test("list works with selective fields", () => { .list.mockReturnValueOnce(driveList1) .mockReturnValueOnce(driveList2); - const drivesCollection = new SafeDrivesCollection_(); - - expect(drivesCollection.list({ name: true })).toStrictEqual(driveList1); - expect(drivesCollection.list({ id: true, name: true })).toStrictEqual( + expect(SafeDrivesCollection_.list({ name: true })).toStrictEqual(driveList1); + expect(SafeDrivesCollection_.list({ id: true, name: true })).toStrictEqual( driveList2, ); @@ -134,9 +122,7 @@ test("list throws an error on an invalid drive", () => { .mocked(global.Drive.Drives) .list.mockReturnValueOnce(driveList); - const drivesCollection = new SafeDrivesCollection_(); - - expect(() => drivesCollection.list(null)).toThrow(""); + expect(() => SafeDrivesCollection_.list(null)).toThrow(""); expect(list.mock.calls).toHaveLength(1); expect(list.mock.calls[0][0]).toStrictEqual({}); @@ -146,9 +132,7 @@ test("list throws an error on an invalid drive list", () => { global.Drive = mockedDrive(); const list = vi.mocked(global.Drive.Drives).list.mockReturnValueOnce({}); - const drivesCollection = new SafeDrivesCollection_(); - - expect(() => drivesCollection.list(null)).toThrow(""); + expect(() => SafeDrivesCollection_.list(null)).toThrow(""); expect(list.mock.calls).toHaveLength(1); expect(list.mock.calls[0][0]).toStrictEqual({}); diff --git a/tests/backend/utils/SafeDriveService/SafeFilesCollection.test.ts b/tests/backend/utils/SafeDriveService/SafeFilesCollection.test.ts index fdbd6317..52660878 100644 --- a/tests/backend/utils/SafeDriveService/SafeFilesCollection.test.ts +++ b/tests/backend/utils/SafeDriveService/SafeFilesCollection.test.ts @@ -3,14 +3,6 @@ import { expect, test, vi } from "vitest"; import { SafeFilesCollection_ } from "../../../../src/backend/utils/SafeDriveService/SafeFilesCollection"; import { mockedDrive } from "../../test-utils/gas-stubs"; -test("SafeFilesCollection constructs correctly", () => { - global.Drive = mockedDrive(); - - expect(() => { - new SafeFilesCollection_(); - }).not.toThrow(); -}); - test("copy works", () => { const file = { capabilities: { @@ -25,9 +17,7 @@ test("copy works", () => { global.Drive = mockedDrive(); const copy = vi.mocked(global.Drive.Files).copy.mockReturnValueOnce(file); - const filesCollection = new SafeFilesCollection_(); - - expect(filesCollection.copy(file, "TARGET_ID", null)).toBe(file); + expect(SafeFilesCollection_.copy(file, "TARGET_ID", null)).toBe(file); expect(copy.mock.calls).toHaveLength(1); expect(copy.mock.calls[0][0]).toBe(file); @@ -49,10 +39,10 @@ test("copy works with optional arguments", () => { global.Drive = mockedDrive(); const copy = vi.mocked(global.Drive.Files).copy.mockReturnValueOnce(file); - const filesCollection = new SafeFilesCollection_(); - expect( - filesCollection.copy(file, "TARGET_ID", null, { supportsAllDrives: true }), + SafeFilesCollection_.copy(file, "TARGET_ID", null, { + supportsAllDrives: true, + }), ).toBe(file); expect(copy.mock.calls).toHaveLength(1); @@ -72,10 +62,8 @@ test("copy works with selective fields", () => { global.Drive = mockedDrive(); const copy = vi.mocked(global.Drive.Files).copy.mockReturnValueOnce(file); - const filesCollection = new SafeFilesCollection_(); - expect( - filesCollection.copy( + SafeFilesCollection_.copy( file, "TARGET_ID", { capabilities: { canMoveItemOutOfDrive: true }, mimeType: true }, @@ -105,9 +93,7 @@ test("copy throws and error on invalid file", () => { global.Drive = mockedDrive(); const copy = vi.mocked(global.Drive.Files).copy.mockReturnValueOnce(file); - const filesCollection = new SafeFilesCollection_(); - - expect(() => filesCollection.copy(file, "TARGET_ID", null)).toThrow(""); + expect(() => SafeFilesCollection_.copy(file, "TARGET_ID", null)).toThrow(""); expect(copy.mock.calls).toHaveLength(1); expect(copy.mock.calls[0][0]).toBe(file); @@ -129,9 +115,7 @@ test("get works", () => { global.Drive = mockedDrive(); const get = vi.mocked(global.Drive.Files).get.mockReturnValueOnce(file); - const filesCollection = new SafeFilesCollection_(); - - expect(filesCollection.get("FILE_ID", null)).toBe(file); + expect(SafeFilesCollection_.get("FILE_ID", null)).toBe(file); expect(get.mock.calls).toHaveLength(1); expect(get.mock.calls[0][0]).toBe("FILE_ID"); @@ -152,9 +136,7 @@ test("get works with optional arguments", () => { global.Drive = mockedDrive(); const get = vi.mocked(global.Drive.Files).get.mockReturnValueOnce(file); - const filesCollection = new SafeFilesCollection_(); - - expect(filesCollection.get("FILE_ID", null, { alt: "ALT" })).toBe(file); + expect(SafeFilesCollection_.get("FILE_ID", null, { alt: "ALT" })).toBe(file); expect(get.mock.calls).toHaveLength(1); expect(get.mock.calls[0][0]).toBe("FILE_ID"); @@ -170,9 +152,9 @@ test("get works with selective fields", () => { global.Drive = mockedDrive(); const get = vi.mocked(global.Drive.Files).get.mockReturnValueOnce(file); - const filesCollection = new SafeFilesCollection_(); - - expect(filesCollection.get("FILE_ID", { id: true, name: true })).toBe(file); + expect(SafeFilesCollection_.get("FILE_ID", { id: true, name: true })).toBe( + file, + ); expect(get.mock.calls).toHaveLength(1); expect(get.mock.calls[0][0]).toBe("FILE_ID"); @@ -192,9 +174,7 @@ test("get throws an error on invalid file", () => { global.Drive = mockedDrive(); const get = vi.mocked(global.Drive.Files).get.mockReturnValueOnce(file); - const filesCollection = new SafeFilesCollection_(); - - expect(() => filesCollection.get("FILE_ID", null)).toThrow(""); + expect(() => SafeFilesCollection_.get("FILE_ID", null)).toThrow(""); expect(get.mock.calls).toHaveLength(1); expect(get.mock.calls[0][0]).toBe("FILE_ID"); @@ -215,9 +195,7 @@ test("create works", () => { global.Drive = mockedDrive(); const create = vi.mocked(global.Drive.Files).create.mockReturnValueOnce(file); - const filesCollection = new SafeFilesCollection_(); - - expect(filesCollection.create(file, null)).toBe(file); + expect(SafeFilesCollection_.create(file, null)).toBe(file); expect(create.mock.calls).toHaveLength(1); expect(create.mock.calls[0][0]).toBe(file); @@ -239,10 +217,10 @@ test("create works with optional arguments", () => { global.Drive = mockedDrive(); const create = vi.mocked(global.Drive.Files).create.mockReturnValueOnce(file); - const filesCollection = new SafeFilesCollection_(); - expect( - filesCollection.create(file, null, undefined, { supportsAllDrives: true }), + SafeFilesCollection_.create(file, null, undefined, { + supportsAllDrives: true, + }), ).toBe(file); expect(create.mock.calls).toHaveLength(1); @@ -262,10 +240,8 @@ test("create works with selective fields", () => { global.Drive = mockedDrive(); const create = vi.mocked(global.Drive.Files).create.mockReturnValueOnce(file); - const filesCollection = new SafeFilesCollection_(); - expect( - filesCollection.create(file, { + SafeFilesCollection_.create(file, { capabilities: { canDelete: true }, name: true, }), @@ -292,9 +268,7 @@ test("create throws an error on invalid file", () => { global.Drive = mockedDrive(); const create = vi.mocked(global.Drive.Files).create.mockReturnValueOnce(file); - const filesCollection = new SafeFilesCollection_(); - - expect(() => filesCollection.create(file, null)).toThrow(""); + expect(() => SafeFilesCollection_.create(file, null)).toThrow(""); expect(create.mock.calls).toHaveLength(1); expect(create.mock.calls[0][0]).toBe(file); @@ -329,9 +303,7 @@ test("list works", () => { global.Drive = mockedDrive(); const list = vi.mocked(global.Drive.Files).list.mockReturnValueOnce(fileList); - const filesCollection = new SafeFilesCollection_(); - - expect(filesCollection.list(null)).toBe(fileList); + expect(SafeFilesCollection_.list(null)).toBe(fileList); expect(list.mock.calls).toHaveLength(1); expect(list.mock.calls[0][0]).toStrictEqual({}); @@ -364,8 +336,6 @@ test("list works with optional arguments", () => { global.Drive = mockedDrive(); const list = vi.mocked(global.Drive.Files).list.mockReturnValueOnce(fileList); - const filesCollection = new SafeFilesCollection_(); - const optionalArgs = { includeItemsFromAllDrives: false, maxResults: 42, @@ -374,7 +344,7 @@ test("list works with optional arguments", () => { supportsAllDrives: true, }; - expect(filesCollection.list(null, optionalArgs)).toBe(fileList); + expect(SafeFilesCollection_.list(null, optionalArgs)).toBe(fileList); expect(list.mock.calls).toHaveLength(1); expect(list.mock.calls[0][0]).toStrictEqual(optionalArgs); @@ -401,10 +371,8 @@ test("list works with selective fields", () => { global.Drive = mockedDrive(); const list = vi.mocked(global.Drive.Files).list.mockReturnValueOnce(fileList); - const filesCollection = new SafeFilesCollection_(); - expect( - filesCollection.list({ + SafeFilesCollection_.list({ capabilities: { canMoveItemOutOfDrive: true }, id: true, }), @@ -440,9 +408,7 @@ test("list throws an error on invalid file", () => { global.Drive = mockedDrive(); const list = vi.mocked(global.Drive.Files).list.mockReturnValueOnce(fileList); - const filesCollection = new SafeFilesCollection_(); - - expect(() => filesCollection.list(null)).toThrow(""); + expect(() => SafeFilesCollection_.list(null)).toThrow(""); expect(list.mock.calls).toHaveLength(1); expect(list.mock.calls[0][0]).toStrictEqual({}); @@ -454,9 +420,7 @@ test("list throws an error on invalid file list", () => { global.Drive = mockedDrive(); const list = vi.mocked(global.Drive.Files).list.mockReturnValueOnce(fileList); - const filesCollection = new SafeFilesCollection_(); - - expect(() => filesCollection.list(null)).toThrow(""); + expect(() => SafeFilesCollection_.list(null)).toThrow(""); expect(list.mock.calls).toHaveLength(1); expect(list.mock.calls[0][0]).toStrictEqual({}); @@ -469,9 +433,7 @@ test("remove works", () => { () => {}, ); - const filesCollection = new SafeFilesCollection_(); - - filesCollection.remove("FILE_ID"); + SafeFilesCollection_.remove("FILE_ID"); expect(remove.mock.calls).toHaveLength(1); expect(remove.mock.calls[0][0]).toBe("FILE_ID"); @@ -491,9 +453,7 @@ test("update works", () => { global.Drive = mockedDrive(); const update = vi.mocked(global.Drive.Files).update.mockReturnValueOnce(file); - const filesCollection = new SafeFilesCollection_(); - - expect(filesCollection.update(file, "FILE_ID", null)).toBe(file); + expect(SafeFilesCollection_.update(file, "FILE_ID", null)).toBe(file); expect(update.mock.calls).toHaveLength(1); expect(update.mock.calls[0][0]).toBe(file); @@ -516,8 +476,6 @@ test("update works with optional arguments", () => { global.Drive = mockedDrive(); const update = vi.mocked(global.Drive.Files).update.mockReturnValueOnce(file); - const filesCollection = new SafeFilesCollection_(); - const optionalArgs = { addParents: "ADD_PARENT", removeParents: "REMOVE_PARENT", @@ -525,7 +483,7 @@ test("update works with optional arguments", () => { }; expect( - filesCollection.update(file, "FILE_ID", null, undefined, optionalArgs), + SafeFilesCollection_.update(file, "FILE_ID", null, undefined, optionalArgs), ).toBe(file); expect(update.mock.calls).toHaveLength(1); @@ -545,10 +503,8 @@ test("update works with selective fields", () => { global.Drive = mockedDrive(); const update = vi.mocked(global.Drive.Files).update.mockReturnValueOnce(file); - const filesCollection = new SafeFilesCollection_(); - expect( - filesCollection.update(file, "FILE_ID", { + SafeFilesCollection_.update(file, "FILE_ID", { capabilities: { canMoveItemOutOfDrive: true }, }), ).toBe(file); @@ -570,9 +526,7 @@ test("update throws an error on invalid file", () => { global.Drive = mockedDrive(); const update = vi.mocked(global.Drive.Files).update.mockReturnValueOnce(file); - const filesCollection = new SafeFilesCollection_(); - - expect(() => filesCollection.update(file, "FILE_ID", null)).toThrow(""); + expect(() => SafeFilesCollection_.update(file, "FILE_ID", null)).toThrow(""); expect(update.mock.calls).toHaveLength(1); expect(update.mock.calls[0][0]).toBe(file); From 7ae9c73796dff14422d3da1d137bfddcd3473df5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20D=C4=9Bdi=C4=8D?= Date: Wed, 5 Feb 2025 16:16:30 +0100 Subject: [PATCH 7/9] Proper error messages for Drive API validation fail --- .../SafeCommentsCollection.ts | 4 ++-- .../SafeDriveService/SafeDrivesCollection.ts | 2 +- .../SafeDriveService/SafeFilesCollection.ts | 10 ++++---- .../SafeCommentsCollection.test.ts | 20 ++++++++++++---- .../SafeDrivesCollection.test.ts | 8 +++++-- .../SafeFilesCollection.test.ts | 24 ++++++++++++++----- 6 files changed, 47 insertions(+), 21 deletions(-) diff --git a/src/backend/utils/SafeDriveService/SafeCommentsCollection.ts b/src/backend/utils/SafeDriveService/SafeCommentsCollection.ts index f428abe0..43a8853d 100644 --- a/src/backend/utils/SafeDriveService/SafeCommentsCollection.ts +++ b/src/backend/utils/SafeDriveService/SafeCommentsCollection.ts @@ -63,7 +63,7 @@ export const SafeCommentsCollection_ = { ): SafeComment => { const ret = Drive.Comments.create(resource, fileId); if (!commentIsSafe_(ret)) { - throw new Error(""); + throw new Error("Comments.create: Comment is not safe."); } return ret; }, @@ -78,7 +78,7 @@ export const SafeCommentsCollection_ = { ): SafeCommentList => { const ret = Drive.Comments.list(fileId, optionalArgs); if (!commentListIsSafe_(ret)) { - throw new Error(""); + throw new Error("Comments.list: Comment list is not safe."); } return ret; }, diff --git a/src/backend/utils/SafeDriveService/SafeDrivesCollection.ts b/src/backend/utils/SafeDriveService/SafeDrivesCollection.ts index 0aa259c5..f90e1f45 100644 --- a/src/backend/utils/SafeDriveService/SafeDrivesCollection.ts +++ b/src/backend/utils/SafeDriveService/SafeDrivesCollection.ts @@ -59,7 +59,7 @@ export const SafeDrivesCollection_ = { }), }); if (!driveListIsSafe_(ret, fields)) { - throw new Error(""); + throw new Error("Drives.list: Drive list is not safe."); } return ret; }, diff --git a/src/backend/utils/SafeDriveService/SafeFilesCollection.ts b/src/backend/utils/SafeDriveService/SafeFilesCollection.ts index 51dd24da..87400a42 100644 --- a/src/backend/utils/SafeDriveService/SafeFilesCollection.ts +++ b/src/backend/utils/SafeDriveService/SafeFilesCollection.ts @@ -107,7 +107,7 @@ export const SafeFilesCollection_ = { }), }); if (!fileIsSafe_(ret, fields)) { - throw new Error(""); + throw new Error("Files.copy: File is not safe."); } return ret; }, @@ -128,7 +128,7 @@ export const SafeFilesCollection_ = { }), }); if (!fileIsSafe_(ret, fields)) { - throw new Error(""); + throw new Error("Files.create: File is not safe."); } return ret; }, @@ -145,7 +145,7 @@ export const SafeFilesCollection_ = { }), }); if (typeof ret !== "string" && !fileIsSafe_(ret, fields)) { - throw new Error(""); + throw new Error("Files.get: File is not safe."); } return ret as unknown as GetReturn; }, @@ -167,7 +167,7 @@ export const SafeFilesCollection_ = { }), }); if (!fileListIsSafe_(ret, fields)) { - throw new Error(""); + throw new Error("Files.list: File list is not safe."); } return ret; }, @@ -195,7 +195,7 @@ export const SafeFilesCollection_ = { }), }); if (!fileIsSafe_(ret, fields)) { - throw new Error(""); + throw new Error("Files.update: File is not safe."); } return ret; }, diff --git a/tests/backend/utils/SafeDriveService/SafeCommentsCollection.test.ts b/tests/backend/utils/SafeDriveService/SafeCommentsCollection.test.ts index f0939ddd..b14ac980 100644 --- a/tests/backend/utils/SafeDriveService/SafeCommentsCollection.test.ts +++ b/tests/backend/utils/SafeDriveService/SafeCommentsCollection.test.ts @@ -59,7 +59,9 @@ test("create throws an error on an invalid comment", () => { .mocked(global.Drive.Comments) .create.mockReturnValueOnce(comment); - expect(() => SafeCommentsCollection_.create(comment, "FILE_ID")).toThrow(""); + expect(() => SafeCommentsCollection_.create(comment, "FILE_ID")).toThrow( + "Comments.create: Comment is not safe.", + ); expect(create.mock.calls).toHaveLength(1); expect(create.mock.calls[0][0]).toBe(comment); @@ -222,7 +224,9 @@ test("list throws an error on an invalid comment", () => { .mocked(global.Drive.Comments) .list.mockReturnValueOnce(commentList); - expect(() => SafeCommentsCollection_.list("FILE_ID")).toThrow(""); + expect(() => SafeCommentsCollection_.list("FILE_ID")).toThrow( + "Comments.list: Comment list is not safe.", + ); expect(list.mock.calls).toHaveLength(1); expect(list.mock.calls[0][0]).toBe("FILE_ID"); @@ -239,7 +243,9 @@ test("list throws an error on an invalid comment list", () => { .mocked(global.Drive.Comments) .list.mockReturnValueOnce(commentList); - expect(() => SafeCommentsCollection_.list("FILE_ID")).toThrow(""); + expect(() => SafeCommentsCollection_.list("FILE_ID")).toThrow( + "Comments.list: Comment list is not safe.", + ); expect(list.mock.calls).toHaveLength(1); expect(list.mock.calls[0][0]).toBe("FILE_ID"); @@ -282,7 +288,9 @@ test("list throws an error on missing replies", () => { .mocked(global.Drive.Comments) .list.mockReturnValueOnce(commentList); - expect(() => SafeCommentsCollection_.list("FILE_ID")).toThrow(""); + expect(() => SafeCommentsCollection_.list("FILE_ID")).toThrow( + "Comments.list: Comment list is not safe.", + ); expect(list.mock.calls).toHaveLength(1); expect(list.mock.calls[0][0]).toBe("FILE_ID"); @@ -333,7 +341,9 @@ test("list throws an error on an invalid reply", () => { .mocked(global.Drive.Comments) .list.mockReturnValueOnce(commentList); - expect(() => SafeCommentsCollection_.list("FILE_ID")).toThrow(""); + expect(() => SafeCommentsCollection_.list("FILE_ID")).toThrow( + "Comments.list: Comment list is not safe.", + ); expect(list.mock.calls).toHaveLength(1); expect(list.mock.calls[0][0]).toBe("FILE_ID"); diff --git a/tests/backend/utils/SafeDriveService/SafeDrivesCollection.test.ts b/tests/backend/utils/SafeDriveService/SafeDrivesCollection.test.ts index a1dbbd35..0c4e3418 100644 --- a/tests/backend/utils/SafeDriveService/SafeDrivesCollection.test.ts +++ b/tests/backend/utils/SafeDriveService/SafeDrivesCollection.test.ts @@ -122,7 +122,9 @@ test("list throws an error on an invalid drive", () => { .mocked(global.Drive.Drives) .list.mockReturnValueOnce(driveList); - expect(() => SafeDrivesCollection_.list(null)).toThrow(""); + expect(() => SafeDrivesCollection_.list(null)).toThrow( + "Drives.list: Drive list is not safe.", + ); expect(list.mock.calls).toHaveLength(1); expect(list.mock.calls[0][0]).toStrictEqual({}); @@ -132,7 +134,9 @@ test("list throws an error on an invalid drive list", () => { global.Drive = mockedDrive(); const list = vi.mocked(global.Drive.Drives).list.mockReturnValueOnce({}); - expect(() => SafeDrivesCollection_.list(null)).toThrow(""); + expect(() => SafeDrivesCollection_.list(null)).toThrow( + "Drives.list: Drive list is not safe.", + ); expect(list.mock.calls).toHaveLength(1); expect(list.mock.calls[0][0]).toStrictEqual({}); diff --git a/tests/backend/utils/SafeDriveService/SafeFilesCollection.test.ts b/tests/backend/utils/SafeDriveService/SafeFilesCollection.test.ts index 52660878..e1bf1229 100644 --- a/tests/backend/utils/SafeDriveService/SafeFilesCollection.test.ts +++ b/tests/backend/utils/SafeDriveService/SafeFilesCollection.test.ts @@ -93,7 +93,9 @@ test("copy throws and error on invalid file", () => { global.Drive = mockedDrive(); const copy = vi.mocked(global.Drive.Files).copy.mockReturnValueOnce(file); - expect(() => SafeFilesCollection_.copy(file, "TARGET_ID", null)).toThrow(""); + expect(() => SafeFilesCollection_.copy(file, "TARGET_ID", null)).toThrow( + "Files.copy: File is not safe.", + ); expect(copy.mock.calls).toHaveLength(1); expect(copy.mock.calls[0][0]).toBe(file); @@ -174,7 +176,9 @@ test("get throws an error on invalid file", () => { global.Drive = mockedDrive(); const get = vi.mocked(global.Drive.Files).get.mockReturnValueOnce(file); - expect(() => SafeFilesCollection_.get("FILE_ID", null)).toThrow(""); + expect(() => SafeFilesCollection_.get("FILE_ID", null)).toThrow( + "Files.get: File is not safe.", + ); expect(get.mock.calls).toHaveLength(1); expect(get.mock.calls[0][0]).toBe("FILE_ID"); @@ -268,7 +272,9 @@ test("create throws an error on invalid file", () => { global.Drive = mockedDrive(); const create = vi.mocked(global.Drive.Files).create.mockReturnValueOnce(file); - expect(() => SafeFilesCollection_.create(file, null)).toThrow(""); + expect(() => SafeFilesCollection_.create(file, null)).toThrow( + "Files.create: File is not safe.", + ); expect(create.mock.calls).toHaveLength(1); expect(create.mock.calls[0][0]).toBe(file); @@ -408,7 +414,9 @@ test("list throws an error on invalid file", () => { global.Drive = mockedDrive(); const list = vi.mocked(global.Drive.Files).list.mockReturnValueOnce(fileList); - expect(() => SafeFilesCollection_.list(null)).toThrow(""); + expect(() => SafeFilesCollection_.list(null)).toThrow( + "Files.list: File list is not safe.", + ); expect(list.mock.calls).toHaveLength(1); expect(list.mock.calls[0][0]).toStrictEqual({}); @@ -420,7 +428,9 @@ test("list throws an error on invalid file list", () => { global.Drive = mockedDrive(); const list = vi.mocked(global.Drive.Files).list.mockReturnValueOnce(fileList); - expect(() => SafeFilesCollection_.list(null)).toThrow(""); + expect(() => SafeFilesCollection_.list(null)).toThrow( + "Files.list: File list is not safe.", + ); expect(list.mock.calls).toHaveLength(1); expect(list.mock.calls[0][0]).toStrictEqual({}); @@ -526,7 +536,9 @@ test("update throws an error on invalid file", () => { global.Drive = mockedDrive(); const update = vi.mocked(global.Drive.Files).update.mockReturnValueOnce(file); - expect(() => SafeFilesCollection_.update(file, "FILE_ID", null)).toThrow(""); + expect(() => SafeFilesCollection_.update(file, "FILE_ID", null)).toThrow( + "Files.update: File is not safe.", + ); expect(update.mock.calls).toHaveLength(1); expect(update.mock.calls[0][0]).toBe(file); From 9f60cb39fe3911431676631c57e66ce84696e553 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20D=C4=9Bdi=C4=8D?= Date: Wed, 5 Feb 2025 21:04:09 +0100 Subject: [PATCH 8/9] Added support for safe partial responses to SafeCommentsCollection --- src/backend/move/copyFileComments.ts | 44 +++++-- .../SafeCommentsCollection.ts | 59 ++++++---- tests/backend/move/copyFileComments.test.ts | 73 +++++++----- .../test-utils/SafeDriveService-stub.ts | 39 ++++--- .../SafeCommentsCollection.test.ts | 107 +++++++++++++----- 5 files changed, 219 insertions(+), 103 deletions(-) diff --git a/src/backend/move/copyFileComments.ts b/src/backend/move/copyFileComments.ts index e709cd98..bd8c5d17 100644 --- a/src/backend/move/copyFileComments.ts +++ b/src/backend/move/copyFileComments.ts @@ -1,3 +1,4 @@ +import type { DeepPick } from "../utils/DeepPick"; import type { SafeComment, SafeCommentList, @@ -6,6 +7,18 @@ import type { import { paginationHelper_ } from "../utils/paginationHelper"; +interface CommentKeys { + anchor: true; + author: { + displayName: true; + me: true; + }; + content: true; + quotedFileContent: true; + replies: true; + resolved: true; +} + export function copyFileComments_( sourceID: string, destinationID: string, @@ -31,15 +44,30 @@ export function copyFileComments_( function listFileComments_( fileID: string, driveService: SafeDriveService_, -): Array { - return paginationHelper_( +): Array> { + return paginationHelper_< + SafeCommentList, + DeepPick + >( (pageToken) => - driveService.Comments.list(fileID, { - fields: - "nextPageToken, comments(author(me, displayName), content, resolved, quotedFileContent, anchor, replies(author(me, displayName), content, action))", - maxResults: 100, - pageToken, - }), + driveService.Comments.list( + fileID, + { + anchor: true, + author: { + displayName: true, + me: true, + }, + content: true, + quotedFileContent: true, + replies: true, + resolved: true, + }, + { + maxResults: 100, + pageToken, + }, + ), (response) => response.comments, ); } diff --git a/src/backend/utils/SafeDriveService/SafeCommentsCollection.ts b/src/backend/utils/SafeDriveService/SafeCommentsCollection.ts index 43a8853d..60aa0217 100644 --- a/src/backend/utils/SafeDriveService/SafeCommentsCollection.ts +++ b/src/backend/utils/SafeDriveService/SafeCommentsCollection.ts @@ -1,12 +1,23 @@ +import type { DeepKeyof } from "../DeepKeyof"; +import type { DeepPick } from "../DeepPick"; + +import { stringifyFields_ } from "./stringifyFields"; + export interface SafeComment { + anchor: string; author: SafeUser; content: string; id: string; + quotedFileContent: { + mimeType: string; + value: string; + }; replies: Array; + resolved: boolean; } -export interface SafeCommentList { - comments: Array; +export interface SafeCommentList> { + comments: Array>; nextPageToken?: string | undefined; } @@ -20,23 +31,27 @@ interface SafeUser { me: boolean; } -function commentIsSafe_( +function commentIsSafe_>( comment: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Comment, -): comment is SafeComment { + keys: F, +): comment is DeepPick { return ( - comment.author !== undefined && - userIsSafe_(comment.author) && - comment.id !== undefined && - comment.content !== undefined && - comment.replies?.every((reply) => commentReplyIsSafe_(reply)) === true + (keys.author !== true || + (comment.author !== undefined && userIsSafe_(comment.author))) && + (keys.id !== true || comment.id !== undefined) && + (keys.content !== true || comment.content !== undefined) && + (keys.replies !== true || + comment.replies?.every((reply) => commentReplyIsSafe_(reply)) === true) ); } -function commentListIsSafe_( +function commentListIsSafe_>( commentList: GoogleAppsScript.Drive_v3.Drive.V3.Schema.CommentList, -): commentList is SafeCommentList { + keys: F, +): commentList is SafeCommentList { return ( - commentList.comments?.every((comment) => commentIsSafe_(comment)) === true + commentList.comments?.every((comment) => commentIsSafe_(comment, keys)) === + true ); } @@ -57,27 +72,31 @@ function userIsSafe_( } export const SafeCommentsCollection_ = { - create: ( + create: >( resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Comment, fileId: string, - ): SafeComment => { + fields: F, + ): DeepPick => { const ret = Drive.Comments.create(resource, fileId); - if (!commentIsSafe_(ret)) { + if (!commentIsSafe_(ret, fields)) { throw new Error("Comments.create: Comment is not safe."); } return ret; }, - list: ( + list: >( fileId: string, + fields: F, optionalArgs: { - fields?: string; maxResults?: number; pageToken?: string | undefined; } = {}, - ): SafeCommentList => { - const ret = Drive.Comments.list(fileId, optionalArgs); - if (!commentListIsSafe_(ret)) { + ): SafeCommentList => { + const ret = Drive.Comments.list(fileId, { + ...optionalArgs, + fields: `nextPageToken, comments(${stringifyFields_(fields)})`, + }); + if (!commentListIsSafe_(ret, fields)) { throw new Error("Comments.list: Comment list is not safe."); } return ret; diff --git a/tests/backend/move/copyFileComments.test.ts b/tests/backend/move/copyFileComments.test.ts index 364d9eee..e09edae2 100644 --- a/tests/backend/move/copyFileComments.test.ts +++ b/tests/backend/move/copyFileComments.test.ts @@ -51,27 +51,26 @@ test("copyFileComments works correctly", () => { ); expect( vi.mocked(driveServiceMock.Comments.list).mock.calls[0][1], + ).toStrictEqual({ + anchor: true, + author: { + displayName: true, + me: true, + }, + content: true, + quotedFileContent: true, + replies: true, + resolved: true, + }); + expect( + vi.mocked(driveServiceMock.Comments.list).mock.calls[0][2], ).toBeDefined(); expect( ( vi.mocked(driveServiceMock.Comments.list).mock - .calls[0][1] as ListCommentsOptions + .calls[0][2] as ListCommentsOptions ).pageToken, ).toBeUndefined(); - expect( - ( - vi.mocked(driveServiceMock.Comments.list).mock - .calls[0][1] as ListCommentsOptions - ).fields, - ).toBeDefined(); - expect( - ( - vi.mocked(driveServiceMock.Comments.list).mock - .calls[0][1] as ListCommentsOptions - ).fields - ?.split(",") - .map((s) => s.trim()), - ).toContain("nextPageToken"); expect(vi.mocked(driveServiceMock.Comments.create).mock.calls).toHaveLength( 2, ); @@ -84,6 +83,9 @@ test("copyFileComments works correctly", () => { expect(vi.mocked(driveServiceMock.Comments.create).mock.calls[0][1]).toBe( "DEST_FILE_ID", ); + expect(vi.mocked(driveServiceMock.Comments.create).mock.calls[0][2].id).toBe( + true, + ); expect( vi.mocked(driveServiceMock.Comments.create).mock.calls[1][0].content, ).toBe("COM2_CONTENT"); @@ -93,6 +95,9 @@ test("copyFileComments works correctly", () => { expect(vi.mocked(driveServiceMock.Comments.create).mock.calls[1][1]).toBe( "DEST_FILE_ID", ); + expect(vi.mocked(driveServiceMock.Comments.create).mock.calls[1][2].id).toBe( + true, + ); }); test("copyFileComments works correctly with replies", () => { @@ -140,27 +145,26 @@ test("copyFileComments works correctly with replies", () => { ); expect( vi.mocked(driveServiceMock.Comments.list).mock.calls[0][1], + ).toStrictEqual({ + anchor: true, + author: { + displayName: true, + me: true, + }, + content: true, + quotedFileContent: true, + replies: true, + resolved: true, + }); + expect( + vi.mocked(driveServiceMock.Comments.list).mock.calls[0][2], ).toBeDefined(); expect( ( vi.mocked(driveServiceMock.Comments.list).mock - .calls[0][1] as ListCommentsOptions + .calls[0][2] as ListCommentsOptions ).pageToken, ).toBeUndefined(); - expect( - ( - vi.mocked(driveServiceMock.Comments.list).mock - .calls[0][1] as ListCommentsOptions - ).fields, - ).toBeDefined(); - expect( - ( - vi.mocked(driveServiceMock.Comments.list).mock - .calls[0][1] as ListCommentsOptions - ).fields - ?.split(",") - .map((s) => s.trim()), - ).toContain("nextPageToken"); expect(vi.mocked(driveServiceMock.Comments.create).mock.calls).toHaveLength( 1, ); @@ -173,6 +177,9 @@ test("copyFileComments works correctly with replies", () => { expect(vi.mocked(driveServiceMock.Comments.create).mock.calls[0][1]).toBe( "DEST_FILE_ID", ); + expect(vi.mocked(driveServiceMock.Comments.create).mock.calls[0][2].id).toBe( + true, + ); expect(vi.mocked(driveServiceMock.Replies.create).mock.calls).toHaveLength(2); expect( vi.mocked(driveServiceMock.Replies.create).mock.calls[0][0].content, @@ -183,6 +190,9 @@ test("copyFileComments works correctly with replies", () => { expect(vi.mocked(driveServiceMock.Replies.create).mock.calls[0][2]).toBe( "DEST_COM_ID", ); + expect( + vi.mocked(driveServiceMock.Replies.create).mock.calls[0][3].fields, + ).toContain("id"); expect( vi.mocked(driveServiceMock.Replies.create).mock.calls[1][0].content, ).toBe("REPLY2_CONTENT"); @@ -192,4 +202,7 @@ test("copyFileComments works correctly with replies", () => { expect(vi.mocked(driveServiceMock.Replies.create).mock.calls[1][2]).toBe( "DEST_COM_ID", ); + expect( + vi.mocked(driveServiceMock.Replies.create).mock.calls[1][3].fields, + ).toContain("id"); }); diff --git a/tests/backend/test-utils/SafeDriveService-stub.ts b/tests/backend/test-utils/SafeDriveService-stub.ts index 77ec8e12..9f38cbfb 100644 --- a/tests/backend/test-utils/SafeDriveService-stub.ts +++ b/tests/backend/test-utils/SafeDriveService-stub.ts @@ -14,8 +14,10 @@ import type { import { mockedRepliesCollection } from "./gas-stubs"; export function mockedSafeDriveService< - // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters -- No other way to pass F to vi.fn() - F extends DeepKeyof, + /* eslint-disable @typescript-eslint/no-unnecessary-type-parameters -- No other way to pass F to vi.fn() */ + CommentKeyof extends DeepKeyof, + FileKeyof extends DeepKeyof, + /* eslint-enable */ >(): MockedObject { // eslint-disable-next-line vitest/prefer-vi-mocked -- Acceptable as return value return { @@ -25,22 +27,27 @@ export function mockedSafeDriveService< ( resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.Comment, fileId: string, - ) => SafeComment + fields: CommentKeyof, + ) => DeepPick >(), list: vi.fn< - (fileId: string, optionalArgs: Record) => SafeCommentList + ( + fileId: string, + fields: CommentKeyof, + optionalArgs: { maxResults?: number; pageToken?: string | undefined }, + ) => SafeCommentList >(), }, Drives: { list: vi.fn< ( - fields: F | null, + fields: FileKeyof | null, optionalArgs?: { maxResults?: number; orderBy?: string; pageToken?: string; }, - ) => SafeDriveList + ) => SafeDriveList >(), }, Files: { @@ -48,31 +55,31 @@ export function mockedSafeDriveService< ( resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.File, fileId: string, - fields: F | null, + fields: FileKeyof | null, optionalArgs?: { supportsAllDrives?: boolean }, - ) => DeepPick + ) => DeepPick >(), create: vi.fn< ( resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.File, - fields: F | null, + fields: FileKeyof | null, // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Required by the Drive API mediaData?: any, optionalArgs?: { supportsAllDrives?: boolean; }, - ) => DeepPick + ) => DeepPick >(), get: vi.fn< ( fileId: string, - fields: F | null, + fields: FileKeyof | null, optionalArgs?: { alt?: string }, - ) => DeepPick + ) => DeepPick >(), list: vi.fn< ( - fields: F | null, + fields: FileKeyof | null, optionalArgs?: { includeItemsFromAllDrives?: boolean; maxResults?: number; @@ -80,14 +87,14 @@ export function mockedSafeDriveService< q?: string; supportsAllDrives?: boolean; }, - ) => SafeFileList + ) => SafeFileList >(), remove: vi.fn<(fileId: string) => void>(), update: vi.fn< ( resource: GoogleAppsScript.Drive_v3.Drive.V3.Schema.File, fileId: string, - fields: F | null, + fields: FileKeyof | null, // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Required by the Drive API mediaData?: any, optionalArgs?: { @@ -95,7 +102,7 @@ export function mockedSafeDriveService< removeParents?: string; supportsAllDrives?: boolean; }, - ) => DeepPick + ) => DeepPick >(), }, Replies: mockedRepliesCollection(), diff --git a/tests/backend/utils/SafeDriveService/SafeCommentsCollection.test.ts b/tests/backend/utils/SafeDriveService/SafeCommentsCollection.test.ts index b14ac980..023200fe 100644 --- a/tests/backend/utils/SafeDriveService/SafeCommentsCollection.test.ts +++ b/tests/backend/utils/SafeDriveService/SafeCommentsCollection.test.ts @@ -27,9 +27,14 @@ test("create works", () => { .mocked(global.Drive.Comments) .create.mockReturnValueOnce(comment); - expect(SafeCommentsCollection_.create(comment, "FILE_ID")).toStrictEqual( - comment, - ); + expect( + SafeCommentsCollection_.create(comment, "FILE_ID", { + author: true, + content: true, + id: true, + replies: true, + }), + ).toStrictEqual(comment); expect(create.mock.calls).toHaveLength(1); expect(create.mock.calls[0][0]).toBe(comment); @@ -59,9 +64,14 @@ test("create throws an error on an invalid comment", () => { .mocked(global.Drive.Comments) .create.mockReturnValueOnce(comment); - expect(() => SafeCommentsCollection_.create(comment, "FILE_ID")).toThrow( - "Comments.create: Comment is not safe.", - ); + expect(() => + SafeCommentsCollection_.create(comment, "FILE_ID", { + author: true, + content: true, + id: true, + replies: true, + }), + ).toThrow("Comments.create: Comment is not safe."); expect(create.mock.calls).toHaveLength(1); expect(create.mock.calls[0][0]).toBe(comment); @@ -113,11 +123,20 @@ test("list works", () => { .mocked(global.Drive.Comments) .list.mockReturnValueOnce(commentList); - expect(SafeCommentsCollection_.list("FILE_ID")).toStrictEqual(commentList); + expect( + SafeCommentsCollection_.list("FILE_ID", { + author: true, + content: true, + id: true, + replies: true, + }), + ).toStrictEqual(commentList); expect(list.mock.calls).toHaveLength(1); expect(list.mock.calls[0][0]).toBe("FILE_ID"); - expect(list.mock.calls[0][1]).toStrictEqual({}); + expect(list.mock.calls[0][1]).toStrictEqual({ + fields: "nextPageToken, comments(author, content, id, replies)", + }); }); test("list works with optional arguments", () => { @@ -166,18 +185,20 @@ test("list works with optional arguments", () => { .list.mockReturnValueOnce(commentList); const optionalArgs = { - fields: "comments(id)", maxResults: 100, pageToken: "TOKEN", }; - expect(SafeCommentsCollection_.list("FILE_ID", optionalArgs)).toStrictEqual( - commentList, - ); + expect( + SafeCommentsCollection_.list("FILE_ID", { id: true }, optionalArgs), + ).toStrictEqual(commentList); expect(list.mock.calls).toHaveLength(1); expect(list.mock.calls[0][0]).toBe("FILE_ID"); - expect(list.mock.calls[0][1]).toBe(optionalArgs); + expect(list.mock.calls[0][1]).toStrictEqual({ + ...optionalArgs, + fields: "nextPageToken, comments(id)", + }); }); test("list throws an error on an invalid comment", () => { @@ -224,13 +245,20 @@ test("list throws an error on an invalid comment", () => { .mocked(global.Drive.Comments) .list.mockReturnValueOnce(commentList); - expect(() => SafeCommentsCollection_.list("FILE_ID")).toThrow( - "Comments.list: Comment list is not safe.", - ); + expect(() => + SafeCommentsCollection_.list("FILE_ID", { + author: true, + content: true, + id: true, + replies: true, + }), + ).toThrow("Comments.list: Comment list is not safe."); expect(list.mock.calls).toHaveLength(1); expect(list.mock.calls[0][0]).toBe("FILE_ID"); - expect(list.mock.calls[0][1]).toStrictEqual({}); + expect(list.mock.calls[0][1]).toStrictEqual({ + fields: "nextPageToken, comments(author, content, id, replies)", + }); }); test("list throws an error on an invalid comment list", () => { @@ -243,13 +271,20 @@ test("list throws an error on an invalid comment list", () => { .mocked(global.Drive.Comments) .list.mockReturnValueOnce(commentList); - expect(() => SafeCommentsCollection_.list("FILE_ID")).toThrow( - "Comments.list: Comment list is not safe.", - ); + expect(() => + SafeCommentsCollection_.list("FILE_ID", { + author: true, + content: true, + id: true, + replies: true, + }), + ).toThrow("Comments.list: Comment list is not safe."); expect(list.mock.calls).toHaveLength(1); expect(list.mock.calls[0][0]).toBe("FILE_ID"); - expect(list.mock.calls[0][1]).toStrictEqual({}); + expect(list.mock.calls[0][1]).toStrictEqual({ + fields: "nextPageToken, comments(author, content, id, replies)", + }); }); test("list throws an error on missing replies", () => { @@ -288,13 +323,20 @@ test("list throws an error on missing replies", () => { .mocked(global.Drive.Comments) .list.mockReturnValueOnce(commentList); - expect(() => SafeCommentsCollection_.list("FILE_ID")).toThrow( - "Comments.list: Comment list is not safe.", - ); + expect(() => + SafeCommentsCollection_.list("FILE_ID", { + author: true, + content: true, + id: true, + replies: true, + }), + ).toThrow("Comments.list: Comment list is not safe."); expect(list.mock.calls).toHaveLength(1); expect(list.mock.calls[0][0]).toBe("FILE_ID"); - expect(list.mock.calls[0][1]).toStrictEqual({}); + expect(list.mock.calls[0][1]).toStrictEqual({ + fields: "nextPageToken, comments(author, content, id, replies)", + }); }); test("list throws an error on an invalid reply", () => { @@ -341,11 +383,18 @@ test("list throws an error on an invalid reply", () => { .mocked(global.Drive.Comments) .list.mockReturnValueOnce(commentList); - expect(() => SafeCommentsCollection_.list("FILE_ID")).toThrow( - "Comments.list: Comment list is not safe.", - ); + expect(() => + SafeCommentsCollection_.list("FILE_ID", { + author: true, + content: true, + id: true, + replies: true, + }), + ).toThrow("Comments.list: Comment list is not safe."); expect(list.mock.calls).toHaveLength(1); expect(list.mock.calls[0][0]).toBe("FILE_ID"); - expect(list.mock.calls[0][1]).toStrictEqual({}); + expect(list.mock.calls[0][1]).toStrictEqual({ + fields: "nextPageToken, comments(author, content, id, replies)", + }); }); From 186b2dc1ffdabfb94a6d037b63d35cca79ac52ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20D=C4=9Bdi=C4=8D?= Date: Wed, 5 Feb 2025 21:06:37 +0100 Subject: [PATCH 9/9] Providing fields argument to Drive.Comments.create and Drive.Replies.create --- src/backend/move/copyFileComments.ts | 8 ++++++-- .../utils/SafeDriveService/SafeCommentsCollection.ts | 4 +++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/backend/move/copyFileComments.ts b/src/backend/move/copyFileComments.ts index bd8c5d17..9cbf24cc 100644 --- a/src/backend/move/copyFileComments.ts +++ b/src/backend/move/copyFileComments.ts @@ -31,12 +31,16 @@ export function copyFileComments_( } const replies = comment.replies; comment.replies = []; - const commentId = driveService.Comments.create(comment, destinationID).id; + const commentId = driveService.Comments.create(comment, destinationID, { + id: true, + }).id; for (const reply of replies) { if (!reply.author.me) { reply.content = `*${reply.author.displayName}:*\n${reply.content}`; } - driveService.Replies.create(reply, destinationID, commentId); + driveService.Replies.create(reply, destinationID, commentId, { + fields: "id", + }); } } } diff --git a/src/backend/utils/SafeDriveService/SafeCommentsCollection.ts b/src/backend/utils/SafeDriveService/SafeCommentsCollection.ts index 60aa0217..60125072 100644 --- a/src/backend/utils/SafeDriveService/SafeCommentsCollection.ts +++ b/src/backend/utils/SafeDriveService/SafeCommentsCollection.ts @@ -77,7 +77,9 @@ export const SafeCommentsCollection_ = { fileId: string, fields: F, ): DeepPick => { - const ret = Drive.Comments.create(resource, fileId); + const ret = Drive.Comments.create(resource, fileId, { + fields: stringifyFields_(fields), + }); if (!commentIsSafe_(ret, fields)) { throw new Error("Comments.create: Comment is not safe."); }