пофикшен персист
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
import { IRoute, navigate, parseRoute, persistOwnSelection, routeUrl } from './routing';
|
||||
import { IRoute, navigate, parseRoute, persistOwnStatus, persistOwnTab, routeUrl } from './routing';
|
||||
|
||||
// buildQuery/navigate читают и пишут window.location через history API, а
|
||||
// подвкладка/фильтр «Моих заявок» — ещё и localStorage (см. persistOwnSelection) —
|
||||
// сбрасываем оба перед каждым тестом, чтобы они не зависели от порядка запуска.
|
||||
// подвкладка/фильтр «Моих заявок» — ещё и localStorage (см. persistOwnTab/
|
||||
// persistOwnStatus) — сбрасываем оба перед каждым тестом, чтобы они не
|
||||
// зависели от порядка запуска.
|
||||
beforeEach(() => {
|
||||
window.history.replaceState({}, '', '/');
|
||||
window.localStorage.clear();
|
||||
@@ -128,38 +129,51 @@ describe('подвкладки и фильтр «Моих заявок»', () =>
|
||||
});
|
||||
});
|
||||
|
||||
describe('persistOwnSelection — запоминание подвкладки/фильтра между визитами', () => {
|
||||
describe('persistOwnTab/persistOwnStatus — запоминание подвкладки/фильтра между визитами', () => {
|
||||
it('без явного rptab в адресе подставляется запомненная подвкладка', () => {
|
||||
persistOwnSelection('rejected', undefined);
|
||||
persistOwnTab('rejected');
|
||||
expect(parseRoute('?rpnav=own').ownTab).toBe('rejected');
|
||||
});
|
||||
|
||||
it('без явного rpstatus подставляется запомненный фильтр (только на «Инициированных»)', () => {
|
||||
persistOwnSelection('created', 'Черновик');
|
||||
persistOwnStatus('Черновик');
|
||||
expect(parseRoute('?rpnav=own').ownStatus).toBe('Черновик');
|
||||
// На вкладках с решениями запомненный фильтр ни при чём — там его нет по смыслу.
|
||||
persistOwnSelection('approved', 'Черновик');
|
||||
persistOwnTab('approved');
|
||||
expect(parseRoute('?rpnav=own').ownStatus).toBeUndefined();
|
||||
});
|
||||
|
||||
it('явный параметр в адресе имеет приоритет над запомненным значением', () => {
|
||||
persistOwnSelection('rejected', undefined);
|
||||
persistOwnTab('rejected');
|
||||
expect(parseRoute('?rpnav=own&rptab=executed').ownTab).toBe('executed');
|
||||
});
|
||||
|
||||
it('очистка фильтра persistOwnSelection убирает его и из последующих parseRoute', () => {
|
||||
persistOwnSelection('created', 'Черновик');
|
||||
it('очистка фильтра persistOwnStatus убирает его и из последующих parseRoute', () => {
|
||||
persistOwnStatus('Черновик');
|
||||
expect(parseRoute('?rpnav=own').ownStatus).toBe('Черновик');
|
||||
|
||||
persistOwnSelection('created', undefined);
|
||||
persistOwnStatus(undefined);
|
||||
expect(parseRoute('?rpnav=own').ownStatus).toBeUndefined();
|
||||
});
|
||||
|
||||
it('запомненное значение не протекает за пределы раздела «Мои заявки»', () => {
|
||||
persistOwnSelection('rejected', undefined);
|
||||
persistOwnTab('rejected');
|
||||
expect(parseRoute('?rpnav=approvals').ownTab).toBeUndefined();
|
||||
});
|
||||
|
||||
// Ровно тот баг, который это всё затевалось починить: подвкладка «Инициированные»
|
||||
// с выбранным фильтром → уход на другую подвкладку → возврат — фильтр должен
|
||||
// остаться прежним, а не сброситься на «Все статусы» (см. RequestPortal.tsx/
|
||||
// gotoOwnTab — persistOwnTab НЕ трогает сохранённый статус).
|
||||
it('переключение на другую подвкладку и обратно не стирает запомненный фильтр', () => {
|
||||
persistOwnStatus('На согласовании');
|
||||
expect(parseRoute('?rpnav=own').ownStatus).toBe('На согласовании');
|
||||
|
||||
persistOwnTab('approved');
|
||||
persistOwnTab('created');
|
||||
expect(parseRoute('?rpnav=own').ownStatus).toBe('На согласовании');
|
||||
});
|
||||
|
||||
it('localStorage недоступен (например, приватный режим) — не роняет parseRoute', () => {
|
||||
const original = window.localStorage.getItem;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- имитация приватного режима, где чтение localStorage бросает
|
||||
|
||||
@@ -71,11 +71,21 @@ const ROUTE_CHANGE_EVENT = 'rp-route-change';
|
||||
// является единственным источником правды для ownTab/ownStatus (см.
|
||||
// buildQuery — он не пишет значения по умолчанию в адрес), поэтому именно тут,
|
||||
// где URL молчит, естественно спросить «а что было в прошлый раз».
|
||||
// Пишутся ТОЛЬКО через persistOwnSelection — то есть только там, где
|
||||
// пользователь СОЗНАТЕЛЬНО меняет вкладку/фильтр (см. gotoOwnTab/setOwnStatus
|
||||
// в RequestPortal.tsx), а не при каждой навигации: иначе, например, просто
|
||||
// открыв и закрыв заявку, можно было бы затереть запомненное значение
|
||||
// значением по умолчанию.
|
||||
// Пишутся ТОЛЬКО через persistOwnTab/persistOwnStatus — то есть только там,
|
||||
// где пользователь СОЗНАТЕЛЬНО меняет вкладку или фильтр (см.
|
||||
// gotoOwnTab/setOwnStatus в RequestPortal.tsx), а не при каждой навигации:
|
||||
// иначе, например, просто открыв и закрыв заявку, можно было бы затереть
|
||||
// запомненное значение значением по умолчанию.
|
||||
//
|
||||
// НАМЕРЕННО два отдельных сеттера, а не один persistOwnSelection(tab, status):
|
||||
// переключение НА подвкладку с решениями (approved/rejected/executed) должно
|
||||
// запомнить только её саму, не трогая фильтр статуса — тот относится
|
||||
// ИСКЛЮЧИТЕЛЬНО к «Инициированным» и при возврате туда должен найтись таким
|
||||
// же, каким был оставлен. Один сеттер этого не даёт: при переключении на
|
||||
// другую подвкладку он получал бы ownStatus=undefined (потому что на других
|
||||
// подвкладках фильтра просто нет) и стирал бы запомненное значение — что и
|
||||
// произошло на практике: уйдя с «Инициированных» на «Согласованные» и
|
||||
// вернувшись обратно, фильтр каждый раз сбрасывался на «Все статусы».
|
||||
const OWN_TAB_STORAGE_KEY = 'rp-own-tab';
|
||||
const OWN_STATUS_STORAGE_KEY = 'rp-own-status';
|
||||
|
||||
@@ -96,10 +106,18 @@ function readStoredOwnStatus(): string | undefined {
|
||||
}
|
||||
}
|
||||
|
||||
/** Запомнить подвкладку/фильтр «Моих заявок» — вызывать только при явном выборе пользователя. */
|
||||
export function persistOwnSelection(ownTab: OwnTab, ownStatus: string | undefined): void {
|
||||
/** Запомнить подвкладку «Моих заявок» — вызывать только при явном выборе пользователя. */
|
||||
export function persistOwnTab(ownTab: OwnTab): void {
|
||||
try {
|
||||
window.localStorage.setItem(OWN_TAB_STORAGE_KEY, ownTab);
|
||||
} catch {
|
||||
// localStorage недоступен (приватный режим и т.п.) — просто не сохраняем.
|
||||
}
|
||||
}
|
||||
|
||||
/** Запомнить фильтр по статусу вкладки «Инициированные» — вызывать только при явном выборе пользователя. */
|
||||
export function persistOwnStatus(ownStatus: string | undefined): void {
|
||||
try {
|
||||
if (ownStatus) {
|
||||
window.localStorage.setItem(OWN_STATUS_STORAGE_KEY, ownStatus);
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user