Merge branch ''review/slice-1-recheck''

This commit is contained in:
Leonid Pershin
2026-08-21 09:34:03 +03:00
3 changed files with 89 additions and 9 deletions
+44
View File
@@ -2,6 +2,50 @@
Сводка: [`../reviewed.md`](../reviewed.md). Индекс среза: [`README.md`](README.md).
## Перепроверка среза 1 (после notices / portraits / Krea)
- **Фазы:** 04
- **Проверен на:** `5a0d75b`, 2026-08-21
- **Пути:** `src/HSchool.Client`, `src/HSchool.Protocol`, `src/HSchool.Content`,
`src/HSchool.Server/Game`, `src/HSchool.Server/Api/ModEndpoints.cs`,
`src/HSchool.Server/Api/SchoolEndpoints.cs`, `src/HSchool.Server/Net`,
`tests/HSchool.Content.Tests`, `tests/HSchool.Protocol.Tests`,
`tests/HSchool.AppHost.Tests/SchoolApiTests.cs`, `tests/HSchool.AppHost.Tests/GameSocketTests.cs`,
`tests/HSchool.AppHost.Tests/ServiceabilityTests.cs`
- **Итог:** перепроверка; `git log d087486..HEAD` по путям среза непустой (портреты, notices,
Krea, сцена). Обещания фаз 0–4 целы. Усилен тест `localize()` под два `.manager`. Код не
чинился. AppHost socket/API не гонялись (не трогали). Фазы 🔄/⬜ не закрывались.
Что подтверждено (после дрейфа):
- PixiJS нет в `package.json` и в клиентском коде. Overview: вкладки Карта/Люди, дерево,
локация с четырьмя секциями, клиентский фильтр, `localize()`. Панель общих событий по-прежнему
снята (фаза 8 / `near-term.md`); notices — модалки/тосты, не возврат ленты.
- `SchoolWorker``LongRunning`, `MaxCatchUpSteps = 5`. Супервизор `World` не трогает.
`SchoolContentUnavailableException` + `persist: false` + `RememberIncompatible`. Outbox
`DropOldest`; `WaitToReadAsync` переносится. `modal.ts` резолвит явно; `.dialog--screen`
`height: fit-content`; `DefaultStartDate` UTC; меню патчит `card.update`.
- Каталог/карта: last-wins, parent/abstract, патчи, связность, пустая комната, отказ без двора
(15 зелёных в `MapValidation`/`ExamplePack`/`Inheritance`). `MapSnapshot` round-trip + size
(4 зелёных в Protocol). Кодек / `protocol.ts` / `docs/protocol.md` — один снимок (протокол v10).
- `core` в create заблокирован (`createSchoolDialog.test.ts`). Клиентский filter дерева и
пустые секции локации — `gameScreen.test.ts`.
Дописано на этом проходе:
- `gameScreen.test.ts``localize()` смотрит overview (не manage): вкладки + четыре секции и
empty-строки до/после смены языка
Исправлено:
- ничего в прод-коде: расхождений с дизайном среза 1, которые надо чинить, не нашлось.
Открытое:
- ветка не слита: основное дерево на `main`, но грязное (untracked срез 12 + dirty
README/AGENTS) — без stash, ждёт чистый main.
- соседний `review/slice-2-recheck` тоже ждёт чистый main — не сливать чужое.
## Перепроверка среза 1 (после одежды / сессии / общения)
- **Фазы:** 04
+1 -1
View File
@@ -20,7 +20,7 @@
| Срез | Проверен на | Журнал |
| --- | --- | --- |
| Срез 1. Оболочка и карта | `d087486` | [01-shell](01-shell/reviewed.md) |
| Срез 1. Оболочка и карта | `5a0d75b` | [01-shell](01-shell/reviewed.md) |
| Срез 2. Люди | `8108508` | [02-people](02-people/reviewed.md) |
| Срез 3. Штат | `cf1403e` | [03-staffing](03-staffing/reviewed.md) |
| Срез 4. Расписание | `01ef277` | [04-schedule](04-schedule/reviewed.md) |
+44 -8
View File
@@ -35,6 +35,29 @@ vi.mock('../net/api.ts', async (importOriginal) => {
const initial = getLocale();
function overviewPanel(root: HTMLElement, index: number): HTMLElement {
const overview = root.querySelectorAll(':scope > .manager')[0];
const panel = overview?.querySelectorAll(':scope > .panel')[index];
if (!(panel instanceof HTMLElement)) {
throw new Error('overview panel is missing');
}
return panel;
}
function mapTabs(root: HTMLElement): HTMLButtonElement[] {
return [...overviewPanel(root, 0).querySelectorAll<HTMLButtonElement>('.panel__tab')];
}
function locationBody(root: HTMLElement): HTMLElement {
const body = overviewPanel(root, 1).querySelector(':scope > .panel__body');
if (!(body instanceof HTMLElement)) {
throw new Error('location panel is missing');
}
return body;
}
function school(overrides: Partial<School> = {}): School {
return {
id: 1,
@@ -174,18 +197,31 @@ describe('GameScreen location tree', () => {
document.body.append(screen.element);
screen.show(school());
expect(screen.element.querySelector('.panel__section-title')?.textContent).toBe(t('locationItems'));
expect([...screen.element.querySelectorAll('.panel__empty')].map((node) => node.textContent)).toContain(
t('itemsEmpty'),
);
const location = locationBody(screen.element);
const titles = () => [...location.querySelectorAll('.panel__section-title')].map((node) => node.textContent);
const empties = () => [...location.querySelectorAll('.panel__empty')].map((node) => node.textContent);
const tabs = () => [...mapTabs(screen.element)].map((node) => node.textContent);
expect(tabs()).toEqual([t('mapTitle'), t('peopleTitle')]);
expect(titles()).toEqual([
t('locationItems'),
t('locationCharacters'),
t('locationActivities'),
t('locationPositions'),
]);
expect(empties()).toEqual([t('itemsEmpty'), t('charactersEmpty'), t('activitiesEmpty'), t('positionsEmpty')]);
setLocale('ru');
screen.localize();
expect(screen.element.querySelector('.panel__section-title')?.textContent).toBe(t('locationItems'));
expect([...screen.element.querySelectorAll('.panel__empty')].map((node) => node.textContent)).toContain(
t('itemsEmpty'),
);
expect(tabs()).toEqual([t('mapTitle'), t('peopleTitle')]);
expect(titles()).toEqual([
t('locationItems'),
t('locationCharacters'),
t('locationActivities'),
t('locationPositions'),
]);
expect(empties()).toEqual([t('itemsEmpty'), t('charactersEmpty'), t('activitiesEmpty'), t('positionsEmpty')]);
});
});