This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
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);
|
||||
});
|
||||
Reference in New Issue
Block a user