070959e133
landing-page-staging / Deploy landing page to staging (push) Has been skipped
landing-page-ci / Validate landing page (push) Failing after 4s
visual-baseline / Capture visual baselines (push) Has been cancelled
bake-plugin-previews / Bake plugin previews (push) Has been cancelled
35 lines
1.8 KiB
TypeScript
35 lines
1.8 KiB
TypeScript
// Red-spec for the design-kit upload bug (broken "upload" image tiles): the
|
|
// single-file upload route POST /api/projects/:id/files resolved the caller's
|
|
// desired name with sanitizeName(), which replaces "/" with "_". A kit upload
|
|
// sends name="imagery/hero.png" so the file landed at the project root as
|
|
// "imagery_hero.png" while brand.json still referenced "imagery/hero.png" — the
|
|
// gallery <img> then 404'd and rendered the broken-image glyph, and finalize's
|
|
// copyProjectDirToBrand('imagery') missed the orphaned root file entirely.
|
|
//
|
|
// The fix routes path-bearing names through sanitizePath(), which sanitizes each
|
|
// segment but PRESERVES the directory separator. This test pins that contract:
|
|
// a subdirectory in the desired name must survive name resolution.
|
|
|
|
import { describe, expect, it } from 'vitest';
|
|
import { sanitizeName, sanitizePath } from '../src/projects.js';
|
|
|
|
describe('project upload name resolution preserves subdirectories', () => {
|
|
it('sanitizeName flattens a subdirectory path (the pre-fix behavior)', () => {
|
|
// Documents WHY the route must not use sanitizeName for a path-bearing name.
|
|
expect(sanitizeName('imagery/hero.png')).toBe('imagery_hero.png');
|
|
});
|
|
|
|
it('sanitizePath keeps the subdirectory the design-kit uploader intends', () => {
|
|
expect(sanitizePath('imagery/hero.png')).toBe('imagery/hero.png');
|
|
expect(sanitizePath('logos/wordmark.svg')).toBe('logos/wordmark.svg');
|
|
});
|
|
|
|
it('sanitizePath rejects traversal and sanitizes each segment', () => {
|
|
// A "../" escape is refused outright (the route's try/catch turns this into
|
|
// an error response) rather than silently mangled, and ordinary segments
|
|
// are still cleaned of whitespace/garbage.
|
|
expect(() => sanitizePath('imagery/../evil.png')).toThrow();
|
|
expect(sanitizePath('imagery/he ro.png')).toBe('imagery/he-ro.png');
|
|
});
|
|
});
|