-

- {path &&
{path}
}
+ {imageError ? (
+
+ ⚠️ {imageError}
+
+ ) : (
+

+ )}
+ {imagePath && (
+
{formatDisplayPath(imagePath)}
+ )}
{showControls && isHovering && (
setIsDragging(false)}
onMouseLeave={() => setIsDragging(false)}>
- {path && (
+ {imagePath && (
diff --git a/webview-ui/src/components/common/__tests__/ImageViewer.spec.tsx b/webview-ui/src/components/common/__tests__/ImageViewer.spec.tsx
new file mode 100644
index 000000000000..5f85978b741f
--- /dev/null
+++ b/webview-ui/src/components/common/__tests__/ImageViewer.spec.tsx
@@ -0,0 +1,116 @@
+// npx vitest run src/components/common/__tests__/ImageViewer.spec.tsx
+
+import { render, fireEvent } from "@testing-library/react"
+import { describe, it, expect, vi } from "vitest"
+import { ImageViewer } from "../ImageViewer"
+
+// Mock vscode API
+vi.mock("@src/utils/vscode", () => ({
+ vscode: {
+ postMessage: vi.fn(),
+ },
+}))
+
+// Import the mocked vscode after the mock is set up
+import { vscode } from "@src/utils/vscode"
+
+describe("ImageViewer", () => {
+ it("should render image with webview URI", () => {
+ const webviewUri = "https://file+.vscode-resource.vscode-cdn.net/path/to/image.png"
+ const { container } = render()
+
+ const img = container.querySelector("img")
+ expect(img).toBeTruthy()
+ expect(img?.src).toBe(webviewUri)
+ expect(img?.alt).toBe("Test image")
+ })
+
+ it("should render image with vscode-resource URI", () => {
+ const vscodeResourceUri = "vscode-resource://file///path/to/image.png"
+ const { container } = render()
+
+ const img = container.querySelector("img")
+ expect(img).toBeTruthy()
+ expect(img?.src).toBe(vscodeResourceUri)
+ })
+
+ it("should handle base64 images", () => {
+ const base64Image =
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg=="
+ const { container } = render()
+
+ const img = container.querySelector("img")
+ expect(img).toBeTruthy()
+ expect(img?.src).toBe(base64Image)
+ })
+
+ it("should use imageUri for rendering and imagePath for display", () => {
+ const webviewUri = "https://file+.vscode-resource.vscode-cdn.net/path/to/image.png"
+ const filePath = "/Users/test/project/image.png"
+ const { container } = render()
+
+ const img = container.querySelector("img")
+ expect(img).toBeTruthy()
+ // Should use imageUri for src
+ expect(img?.src).toBe(webviewUri)
+
+ // Should display imagePath below image
+ const pathElement = container.querySelector(".text-xs.text-vscode-descriptionForeground")
+ expect(pathElement).toBeTruthy()
+ expect(pathElement?.textContent).toContain("image.png")
+ })
+
+ it("should handle click to open in editor", () => {
+ const webviewUri = "https://file+.vscode-resource.vscode-cdn.net/path/to/image.png"
+ const filePath = "/Users/test/project/image.png"
+ const { container } = render()
+
+ const img = container.querySelector("img")
+ expect(img).toBeTruthy()
+
+ // Clear previous calls
+ vi.clearAllMocks()
+
+ // Click the image
+ fireEvent.click(img!)
+
+ // Check if vscode.postMessage was called to open the image with the actual path
+ expect(vscode.postMessage).toHaveBeenCalledWith({
+ type: "openImage",
+ text: filePath,
+ })
+ })
+
+ it("should handle error state gracefully", () => {
+ const invalidUri = "invalid://uri"
+ const { container } = render()
+
+ const img = container.querySelector("img")
+ expect(img).toBeTruthy()
+
+ // Trigger error event
+ fireEvent.error(img!)
+
+ // Image should still be rendered but might have error styling
+ expect(img).toBeTruthy()
+ })
+
+ it("should show no image message when imageUri is empty", () => {
+ const { container } = render()
+
+ // Should show no image message
+ expect(container.textContent).toContain("common:image.noData")
+ })
+
+ it("should display path below image when provided", () => {
+ const filePath = "/Users/test/rc1/path/to/image.png"
+ const webviewUri = "https://file+.vscode-resource.vscode-cdn.net/path/to/image.png"
+ const { container } = render()
+
+ // Check if path is displayed as relative path
+ const pathElement = container.querySelector(".text-xs.text-vscode-descriptionForeground")
+ expect(pathElement).toBeTruthy()
+ // Accept filename or relative path depending on environment
+ expect(pathElement?.textContent).toContain("image.png")
+ })
+})
diff --git a/webview-ui/src/i18n/locales/ca/common.json b/webview-ui/src/i18n/locales/ca/common.json
index c056a4432876..edf95df4a03c 100644
--- a/webview-ui/src/i18n/locales/ca/common.json
+++ b/webview-ui/src/i18n/locales/ca/common.json
@@ -51,7 +51,8 @@
"image": {
"tabs": {
"view": "Imatge"
- }
+ },
+ "noData": "Sense dades d'imatge"
},
"file": {
"errors": {
diff --git a/webview-ui/src/i18n/locales/de/common.json b/webview-ui/src/i18n/locales/de/common.json
index 85137922ffd0..b332d71413b7 100644
--- a/webview-ui/src/i18n/locales/de/common.json
+++ b/webview-ui/src/i18n/locales/de/common.json
@@ -51,7 +51,8 @@
"image": {
"tabs": {
"view": "Bild"
- }
+ },
+ "noData": "Keine Bilddaten"
},
"file": {
"errors": {
diff --git a/webview-ui/src/i18n/locales/en/common.json b/webview-ui/src/i18n/locales/en/common.json
index 973cb48297bf..a1830f1f912b 100644
--- a/webview-ui/src/i18n/locales/en/common.json
+++ b/webview-ui/src/i18n/locales/en/common.json
@@ -51,7 +51,8 @@
"image": {
"tabs": {
"view": "Image"
- }
+ },
+ "noData": "No image data"
},
"file": {
"errors": {
diff --git a/webview-ui/src/i18n/locales/es/common.json b/webview-ui/src/i18n/locales/es/common.json
index a293008d8a88..9beee73891f0 100644
--- a/webview-ui/src/i18n/locales/es/common.json
+++ b/webview-ui/src/i18n/locales/es/common.json
@@ -51,7 +51,8 @@
"image": {
"tabs": {
"view": "Imagen"
- }
+ },
+ "noData": "Sin datos de imagen"
},
"file": {
"errors": {
diff --git a/webview-ui/src/i18n/locales/fr/common.json b/webview-ui/src/i18n/locales/fr/common.json
index fd7f53dd976b..8bd04a2aeff1 100644
--- a/webview-ui/src/i18n/locales/fr/common.json
+++ b/webview-ui/src/i18n/locales/fr/common.json
@@ -51,7 +51,8 @@
"image": {
"tabs": {
"view": "Image"
- }
+ },
+ "noData": "Aucune donnée d'image"
},
"file": {
"errors": {
diff --git a/webview-ui/src/i18n/locales/hi/common.json b/webview-ui/src/i18n/locales/hi/common.json
index 15039dc9001a..55f1b5a71703 100644
--- a/webview-ui/src/i18n/locales/hi/common.json
+++ b/webview-ui/src/i18n/locales/hi/common.json
@@ -51,7 +51,8 @@
"image": {
"tabs": {
"view": "चित्र"
- }
+ },
+ "noData": "कोई छवि डेटा नहीं"
},
"file": {
"errors": {
diff --git a/webview-ui/src/i18n/locales/id/common.json b/webview-ui/src/i18n/locales/id/common.json
index 0dac9b2987c9..80104a87e021 100644
--- a/webview-ui/src/i18n/locales/id/common.json
+++ b/webview-ui/src/i18n/locales/id/common.json
@@ -51,7 +51,8 @@
"image": {
"tabs": {
"view": "Gambar"
- }
+ },
+ "noData": "Tidak ada data gambar"
},
"file": {
"errors": {
diff --git a/webview-ui/src/i18n/locales/it/common.json b/webview-ui/src/i18n/locales/it/common.json
index 9ac9cbadad1e..a913113708e2 100644
--- a/webview-ui/src/i18n/locales/it/common.json
+++ b/webview-ui/src/i18n/locales/it/common.json
@@ -51,7 +51,8 @@
"image": {
"tabs": {
"view": "Immagine"
- }
+ },
+ "noData": "Nessun dato immagine"
},
"file": {
"errors": {
diff --git a/webview-ui/src/i18n/locales/ja/common.json b/webview-ui/src/i18n/locales/ja/common.json
index a92a3cd79a58..210c828a21d6 100644
--- a/webview-ui/src/i18n/locales/ja/common.json
+++ b/webview-ui/src/i18n/locales/ja/common.json
@@ -51,7 +51,8 @@
"image": {
"tabs": {
"view": "画像"
- }
+ },
+ "noData": "画像データなし"
},
"file": {
"errors": {
diff --git a/webview-ui/src/i18n/locales/ko/common.json b/webview-ui/src/i18n/locales/ko/common.json
index e8a9b7c64b97..8f613c71398a 100644
--- a/webview-ui/src/i18n/locales/ko/common.json
+++ b/webview-ui/src/i18n/locales/ko/common.json
@@ -51,7 +51,8 @@
"image": {
"tabs": {
"view": "이미지"
- }
+ },
+ "noData": "이미지 데이터 없음"
},
"file": {
"errors": {
diff --git a/webview-ui/src/i18n/locales/nl/common.json b/webview-ui/src/i18n/locales/nl/common.json
index 12a6c74365f1..3c4bc490176d 100644
--- a/webview-ui/src/i18n/locales/nl/common.json
+++ b/webview-ui/src/i18n/locales/nl/common.json
@@ -51,7 +51,8 @@
"image": {
"tabs": {
"view": "Afbeelding"
- }
+ },
+ "noData": "Geen afbeeldingsgegevens"
},
"file": {
"errors": {
diff --git a/webview-ui/src/i18n/locales/pl/common.json b/webview-ui/src/i18n/locales/pl/common.json
index 410c8dbb9c05..8ada6155bfdb 100644
--- a/webview-ui/src/i18n/locales/pl/common.json
+++ b/webview-ui/src/i18n/locales/pl/common.json
@@ -51,7 +51,8 @@
"image": {
"tabs": {
"view": "Obraz"
- }
+ },
+ "noData": "Brak danych obrazu"
},
"file": {
"errors": {
diff --git a/webview-ui/src/i18n/locales/pt-BR/common.json b/webview-ui/src/i18n/locales/pt-BR/common.json
index 30d9b6dc6c1c..b4cfdbb1126c 100644
--- a/webview-ui/src/i18n/locales/pt-BR/common.json
+++ b/webview-ui/src/i18n/locales/pt-BR/common.json
@@ -51,7 +51,8 @@
"image": {
"tabs": {
"view": "Imagem"
- }
+ },
+ "noData": "Nenhum dado de imagem"
},
"file": {
"errors": {
diff --git a/webview-ui/src/i18n/locales/ru/common.json b/webview-ui/src/i18n/locales/ru/common.json
index 8cdb1431eb19..9a29b596c599 100644
--- a/webview-ui/src/i18n/locales/ru/common.json
+++ b/webview-ui/src/i18n/locales/ru/common.json
@@ -51,7 +51,8 @@
"image": {
"tabs": {
"view": "Изображение"
- }
+ },
+ "noData": "Нет данных изображения"
},
"file": {
"errors": {
diff --git a/webview-ui/src/i18n/locales/tr/common.json b/webview-ui/src/i18n/locales/tr/common.json
index 15f13fcdd36c..d268bf223f5e 100644
--- a/webview-ui/src/i18n/locales/tr/common.json
+++ b/webview-ui/src/i18n/locales/tr/common.json
@@ -51,7 +51,8 @@
"image": {
"tabs": {
"view": "Resim"
- }
+ },
+ "noData": "Resim verisi yok"
},
"file": {
"errors": {
diff --git a/webview-ui/src/i18n/locales/vi/common.json b/webview-ui/src/i18n/locales/vi/common.json
index a75e1e1f4acd..9815c23b6cb5 100644
--- a/webview-ui/src/i18n/locales/vi/common.json
+++ b/webview-ui/src/i18n/locales/vi/common.json
@@ -51,7 +51,8 @@
"image": {
"tabs": {
"view": "Hình ảnh"
- }
+ },
+ "noData": "Không có dữ liệu hình ảnh"
},
"file": {
"errors": {
diff --git a/webview-ui/src/i18n/locales/zh-CN/common.json b/webview-ui/src/i18n/locales/zh-CN/common.json
index 902bd7f7e068..afdb34794d7d 100644
--- a/webview-ui/src/i18n/locales/zh-CN/common.json
+++ b/webview-ui/src/i18n/locales/zh-CN/common.json
@@ -51,7 +51,8 @@
"image": {
"tabs": {
"view": "图像"
- }
+ },
+ "noData": "无图片数据"
},
"file": {
"errors": {
diff --git a/webview-ui/src/i18n/locales/zh-TW/common.json b/webview-ui/src/i18n/locales/zh-TW/common.json
index 9497d369a5bf..b9c9070c8e4c 100644
--- a/webview-ui/src/i18n/locales/zh-TW/common.json
+++ b/webview-ui/src/i18n/locales/zh-TW/common.json
@@ -51,7 +51,8 @@
"image": {
"tabs": {
"view": "圖像"
- }
+ },
+ "noData": "無圖片資料"
},
"file": {
"errors": {