131 lines
8.5 KiB
JavaScript
131 lines
8.5 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import { readFileSync } from "node:fs";
|
|
import { createServer } from "node:http";
|
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
import { test } from "node:test";
|
|
import { build } from "esbuild";
|
|
|
|
test("the owner can toggle the gallery, everyone sees its badge and direct entry", {
|
|
skip: !process.env.PGAMES_PLAYWRIGHT_PATH,
|
|
}, async () => {
|
|
const { chromium } = await import(pathToFileURL(process.env.PGAMES_PLAYWRIGHT_PATH + "/index.mjs").href);
|
|
const compiled = await build({ stdin: { contents: `
|
|
import {createElement as h} from 'react'; import {createRoot} from 'react-dom/client';
|
|
import {MemoryRouter, Routes, Route, useLocation} from 'react-router-dom';
|
|
import {AuthProvider} from './auth'; import {UiProvider} from './ui/Ui';
|
|
import {TranslationRunProvider} from './translator/runner'; import {UploadProvider} from './uploads';
|
|
import {GamePage} from './pages/GamePage';
|
|
function Destination() {const at = useLocation(); return h('output', null, at.pathname + at.search);}
|
|
createRoot(document.querySelector('main')).render(h(MemoryRouter, {initialEntries: ['/games/1']},
|
|
h(UiProvider, null, h(AuthProvider, null, h(TranslationRunProvider, null, h(UploadProvider, null,
|
|
h(Routes, null, h(Route, {path: '/games/:gameId', element: h(GamePage)}),
|
|
h(Route, {path: '/play/:versionId', element: h(Destination)}))))))));`,
|
|
resolveDir: fileURLToPath(new URL("../src/", import.meta.url)), loader: "tsx" },
|
|
bundle: true, write: false, format: "iife", platform: "browser", logLevel: "silent" });
|
|
const css = readFileSync(new URL("../src/styles.css", import.meta.url), "utf8");
|
|
const version = { id: 1, game_id: 1, parent_id: null, owner: { id: 7, username: "author" }, name: "Моя версия",
|
|
status: "ready", kind: "mod", visibility: "draft", created_at: new Date().toISOString(), size_bytes: 1,
|
|
gallery_available: true, gallery_unlocked: false, languages: [] };
|
|
let userId = 7, fail = false;
|
|
const writes = [];
|
|
const server = createServer(async (req, res) => {
|
|
if (req.url === "/bundle.js") { res.setHeader("Content-Type", "text/javascript"); res.end(compiled.outputFiles[0].text); return; }
|
|
if (req.url === "/style.css") { res.setHeader("Content-Type", "text/css"); res.end(css); return; }
|
|
res.setHeader("Content-Type", "application/json");
|
|
if (req.url === "/api/auth/me") { res.end(JSON.stringify({ id: userId, username: "author", permissions: ["games.play"] })); return; }
|
|
if (req.url === "/api/games/1") { res.end(JSON.stringify({ id: 1, title: "MIST", tags: [], gallery_hashes: [], versions: [version] })); return; }
|
|
if (req.url === "/api/versions/1/gallery" && req.method === "PATCH") {
|
|
let body = "";
|
|
for await (const chunk of req) body += chunk;
|
|
const settings = JSON.parse(body);
|
|
writes.push(settings);
|
|
if (fail) { res.statusCode = 500; res.end(JSON.stringify({ detail: "Не удалось сохранить настройку" })); return; }
|
|
version.gallery_unlocked = settings.gallery_unlocked;
|
|
res.end(JSON.stringify(version)); return;
|
|
}
|
|
res.setHeader("Content-Type", "text/html");
|
|
res.end('<!doctype html><meta charset="utf-8"><link rel="stylesheet" href="/style.css"><main></main><script src="/bundle.js"></script>');
|
|
});
|
|
await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
|
|
let browser;
|
|
try {
|
|
browser = await chromium.launch({ headless: true, channel: process.env.PGAMES_BROWSER_CHANNEL });
|
|
const page = await browser.newPage({ viewport: { width: 1100, height: 800 } });
|
|
page.setDefaultTimeout(5000);
|
|
const origin = `http://127.0.0.1:${server.address().port}`;
|
|
await page.goto(origin);
|
|
const checkbox = page.getByRole("checkbox", { name: "Открыть всю галерею в этой версии" });
|
|
await checkbox.check();
|
|
await page.getByText("Галерея открыта", { exact: true }).waitFor();
|
|
await page.getByRole("button", { name: "Открыть галерею", exact: true }).click();
|
|
await page.getByText("/play/1?gallery=1", { exact: true }).waitFor();
|
|
await page.reload();
|
|
await checkbox.waitFor();
|
|
assert.equal(await checkbox.isChecked(), true);
|
|
await checkbox.uncheck();
|
|
await page.getByText("Галерея открыта", { exact: true }).waitFor({ state: "detached" });
|
|
fail = true;
|
|
await checkbox.click();
|
|
await page.getByText("Не удалось сохранить настройку", { exact: true }).waitFor();
|
|
assert.equal(await checkbox.isChecked(), false);
|
|
assert.deepEqual(writes, [{ gallery_unlocked: true }, { gallery_unlocked: false }, { gallery_unlocked: true }]);
|
|
version.gallery_unlocked = true;
|
|
userId = 8;
|
|
await page.reload();
|
|
await page.getByText("Галерея открыта", { exact: true }).waitFor();
|
|
assert.equal(await checkbox.count(), 0);
|
|
await page.setViewportSize({ width: 375, height: 800 });
|
|
assert.equal(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth), true);
|
|
} finally {
|
|
await browser?.close();
|
|
await new Promise((resolve) => server.close(resolve));
|
|
}
|
|
});
|
|
|
|
test("the unlocked Gallery viewer opens above its index and closes back to the main menu", {
|
|
skip: !process.env.PGAMES_PLAYWRIGHT_PATH,
|
|
}, async () => {
|
|
const { chromium } = await import(pathToFileURL(process.env.PGAMES_PLAYWRIGHT_PATH + "/index.mjs").href);
|
|
const compiled = await build({ stdin: { contents: `
|
|
import {Engine} from './player/engine'; import {parseStatements} from './player/pyparse';
|
|
const game = {resolution: [640, 480], entry: 'start', title: 'Gallery test', ui: {}, files: {}, defaults: [],
|
|
init: parseStatements('g = Gallery()\\ng.button("Art")\\ng.image("picture")\\ng.condition("False")'),
|
|
characters: {}, channels: {}, images: {picture: {color: '#ff00ff'}}, transforms: {}, atl: {}, transitions: {}, screens: {}, styles: {}, audio: {}};
|
|
const tr = {lang: 'en', renpyName: null, str: s => s, line: (_, s) => s};
|
|
const saves = {list: async () => [], get: async () => null, put: async () => {}, remove: async () => {}};
|
|
const engine = new Engine(document.querySelector('main'), game, {files: {}, galleryUnlocked: true},
|
|
[{labels: [{name: 'start', body: [{op: 'return'}]}], anchors: {}}], saves, 'gallery-browser', () => {}, tr, async () => tr);
|
|
engine.start();`, resolveDir: fileURLToPath(new URL("../src/", import.meta.url)), loader: "tsx" },
|
|
bundle: true, write: false, format: "iife", platform: "browser", logLevel: "silent" });
|
|
const css = readFileSync(new URL("../src/player/player.css", import.meta.url), "utf8");
|
|
const server = createServer((req, res) => {
|
|
if (req.url === "/bundle.js") { res.setHeader("Content-Type", "text/javascript"); res.end(compiled.outputFiles[0].text); return; }
|
|
if (req.url === "/style.css") { res.setHeader("Content-Type", "text/css"); res.end(css); return; }
|
|
res.setHeader("Content-Type", "text/html");
|
|
res.end('<!doctype html><meta charset="utf-8"><link rel="stylesheet" href="/style.css"><style>main{width:800px;height:600px}</style><main></main><script src="/bundle.js"></script>');
|
|
});
|
|
await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
|
|
let browser;
|
|
try {
|
|
browser = await chromium.launch({ headless: true, channel: process.env.PGAMES_BROWSER_CHANNEL });
|
|
const page = await browser.newPage({ viewport: { width: 1000, height: 800 } });
|
|
page.setDefaultTimeout(5000);
|
|
await page.goto(`http://127.0.0.1:${server.address().port}`);
|
|
await page.getByRole("button", { name: "Галерея открыта", exact: true }).click();
|
|
await page.getByRole("button", { name: "Art", exact: true }).click();
|
|
await page.locator(".pg-gallery").waitFor();
|
|
const top = await page.locator(".pg-gallery").evaluate((overlay) => {
|
|
const box = overlay.getBoundingClientRect();
|
|
return !!document.elementFromPoint(box.x + box.width / 2, box.y + box.height / 2)?.closest(".pg-gallery");
|
|
});
|
|
assert.equal(top, true, "the gallery image is above the index and receives input");
|
|
await page.locator(".pg-gallery").getByRole("button", { name: "Закрыть", exact: true }).click();
|
|
await page.getByRole("button", { name: "Art", exact: true }).waitFor();
|
|
await page.getByRole("button", { name: "Закрыть", exact: true }).click();
|
|
await page.getByRole("button", { name: "Начать", exact: true }).waitFor();
|
|
} finally {
|
|
await browser?.close();
|
|
await new Promise((resolve) => server.close(resolve));
|
|
}
|
|
});
|