Some checks failed
Deploy MineGeo to Dokploy / deploy (push) Failing after 2m37s
141 lines
5.3 KiB
JavaScript
141 lines
5.3 KiB
JavaScript
// Isolated database only; no fixture accounts or scores enter the real board.
|
|
import assert from "node:assert/strict";
|
|
import { readFile, readdir } from "node:fs/promises";
|
|
import { PGlite } from "../.data/sql-verification/node_modules/@electric-sql/pglite/dist/index.js";
|
|
|
|
const db = new PGlite();
|
|
try {
|
|
await db.exec(`create role anon; create role authenticated; create role service_role;
|
|
create schema auth; create table auth.users(id uuid primary key);
|
|
create function auth.uid() returns uuid language sql as $$ select null::uuid $$;
|
|
create schema storage;
|
|
create table storage.buckets(id text primary key,name text,public boolean,file_size_limit bigint,allowed_mime_types text[]);
|
|
create table storage.objects(id uuid primary key,bucket_id text,name text,owner_id text);
|
|
create function storage.foldername(text) returns text[] language sql as $$ select string_to_array($1, '/') $$;`);
|
|
for (const file of (await readdir("supabase/migrations"))
|
|
.filter((file) => file.endsWith(".sql"))
|
|
.sort()) {
|
|
await db.exec(await readFile(`supabase/migrations/${file}`, "utf8"));
|
|
}
|
|
async function board(difficulty = "all", search = "", page = 1, limit = 25) {
|
|
return (
|
|
await db.query("select public.player_leaderboard($1,$2,$3,$4) as board", [
|
|
difficulty,
|
|
search,
|
|
page,
|
|
limit,
|
|
])
|
|
).rows[0].board;
|
|
}
|
|
assert.deepEqual((await board()).entries, []);
|
|
assert.equal((await board()).page, 1);
|
|
assert.equal((await board()).pages, 1);
|
|
|
|
const ids = [];
|
|
for (const name of ["Alice", "Bob", "Carol", "%_Miner"]) {
|
|
const id = (
|
|
await db.query(
|
|
"insert into auth.users values(gen_random_uuid()) returning id",
|
|
)
|
|
).rows[0].id;
|
|
await db.query(
|
|
"insert into public.profiles(id,display_name) values($1,$2)",
|
|
[id, name],
|
|
);
|
|
ids.push(id);
|
|
}
|
|
const dataset = (
|
|
await db.query(
|
|
`insert into public.datasets(owner_id,name,source,bounds,state,panorama_count)
|
|
values($1,'Leaderboard fixture','plugin','{"minX":0,"minZ":0,"maxX":64,"maxZ":64}','published',5) returning id`,
|
|
[ids[0]],
|
|
)
|
|
).rows[0].id;
|
|
const revision = (
|
|
await db.query(
|
|
"insert into public.revisions(dataset_id,asset_root,manifest) values($1,'fixture','{}') returning id",
|
|
[dataset],
|
|
)
|
|
).rows[0].id;
|
|
async function game(
|
|
owner,
|
|
difficulty,
|
|
score,
|
|
current = 5,
|
|
missingResult = false,
|
|
) {
|
|
const session = (
|
|
await db.query(
|
|
"insert into public.game_sessions(revision_id,owner_id,access_hash,difficulty,difficulty_settings,current_round) values($1,$2,'private-fixture-secret',$3,public.resolve_difficulty_preset($3),$4) returning id",
|
|
[revision, owner, difficulty, current],
|
|
)
|
|
).rows[0].id;
|
|
for (let round = 0; round < 5; round++) {
|
|
await db.query(
|
|
"insert into public.game_rounds(session_id,round_number,viewpoint,result) values($1,$2,'{}',$3)",
|
|
[
|
|
session,
|
|
round,
|
|
missingResult && round === 4
|
|
? null
|
|
: JSON.stringify({ score: score / 5 }),
|
|
],
|
|
);
|
|
}
|
|
}
|
|
await game(ids[0], "easy", 19000);
|
|
await game(ids[0], "hard", 23000);
|
|
await game(ids[1], "easy", 21000);
|
|
await game(ids[1], "hard", 23000);
|
|
await game(ids[2], "easy", 20000);
|
|
await game(ids[2], "hard", 23000);
|
|
await game(ids[2], "hard", 23000);
|
|
await game(ids[3], "easy", 5000);
|
|
await game(null, "easy", 25000);
|
|
await game(ids[0], "normal", 25000, 4);
|
|
await game(ids[0], "normal", 25000, 5, true);
|
|
|
|
const all = await board();
|
|
assert.equal(all.total_players, 4);
|
|
assert.equal(all.total_games, 8);
|
|
assert.deepEqual(
|
|
all.entries.map((player) => player.display_name),
|
|
["Carol", "Bob", "Alice", "%_Miner"],
|
|
);
|
|
assert.equal(all.entries[0].average_score, 22000);
|
|
assert.equal(all.entries[0].games_played, 3);
|
|
assert.deepEqual(
|
|
(await board("easy")).leaders.map((player) => player.display_name),
|
|
["Bob", "Carol", "Alice"],
|
|
);
|
|
assert.equal((await board("normal")).total_players, 0);
|
|
assert.equal((await board("all", "alice")).entries[0].rank, 3);
|
|
assert.equal((await board("all", "%_")).matching_players, 1);
|
|
assert.equal((await board("all", "' OR 1=1--")).matching_players, 0);
|
|
assert.equal((await board("all", "missing")).pages, 1);
|
|
const last = await board("all", "", 999, 2);
|
|
assert.equal(last.page, 2);
|
|
assert.equal(last.pages, 2);
|
|
assert.deepEqual(
|
|
last.entries.map((player) => player.rank),
|
|
[3, 4],
|
|
);
|
|
assert.equal((await board("all", "", -1, 2)).page, 1);
|
|
assert.equal((await board("all", "", 1, 0)).entries.length, 1);
|
|
assert.equal((await board(null, null, null, null)).page, 1);
|
|
assert.equal(JSON.stringify(all).includes("private-fixture-secret"), false);
|
|
assert.equal(JSON.stringify(all).includes("viewpoint"), false);
|
|
for (const role of ["anon", "authenticated", "service_role"]) {
|
|
const result = await db.query(
|
|
"select has_function_privilege($1,'public.player_leaderboard(text,text,integer,integer)','execute') as allowed",
|
|
[role],
|
|
);
|
|
assert.equal(result.rows[0].allowed, role === "service_role");
|
|
}
|
|
console.log(
|
|
"Leaderboard SQL passed: empty board, completed games, guests, ranking ties, difficulty, literal search, pagination, and server-only permissions.",
|
|
);
|
|
} finally {
|
|
await db.close();
|
|
}
|