Files
ComfyUI_frontend/tests-ui/tests/composables/clipboard.test.ts
2025-12-08 17:13:24 -07:00

106 lines
3.5 KiB
TypeScript

import { describe, expect, it } from 'vitest'
/**
* Encodes a UTF-8 string to base64 (same logic as useCopy.ts)
*/
function encodeClipboardData(data: string): string {
return btoa(
String.fromCharCode(...Array.from(new TextEncoder().encode(data)))
)
}
/**
* Decodes base64 to UTF-8 string (same logic as usePaste.ts)
*/
function decodeClipboardData(base64: string): string {
const binaryString = atob(base64)
const bytes = Uint8Array.from(binaryString, (c) => c.charCodeAt(0))
return new TextDecoder().decode(bytes)
}
describe('Clipboard UTF-8 base64 encoding/decoding', () => {
it('should handle ASCII-only strings', () => {
const original = '{"nodes":[{"id":1,"type":"LoadImage"}]}'
const encoded = encodeClipboardData(original)
const decoded = decodeClipboardData(encoded)
expect(decoded).toBe(original)
})
it('should handle Chinese characters in localized_name', () => {
const original =
'{"nodes":[{"id":1,"type":"LoadImage","localized_name":"图像"}]}'
const encoded = encodeClipboardData(original)
const decoded = decodeClipboardData(encoded)
expect(decoded).toBe(original)
})
it('should handle Japanese characters', () => {
const original = '{"localized_name":"画像を読み込む"}'
const encoded = encodeClipboardData(original)
const decoded = decodeClipboardData(encoded)
expect(decoded).toBe(original)
})
it('should handle Korean characters', () => {
const original = '{"localized_name":"이미지 불러오기"}'
const encoded = encodeClipboardData(original)
const decoded = decodeClipboardData(encoded)
expect(decoded).toBe(original)
})
it('should handle mixed ASCII and Unicode characters', () => {
const original =
'{"nodes":[{"id":1,"type":"LoadImage","localized_name":"加载图像","label":"Load Image 图片"}]}'
const encoded = encodeClipboardData(original)
const decoded = decodeClipboardData(encoded)
expect(decoded).toBe(original)
})
it('should handle emoji characters', () => {
const original = '{"title":"Test Node 🎨🖼️"}'
const encoded = encodeClipboardData(original)
const decoded = decodeClipboardData(encoded)
expect(decoded).toBe(original)
})
it('should handle empty string', () => {
const original = ''
const encoded = encodeClipboardData(original)
const decoded = decodeClipboardData(encoded)
expect(decoded).toBe(original)
})
it('should handle complex node data with multiple Unicode fields', () => {
const original = JSON.stringify({
nodes: [
{
id: 1,
type: 'LoadImage',
localized_name: '图像',
inputs: [{ localized_name: '图片', name: 'image' }],
outputs: [{ localized_name: '输出', name: 'output' }]
}
],
groups: [{ title: '预处理组 🔧' }],
links: []
})
const encoded = encodeClipboardData(original)
const decoded = decodeClipboardData(encoded)
expect(decoded).toBe(original)
expect(JSON.parse(decoded)).toEqual(JSON.parse(original))
})
it('should produce valid base64 output', () => {
const original = '{"localized_name":"中文测试"}'
const encoded = encodeClipboardData(original)
// Base64 should only contain valid characters
expect(encoded).toMatch(/^[A-Za-z0-9+/=]+$/)
})
it('should fail with plain btoa for non-Latin1 characters', () => {
const original = '{"localized_name":"图像"}'
// This demonstrates why we need TextEncoder - plain btoa fails
expect(() => btoa(original)).toThrow()
})
})