Validate and deduplicate custom difficulty presets
Some checks failed
Deploy MineGeo to Dokploy / deploy (push) Failing after 6m4s
Some checks failed
Deploy MineGeo to Dokploy / deploy (push) Failing after 6m4s
This commit is contained in:
181
scripts/test-difficulty-presets-sql.mjs
Normal file
181
scripts/test-difficulty-presets-sql.mjs
Normal file
@@ -0,0 +1,181 @@
|
||||
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((f) => f.endsWith(".sql"))
|
||||
.sort()) {
|
||||
if (file.endsWith("fix_difficulty_preset_names.sql"))
|
||||
await assert.rejects(
|
||||
db.query(
|
||||
"insert into public.difficulty_presets(name,seconds,zoom) values('Normal',90,true)",
|
||||
),
|
||||
(error) => error.code === "23514",
|
||||
);
|
||||
await db.exec(await readFile(`supabase/migrations/${file}`, "utf8"));
|
||||
}
|
||||
const valid = [
|
||||
"Normal",
|
||||
"Speed 90",
|
||||
"Hard",
|
||||
"Тест",
|
||||
"中文",
|
||||
"😎😎",
|
||||
"😎".repeat(40),
|
||||
"a".repeat(40),
|
||||
"a\\b",
|
||||
];
|
||||
for (const name of valid)
|
||||
await db.query(
|
||||
"insert into public.difficulty_presets(name,seconds,zoom) values($1,90,true)",
|
||||
[name],
|
||||
);
|
||||
for (const name of [
|
||||
"",
|
||||
"a",
|
||||
"😎",
|
||||
"a".repeat(41),
|
||||
"😎".repeat(41),
|
||||
" leading",
|
||||
"trailing ",
|
||||
"x\nname",
|
||||
"x\u0085name",
|
||||
"x\u202ename",
|
||||
"x\u2066name",
|
||||
])
|
||||
await assert.rejects(
|
||||
db.query(
|
||||
"insert into public.difficulty_presets(name,seconds,zoom) values($1,90,true)",
|
||||
[name],
|
||||
),
|
||||
(error) => error.code === "23514",
|
||||
);
|
||||
for (const seconds of [0, 14, 16, 601])
|
||||
await assert.rejects(
|
||||
db.query(
|
||||
"insert into public.difficulty_presets(name,seconds,zoom) values('Invalid clock',$1,true)",
|
||||
[seconds],
|
||||
),
|
||||
(error) => error.code === "23514",
|
||||
);
|
||||
await assert.rejects(
|
||||
db.query(
|
||||
"insert into public.difficulty_presets(name,seconds,zoom) values('normal',90,true)",
|
||||
),
|
||||
(error) => error.code === "23505",
|
||||
);
|
||||
|
||||
const preset = (
|
||||
await db.query(
|
||||
"insert into public.difficulty_presets(name,seconds,zoom) values('Playable preset 45',45,false) returning id",
|
||||
)
|
||||
).rows[0].id;
|
||||
for (const [id, seconds] of [
|
||||
["easy", 180],
|
||||
["normal", 90],
|
||||
["hard", 30],
|
||||
])
|
||||
assert.equal(
|
||||
(
|
||||
await db.query("select public.resolve_difficulty_preset($1) preset", [
|
||||
id,
|
||||
])
|
||||
).rows[0].preset.seconds,
|
||||
seconds,
|
||||
);
|
||||
await assert.rejects(
|
||||
db.query(
|
||||
"select public.resolve_difficulty_preset('00000000-0000-4000-8000-000000000000')",
|
||||
),
|
||||
/Choose a saved difficulty/,
|
||||
);
|
||||
assert.equal(
|
||||
(
|
||||
await db.query("select public.resolve_difficulty_preset($1) preset", [
|
||||
preset.toUpperCase(),
|
||||
])
|
||||
).rows[0].preset.id,
|
||||
preset,
|
||||
);
|
||||
const owner = (
|
||||
await db.query(
|
||||
"insert into auth.users values(gen_random_uuid()) returning id",
|
||||
)
|
||||
).rows[0].id;
|
||||
const map = (
|
||||
await db.query(
|
||||
`insert into public.datasets(owner_id,name,source,bounds,state,panorama_count)
|
||||
values($1,'Difficulty fixture','plugin','{"minX":0,"minZ":0,"maxX":64,"maxZ":64}','published',5) returning id`,
|
||||
[owner],
|
||||
)
|
||||
).rows[0].id;
|
||||
const manifest = {
|
||||
viewpoints: Array.from({ length: 5 }, (_, i) => ({
|
||||
id: `p${i}`,
|
||||
x: i,
|
||||
y: 65,
|
||||
z: i,
|
||||
})),
|
||||
};
|
||||
const revision = (
|
||||
await db.query(
|
||||
"insert into public.revisions(dataset_id,asset_root,manifest) values($1,'fixture',$2) returning id",
|
||||
[map, JSON.stringify(manifest)],
|
||||
)
|
||||
).rows[0].id;
|
||||
await db.query("update public.datasets set revision_id=$1 where id=$2", [
|
||||
revision,
|
||||
map,
|
||||
]);
|
||||
const solo = (
|
||||
await db.query("select public.create_game($1,$2,$3,$4) id", [
|
||||
map,
|
||||
preset,
|
||||
owner,
|
||||
"a".repeat(64),
|
||||
])
|
||||
).rows[0].id;
|
||||
const multi = (
|
||||
await db.query("select public.create_map_room($1,$2,'Host',2,$3,$4) id", [
|
||||
map,
|
||||
preset,
|
||||
"b".repeat(64),
|
||||
owner,
|
||||
])
|
||||
).rows[0].id;
|
||||
for (const [table, id] of [
|
||||
["game_sessions", solo],
|
||||
["multiplayer_rooms", multi],
|
||||
])
|
||||
assert.deepEqual(
|
||||
(
|
||||
await db.query(
|
||||
`select difficulty_settings from public.${table} where id=$1`,
|
||||
[id],
|
||||
)
|
||||
).rows[0].difficulty_settings,
|
||||
{ id: preset, name: "Playable preset 45", seconds: 45, zoom: false },
|
||||
);
|
||||
assert.equal(
|
||||
(
|
||||
await db.query(
|
||||
"select has_table_privilege('anon','public.difficulty_presets','INSERT') allowed",
|
||||
)
|
||||
).rows[0].allowed,
|
||||
false,
|
||||
);
|
||||
console.log(
|
||||
"Difficulty SQL regressions passed: original failure reproduced, normal/Unicode names, unsafe names, duplicates, time limits, solo/multiplayer rules and permissions.",
|
||||
);
|
||||
} finally {
|
||||
await db.close();
|
||||
}
|
||||
Reference in New Issue
Block a user