feat: backend implementation for media manager v2 (WIP - Undeployed)
This commit is contained in:
@ -1,3 +1,4 @@
|
||||
|
||||
import { MediaService } from "./MediaService"
|
||||
import { MockDriveService } from "./MockDriveService"
|
||||
import { MockShopifyMediaService } from "./MockShopifyMediaService"
|
||||
@ -12,8 +13,9 @@ class MockNetworkService implements INetworkService {
|
||||
this.lastUrl = url
|
||||
this.lastPayload = params.payload
|
||||
return {
|
||||
getResponseCode: () => 200
|
||||
} as GoogleAppsScript.URL_Fetch.HTTPResponse
|
||||
getResponseCode: () => 200,
|
||||
getBlob: () => ({ getBytes: () => [], getContentType: () => "image/jpeg", setName: () => {} })
|
||||
} as unknown as GoogleAppsScript.URL_Fetch.HTTPResponse
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,28 +30,89 @@ describe("MediaService", () => {
|
||||
driveService = new MockDriveService()
|
||||
shopifyService = new MockShopifyMediaService()
|
||||
networkService = new MockNetworkService()
|
||||
config = { productPhotosFolderId: "root" } as Config // Mock config
|
||||
config = { productPhotosFolderId: "root" } as Config
|
||||
|
||||
mediaService = new MediaService(driveService, shopifyService, networkService, config)
|
||||
|
||||
// Global Mocks
|
||||
global.Utilities = {
|
||||
base64Encode: (b) => "base64",
|
||||
newBlob: (b, m, n) => ({
|
||||
getBytes: () => b,
|
||||
getContentType: () => m,
|
||||
getName: () => n,
|
||||
setName: () => {}
|
||||
})
|
||||
} as any
|
||||
global.Drive = { Files: { get: () => ({ appProperties: {} }) } } as any
|
||||
global.UrlFetchApp = networkService as unknown as GoogleAppsScript.URL_Fetch.UrlFetchApp
|
||||
})
|
||||
|
||||
test("syncMediaForSku uploads files from Drive to Shopify", () => {
|
||||
// Setup Drive State
|
||||
test("getUnifiedMediaState should match files", () => {
|
||||
const folder = driveService.getOrCreateFolder("SKU123", "root")
|
||||
const blob1 = { getName: () => "01.jpg", getMimeType: () => "image/jpeg", getBytes: () => [] } as unknown as GoogleAppsScript.Base.Blob
|
||||
const blob1 = { getName: () => "01.jpg", getMimeType: () => "image/jpeg", getBytes: () => [], getThumbnail: () => ({ getBytes: () => [] }) } as unknown as GoogleAppsScript.Base.Blob
|
||||
driveService.saveFile(blob1, folder.getId())
|
||||
|
||||
// Run Sync
|
||||
mediaService.syncMediaForSku("SKU123", "shopify_prod_id")
|
||||
|
||||
// Verify Network Call (Upload)
|
||||
expect(networkService.lastUrl).toBe("https://mock-upload.shopify.com")
|
||||
// Verify payload contained file
|
||||
expect(networkService.lastPayload).toHaveProperty("file")
|
||||
const state = mediaService.getUnifiedMediaState("SKU123", "pid")
|
||||
expect(state).toHaveLength(1)
|
||||
expect(state[0].filename).toBe("01.jpg")
|
||||
})
|
||||
|
||||
test("syncMediaForSku does nothing if no files", () => {
|
||||
mediaService.syncMediaForSku("SKU_EMPTY", "pid")
|
||||
expect(networkService.lastUrl).toBe("")
|
||||
test("processMediaChanges should handle deletions", () => {
|
||||
const folder = driveService.getOrCreateFolder("SKU123", "root")
|
||||
const blob1 = {
|
||||
getName: () => "delete_me.jpg",
|
||||
getId: () => "file_id_1",
|
||||
getMimeType: () => "image/jpeg",
|
||||
getBytes: () => [],
|
||||
getThumbnail: () => ({ getBytes: () => [] })
|
||||
} as unknown as GoogleAppsScript.Base.Blob
|
||||
driveService.saveFile(blob1, folder.getId())
|
||||
|
||||
// Update Shopify Mock to return this media
|
||||
shopifyService.getProductMedia = jest.fn().mockReturnValue([{
|
||||
id: "gid://shopify/Media/media_1",
|
||||
alt: "delete_me.jpg"
|
||||
}])
|
||||
|
||||
// Update global Drive to return synced ID
|
||||
global.Drive = { Files: { get: () => ({ appProperties: { shopify_media_id: "gid://shopify/Media/media_1" } }) } } as any
|
||||
|
||||
const finalState = []
|
||||
|
||||
const deleteSpy = jest.spyOn(shopifyService, 'productDeleteMedia')
|
||||
const trashSpy = jest.spyOn(driveService, 'trashFile')
|
||||
|
||||
mediaService.processMediaChanges("SKU123", finalState, "pid")
|
||||
|
||||
expect(deleteSpy).toHaveBeenCalled()
|
||||
expect(trashSpy).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
test("processMediaChanges should handle backfills (Shopify -> Drive)", () => {
|
||||
// Current state: Empty Drive, 1 Shopify Media
|
||||
shopifyService.getProductMedia = jest.fn().mockReturnValue([{
|
||||
id: "gid://shopify/Media/media_2",
|
||||
alt: "backfill.jpg",
|
||||
preview: { image: { originalSrc: "http://shopify.com/img.jpg" } }
|
||||
}])
|
||||
|
||||
// Final state: 1 item (the backfilled one)
|
||||
const finalState = [{
|
||||
id: "gid://shopify/Media/media_2",
|
||||
filename: "backfill.jpg",
|
||||
status: "synced"
|
||||
}]
|
||||
|
||||
// Mock network fetch for download
|
||||
jest.spyOn(networkService, 'fetch')
|
||||
|
||||
mediaService.processMediaChanges("SKU123", finalState, "pid")
|
||||
|
||||
// Should create file in Drive
|
||||
const folder = driveService.getOrCreateFolder("SKU123", "root")
|
||||
const files = driveService.getFiles(folder.getId())
|
||||
expect(files).toHaveLength(1)
|
||||
expect(files[0].getName()).toBe("backfill.jpg")
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user