feat(photos): добавить эффекты и настройки панели редактора
- текстура, чёткость, дымка, виньетка и зерно в неразрушающем редакторе - живой WebGL2-предпросмотр эффектов и CPU-фолбэк - секции редактора свёрнуты по умолчанию, состояние в localStorage - вкладка «Редактирование» доступна только из просмотрщика
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import {
|
||||
defaultSectionCollapse,
|
||||
EDITOR_SECTIONS_KEY,
|
||||
loadSectionCollapse,
|
||||
normalizeSectionCollapse,
|
||||
saveSectionCollapse
|
||||
} from './editor-sections';
|
||||
|
||||
function memoryStorage(initial: Record<string, string> = {}) {
|
||||
const data = new Map(Object.entries(initial));
|
||||
return {
|
||||
data,
|
||||
getItem(key: string) {
|
||||
return data.has(key) ? data.get(key)! : null;
|
||||
},
|
||||
setItem(key: string, value: string) {
|
||||
data.set(key, value);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
describe('секции редактора', () => {
|
||||
it('по умолчанию все секции свёрнуты', () => {
|
||||
const state = defaultSectionCollapse();
|
||||
for (const section of [
|
||||
'light',
|
||||
'curve',
|
||||
'color',
|
||||
'mixer',
|
||||
'pointColor',
|
||||
'correction',
|
||||
'effects'
|
||||
] as const) {
|
||||
expect(state[section]).toBe(true);
|
||||
}
|
||||
expect(loadSectionCollapse(null)).toEqual(defaultSectionCollapse());
|
||||
});
|
||||
|
||||
it('читает сохранённое состояние и восстанавливает недостающие ключи', () => {
|
||||
const storage = memoryStorage({
|
||||
[EDITOR_SECTIONS_KEY]: JSON.stringify({ effects: false, light: false, unknown: false })
|
||||
});
|
||||
const state = loadSectionCollapse(storage);
|
||||
expect(state.effects).toBe(false);
|
||||
expect(state.light).toBe(false);
|
||||
expect(state.color).toBe(true);
|
||||
expect('unknown' in state).toBe(false);
|
||||
});
|
||||
|
||||
it('игнорирует невалидный JSON и небулевы значения', () => {
|
||||
expect(
|
||||
loadSectionCollapse(memoryStorage({ [EDITOR_SECTIONS_KEY]: '{oops' }))
|
||||
).toEqual(defaultSectionCollapse());
|
||||
expect(normalizeSectionCollapse({ effects: 'no', color: 1 })).toEqual(
|
||||
defaultSectionCollapse()
|
||||
);
|
||||
expect(normalizeSectionCollapse(null)).toEqual(defaultSectionCollapse());
|
||||
});
|
||||
|
||||
it('сохраняет состояние в хранилище', () => {
|
||||
const storage = memoryStorage();
|
||||
const state = { ...defaultSectionCollapse(), effects: false, curve: false };
|
||||
saveSectionCollapse(state, storage);
|
||||
expect(storage.data.get(EDITOR_SECTIONS_KEY)).toBe(JSON.stringify(state));
|
||||
expect(loadSectionCollapse(storage)).toEqual(state);
|
||||
});
|
||||
|
||||
it('переживает недоступное хранилище', () => {
|
||||
const broken = {
|
||||
getItem() {
|
||||
throw new Error('denied');
|
||||
},
|
||||
setItem() {
|
||||
throw new Error('denied');
|
||||
}
|
||||
};
|
||||
expect(loadSectionCollapse(broken)).toEqual(defaultSectionCollapse());
|
||||
expect(() => saveSectionCollapse(defaultSectionCollapse(), broken)).not.toThrow();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user