Complete phase 39 school owners with owner-scoped API, menu, and tests.

Drop golden save load tests in favor of incompatible-save behavior; dress legacy people files on reload; fix AppHost isolation for multi-user socket and save cleanup.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Leonid Pershin
2026-08-20 09:44:08 +03:00
co-authored by Cursor
parent 4b236a7916
commit cc18429108
15 changed files with 371 additions and 341 deletions
@@ -88,6 +88,7 @@ function school(): School {
running: false,
speedIndex: 0,
seed: 1,
mine: true,
};
}
+1 -1
View File
@@ -47,7 +47,7 @@ export function el<K extends keyof HTMLElementTagNameMap>(
}
if (options.autocomplete !== undefined && 'autocomplete' in element) {
(element as HTMLInputElement).autocomplete = options.autocomplete;
element.setAttribute('autocomplete', options.autocomplete);
}
if (options.maxlength !== undefined && 'maxLength' in element) {
+2 -2
View File
@@ -43,7 +43,7 @@ describe('GameScreen speed buttons', () => {
});
const manageTab = screen.element.querySelectorAll<HTMLElement>('.mode-tab')[1];
expect(manageTab?.hidden).toBe(true);
expect(screen.element.querySelector('.clock__controls')?.hidden).toBe(true);
expect((manageTab as HTMLElement).hidden).toBe(true);
expect((screen.element.querySelector('.clock__controls') as HTMLElement).hidden).toBe(true);
});
});
-1
View File
@@ -12,7 +12,6 @@ import { schoolWord, t } from '../i18n/strings.ts';
import { el } from './dom.ts';
import { confirmDialog } from './confirmDialog.ts';
import { createSchoolDialog } from './createSchoolDialog.ts';
import { swarmUiSettingsDialog } from './swarmUiSettingsDialog.ts';
import { SchoolCard, type MenuSchool } from './schoolCard.ts';
interface MainMenuOptions {
+2 -2
View File
@@ -1,7 +1,7 @@
/**
* @vitest-environment happy-dom
*/
import { describe, expect, it, vi } from 'vitest';
import { describe, expect, it } from 'vitest';
import { SchoolCard } from './schoolCard.ts';
describe('SchoolCard ownership', () => {
@@ -27,6 +27,6 @@ describe('SchoolCard ownership', () => {
document.body.append(card.element);
expect(card.element.querySelector('.button--danger')?.hidden).toBe(true);
expect((card.element.querySelector('.button--danger') as HTMLElement).hidden).toBe(true);
});
});
@@ -2,7 +2,7 @@
* @vitest-environment happy-dom
*/
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { ApiError, fetchSchools, fetchSession } from '../net/api.ts';
import { ApiError, fetchSession } from '../net/api.ts';
import { t } from '../i18n/strings.ts';
import { ensureSession } from './sessionGate.ts';
+3 -2
View File
@@ -982,8 +982,9 @@ internal sealed class SchoolWorker
if (DressGenerator.NeedsDressing(roster, applicants))
{
throw new SchoolContentUnavailableException(
$"School {_id} people have no clothes; the school was left unstarted.");
roster = DressGenerator.EnsureRoster(catalog, roster, seed, school.Clock.Time);
applicants = DressGenerator.EnsurePool(catalog, applicants, roster, seed, school.Clock.Time);
generated = true;
}
RequireKnownApparel(catalog, roster, applicants);