54 lines
1.9 KiB
TypeScript
54 lines
1.9 KiB
TypeScript
import { describe, it, expect } from 'vitest'
|
|
import JSZip from 'jszip'
|
|
import { buildZip } from '@/lib/exporter/zip'
|
|
import type { BuildZipInput } from '@/lib/exporter/zip'
|
|
|
|
const TE = new TextEncoder()
|
|
|
|
describe('Export ZIP 검증 강화 4차: 루트 파일(favicon/manifest/robots)', () => {
|
|
it('루트 파일들을 포함한다: favicon.ico / site.webmanifest / robots.txt', async () => {
|
|
const manifest = {
|
|
name: 'Landing Builder',
|
|
short_name: 'LB',
|
|
start_url: '/',
|
|
display: 'standalone',
|
|
icons: [{ src: '/favicon.png', sizes: '512x512', type: 'image/png' }],
|
|
}
|
|
const input: BuildZipInput = {
|
|
html: '<!DOCTYPE html><html><head><title>a</title></head><body>ok</body></html>',
|
|
css: 'body{color:#111}',
|
|
js: 'console.log("ok")',
|
|
assets: {},
|
|
extras: {
|
|
'favicon.ico': new Uint8Array([0, 1, 2, 3]),
|
|
'site.webmanifest': TE.encode(JSON.stringify(manifest)),
|
|
'robots.txt': TE.encode('User-agent: *\nDisallow:'),
|
|
},
|
|
}
|
|
const zipBytes = await buildZip(input)
|
|
|
|
const zip = await JSZip.loadAsync(zipBytes)
|
|
const names = Object.keys(zip.files)
|
|
expect(names).toContain('favicon.ico')
|
|
expect(names).toContain('site.webmanifest')
|
|
expect(names).toContain('robots.txt')
|
|
|
|
const robots = await zip.files['robots.txt'].async('string')
|
|
expect(robots).toMatch(/User-agent: \*/)
|
|
|
|
const parsed = JSON.parse(await zip.files['site.webmanifest'].async('string'))
|
|
expect(parsed.name).toBe('Landing Builder')
|
|
expect(parsed.icons[0].type).toBe('image/png')
|
|
})
|
|
|
|
it('잘못된 manifest JSON이면 실패한다', async () => {
|
|
const badInput: BuildZipInput = {
|
|
html: '<!DOCTYPE html><html><head><title>a</title></head><body>ok</body></html>',
|
|
css: 'body{color:#111}',
|
|
js: 'console.log("ok")',
|
|
extras: { 'site.webmanifest': TE.encode('{ invalid json') },
|
|
}
|
|
await expect(buildZip(badInput)).rejects.toThrow()
|
|
})
|
|
})
|