148 lines
5.8 KiB
TypeScript
148 lines
5.8 KiB
TypeScript
import { afterEach, expect, it, vi } from 'vitest';
|
|
import { flushSync, mount, unmount } from 'svelte';
|
|
import BetaRevisionDialog from '../../src/lib/ui/components/BetaRevisionDialog.svelte';
|
|
import ScriptUploadDrawer from '../../src/lib/ui/components/ScriptUploadDrawer.svelte';
|
|
|
|
vi.mock('$app/navigation', () => ({ goto: vi.fn() }));
|
|
let component: ReturnType<typeof mount> | undefined;
|
|
afterEach(async () => {
|
|
if (component) await unmount(component);
|
|
component = undefined;
|
|
document.body.replaceChildren();
|
|
vi.unstubAllGlobals();
|
|
});
|
|
|
|
it('fills exact filenames from a manifest, preserves manual values, and sends each release', async () => {
|
|
const uploaded: FormData[] = [];
|
|
vi.stubGlobal(
|
|
'fetch',
|
|
vi.fn(async (url: string, options?: RequestInit) => {
|
|
if (url === '/api/scope-options') return Response.json({ games: [], mapsByGame: {} });
|
|
if (url === '/api/servers') return Response.json({ servers: [] });
|
|
if (url === '/api/scripts/inspect')
|
|
return Response.json({ sha256: 'test', duplicates: [] });
|
|
uploaded.push(options!.body as FormData);
|
|
return Response.json({
|
|
ok: true,
|
|
script: { id: uploaded.length },
|
|
versionId: uploaded.length
|
|
});
|
|
})
|
|
);
|
|
const drawer = mount(ScriptUploadDrawer, {
|
|
target: document.body,
|
|
props: { scripts: [], onuploaded: async () => {} }
|
|
});
|
|
component = drawer;
|
|
flushSync();
|
|
const dialog = document.querySelector('dialog')!;
|
|
dialog.showModal = () => {
|
|
dialog.open = true;
|
|
};
|
|
await drawer.addFiles([
|
|
new File(['hud'], 'hud.gsc'),
|
|
new File(['join'], 'join.gsc'),
|
|
new File(['lock'], 'lock.gsc')
|
|
]);
|
|
flushSync();
|
|
const versions = [...document.querySelectorAll<HTMLInputElement>('input[placeholder="1.2.0"]')];
|
|
expect(versions).toHaveLength(3);
|
|
const uploadButton = [...document.querySelectorAll<HTMLButtonElement>('button')].find(
|
|
(button) => button.textContent?.trim() === 'Upload'
|
|
)!;
|
|
expect(uploadButton.disabled).toBe(true);
|
|
versions[0].value = '3.0.0';
|
|
versions[0].dispatchEvent(new Event('input', { bubbles: true }));
|
|
flushSync();
|
|
const manifest = document.querySelector<HTMLInputElement>('input[accept=".json"]')!;
|
|
Object.defineProperty(manifest, 'files', {
|
|
configurable: true,
|
|
value: [
|
|
new File(['{"hud.gsc":"1.0.0","join.gsc":"2.0.0","LOCK.gsc":"9.0.0"}'], 'versions.json')
|
|
]
|
|
});
|
|
manifest.dispatchEvent(new Event('change', { bubbles: true }));
|
|
await vi.waitFor(() => {
|
|
flushSync();
|
|
expect(versions[1].value).toBe('2.0.0');
|
|
});
|
|
expect(versions[0].value).toBe('3.0.0');
|
|
expect(versions[2].value).toBe('');
|
|
expect(uploadButton.disabled).toBe(true);
|
|
versions[2].value = '1.0';
|
|
versions[2].dispatchEvent(new Event('input', { bubbles: true }));
|
|
flushSync();
|
|
expect(uploadButton.disabled).toBe(true);
|
|
versions[2].value = '1.0.0';
|
|
versions[2].dispatchEvent(new Event('input', { bubbles: true }));
|
|
flushSync();
|
|
expect(uploadButton.disabled).toBe(false);
|
|
uploadButton.click();
|
|
await vi.waitFor(() => expect(uploaded).toHaveLength(3));
|
|
expect(uploaded.map((form) => form.get('releaseVersion'))).toEqual(['3.0.0', '2.0.0', '1.0.0']);
|
|
});
|
|
|
|
it('requires a replacement release before beta review and includes it in the revision request', async () => {
|
|
let submitted: FormData | null = null;
|
|
const onUpdate = vi.fn();
|
|
vi.stubGlobal(
|
|
'fetch',
|
|
vi.fn(async (url: string, options?: RequestInit) => {
|
|
if (url === '/api/scripts/inspect')
|
|
return Response.json({ sha256: 'new-hash', duplicates: [] });
|
|
if (url.endsWith('/files/4')) return new Response('original script');
|
|
submitted = options!.body as FormData;
|
|
return Response.json({ ok: true });
|
|
})
|
|
);
|
|
component = mount(BetaRevisionDialog, {
|
|
target: document.body,
|
|
props: {
|
|
open: true,
|
|
betaId: 7,
|
|
revision: 1,
|
|
servers: [],
|
|
onUpdate,
|
|
files: [
|
|
{
|
|
id: 4,
|
|
name: 'HUD',
|
|
kind: 'script',
|
|
target_rel_path: 'hud.gsc',
|
|
version: { version: 1, release_version: '1.0.0', sha256: 'old-hash' }
|
|
}
|
|
]
|
|
}
|
|
});
|
|
flushSync();
|
|
const input = document.querySelector<HTMLInputElement>('input[type="file"]:not([accept])')!;
|
|
Object.defineProperty(input, 'files', {
|
|
configurable: true,
|
|
value: [new File(['updated script'], 'hud.gsc')]
|
|
});
|
|
input.dispatchEvent(new Event('change', { bubbles: true }));
|
|
await vi.waitFor(() => {
|
|
flushSync();
|
|
expect(document.querySelector('input[required]')).not.toBeNull();
|
|
});
|
|
const review = [...document.querySelectorAll<HTMLButtonElement>('button')].find(
|
|
(button) => button.textContent?.trim() === 'Review update'
|
|
)!;
|
|
expect(review.disabled).toBe(true);
|
|
const version = document.querySelector<HTMLInputElement>('input[required]')!;
|
|
version.value = '1.0.1';
|
|
version.dispatchEvent(new Event('input', { bubbles: true }));
|
|
flushSync();
|
|
expect(review.disabled).toBe(false);
|
|
review.click();
|
|
flushSync();
|
|
expect(document.body.textContent).toContain('Release 1.0.0 → 1.0.1');
|
|
const deploy = [...document.querySelectorAll<HTMLButtonElement>('button')].find(
|
|
(button) => button.textContent?.trim() === 'Deploy revision 2'
|
|
)!;
|
|
deploy.click();
|
|
await vi.waitFor(() => expect(onUpdate).toHaveBeenCalledOnce());
|
|
expect(submitted!.get('release:4')).toBe('1.0.1');
|
|
expect(submitted!.get('file:4')).toBeInstanceOf(File);
|
|
});
|