mirror of
https://github.com/tiennm99/miti99bot.git
synced 2026-09-03 02:20:16 +00:00
refactor(loldle): consume loldle.net's raw schema directly
Drop the in-scraper normalization step — champions.json now mirrors the exact shape emitted by loldle.net's JS bundle. Records use _id, championId, championName, arrays for positions/species/regions/ range_type, "Male"/"Female"/"Other" gender strings, and a full YYYY-MM-DD release_date. Comparison is schema-aware: multi-value keys accept arrays directly, the year axis parses YYYY out of the ISO date, and exact compares stay case-insensitive.
This commit is contained in:
@@ -22,18 +22,8 @@ import { resolve } from "node:path";
|
||||
|
||||
const LOLDLE_CLASSIC = "https://loldle.net/classic";
|
||||
|
||||
const LANE_MAP = {
|
||||
top: "top",
|
||||
jungle: "jungle",
|
||||
middle: "mid",
|
||||
bottom: "bottom",
|
||||
support: "support",
|
||||
};
|
||||
|
||||
const GENDER_MAP = { male: "male", female: "female", other: "divers" };
|
||||
|
||||
const CHAMPION_RECORD_RX =
|
||||
/\{_id:"[a-f0-9]+",championId:"[^"]+",championName:"([^"]+)",gender:"([^"]+)",positions:\[([^\]]+)\],species:\[([^\]]+)\],resource:"([^"]+)",range_type:\[([^\]]+)\],regions:\[([^\]]+)\],release_date:"(\d{4})-\d{2}-\d{2}"\}/g;
|
||||
/\{_id:"([a-f0-9]+)",championId:"([^"]+)",championName:"([^"]+)",gender:"([^"]+)",positions:\[([^\]]+)\],species:\[([^\]]+)\],resource:"([^"]+)",range_type:\[([^\]]+)\],regions:\[([^\]]+)\],release_date:"(\d{4}-\d{2}-\d{2})"\}/g;
|
||||
|
||||
async function fetchText(url) {
|
||||
const res = await fetch(url);
|
||||
@@ -45,10 +35,6 @@ function parseJsArrayStrings(inner) {
|
||||
return [...inner.matchAll(/"([^"]+)"/g)].map((m) => m[1]);
|
||||
}
|
||||
|
||||
function normalizeRegion(name) {
|
||||
return name.toLowerCase().replace(/\s+/g, "-");
|
||||
}
|
||||
|
||||
async function scrapeLoldle() {
|
||||
const html = await fetchText(LOLDLE_CLASSIC);
|
||||
const scriptMatch = html.match(/<script\s+src="(js\/index\.[^"]+\.js)"/);
|
||||
@@ -59,27 +45,33 @@ async function scrapeLoldle() {
|
||||
const seen = new Set();
|
||||
const records = [];
|
||||
for (const m of bundle.matchAll(CHAMPION_RECORD_RX)) {
|
||||
const [, name, gender, positionsRaw, speciesRaw, resource, rangeTypeRaw, regionsRaw, year] = m;
|
||||
if (seen.has(name)) continue;
|
||||
seen.add(name);
|
||||
|
||||
const lanes = parseJsArrayStrings(positionsRaw)
|
||||
.map((p) => LANE_MAP[p.toLowerCase()])
|
||||
.filter(Boolean);
|
||||
const regions = parseJsArrayStrings(regionsRaw).map(normalizeRegion);
|
||||
const species = parseJsArrayStrings(speciesRaw).map((s) => s.toLowerCase());
|
||||
const rangeType = parseJsArrayStrings(rangeTypeRaw)[0]?.toLowerCase();
|
||||
const [
|
||||
,
|
||||
_id,
|
||||
championId,
|
||||
championName,
|
||||
gender,
|
||||
positions,
|
||||
species,
|
||||
resource,
|
||||
rangeType,
|
||||
regions,
|
||||
releaseDate,
|
||||
] = m;
|
||||
if (seen.has(championName)) continue;
|
||||
seen.add(championName);
|
||||
|
||||
records.push({
|
||||
id: name,
|
||||
name,
|
||||
gender: GENDER_MAP[gender.toLowerCase()] ?? "divers",
|
||||
species: species.join(","),
|
||||
_id,
|
||||
championId,
|
||||
championName,
|
||||
gender,
|
||||
positions: parseJsArrayStrings(positions),
|
||||
species: parseJsArrayStrings(species),
|
||||
resource,
|
||||
attackType: rangeType === "melee" ? "close" : "range",
|
||||
region: regions.join(","),
|
||||
lane: lanes.join(","),
|
||||
releaseDate: Number(year),
|
||||
range_type: parseJsArrayStrings(rangeType),
|
||||
regions: parseJsArrayStrings(regions),
|
||||
release_date: releaseDate,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -88,7 +80,7 @@ async function scrapeLoldle() {
|
||||
"loldle.net: zero champion records parsed — bundle format changed, update CHAMPION_RECORD_RX",
|
||||
);
|
||||
}
|
||||
records.sort((a, b) => a.name.localeCompare(b.name));
|
||||
records.sort((a, b) => a.championName.localeCompare(b.championName));
|
||||
return records;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,8 @@ immediately rolls into a fresh round — no manual "new round" command needed.
|
||||
## Architecture
|
||||
|
||||
- `compare.js` — pure attribute comparison across 7 classic-mode attributes
|
||||
(gender, species, range, resource, region, lane, year). Returns `correct`,
|
||||
matching loldle.net's raw schema (`gender`, `species`, `range_type`,
|
||||
`resource`, `regions`, `positions`, `release_date`). Returns `correct`,
|
||||
`partial`, or `wrong` per attribute, plus a `direction` hint for year.
|
||||
- `lookup.js` — normalizes user input and resolves it to a champion record.
|
||||
- `daily.js` — `pickRandom` / `pickDaily` (djb2-hashed date seed for future
|
||||
|
||||
+3066
-1352
File diff suppressed because it is too large
Load Diff
@@ -1,16 +1,21 @@
|
||||
/**
|
||||
* @file Classic-mode champion comparison — ported from tiennm99/loldle
|
||||
* (lib/classic-mode.js). Pure functions, no DOM/React.
|
||||
* @file Classic-mode champion comparison against the raw loldle.net schema.
|
||||
* Pure functions, no DOM/React.
|
||||
*
|
||||
* Champion records use the shape emitted by scripts/scrape-loldle-data.js
|
||||
* (identical to loldle.net's JS bundle): gender is a string ("Male"), the
|
||||
* multi-value axes (positions, species, regions, range_type) are arrays,
|
||||
* and release_date is an ISO "YYYY-MM-DD" string.
|
||||
*/
|
||||
|
||||
export const CLASSIC_ATTRIBUTES = [
|
||||
{ key: "gender", label: "Gender", type: "exact" },
|
||||
{ key: "species", label: "Species", type: "multi" },
|
||||
{ key: "attackType", label: "Range", type: "exact" },
|
||||
{ key: "range_type", label: "Range", type: "multi" },
|
||||
{ key: "resource", label: "Resource", type: "exact" },
|
||||
{ key: "region", label: "Region", type: "multi" },
|
||||
{ key: "lane", label: "Lane", type: "multi" },
|
||||
{ key: "releaseDate", label: "Year", type: "year" },
|
||||
{ key: "regions", label: "Region", type: "multi" },
|
||||
{ key: "positions", label: "Lane", type: "multi" },
|
||||
{ key: "release_date", label: "Year", type: "year" },
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -20,32 +25,32 @@ export const CLASSIC_ATTRIBUTES = [
|
||||
*/
|
||||
export function compareChampions(guess, target) {
|
||||
return CLASSIC_ATTRIBUTES.map((attr) => {
|
||||
const guessVal = guess[attr.key] ?? "";
|
||||
const targetVal = target[attr.key] ?? "";
|
||||
const guessVal = guess[attr.key];
|
||||
const targetVal = target[attr.key];
|
||||
|
||||
switch (attr.type) {
|
||||
case "exact":
|
||||
return {
|
||||
...attr,
|
||||
guessValue: formatValue(attr.key, guessVal),
|
||||
targetValue: formatValue(attr.key, targetVal),
|
||||
guessValue: formatValue(guessVal),
|
||||
targetValue: formatValue(targetVal),
|
||||
result:
|
||||
String(guessVal).toLowerCase() === String(targetVal).toLowerCase()
|
||||
String(guessVal ?? "").toLowerCase() === String(targetVal ?? "").toLowerCase()
|
||||
? "correct"
|
||||
: "wrong",
|
||||
};
|
||||
case "multi":
|
||||
return {
|
||||
...attr,
|
||||
guessValue: formatValue(attr.key, guessVal),
|
||||
targetValue: formatValue(attr.key, targetVal),
|
||||
guessValue: formatValue(guessVal),
|
||||
targetValue: formatValue(targetVal),
|
||||
result: compareMultiValue(guessVal, targetVal),
|
||||
};
|
||||
case "year":
|
||||
return {
|
||||
...attr,
|
||||
guessValue: guessVal || "?",
|
||||
targetValue: targetVal || "?",
|
||||
guessValue: parseYear(guessVal) || "?",
|
||||
targetValue: parseYear(targetVal) || "?",
|
||||
...compareYear(guessVal, targetVal),
|
||||
};
|
||||
default:
|
||||
@@ -54,9 +59,9 @@ export function compareChampions(guess, target) {
|
||||
});
|
||||
}
|
||||
|
||||
function compareMultiValue(guessStr, targetStr) {
|
||||
const guessSet = parseSet(guessStr);
|
||||
const targetSet = parseSet(targetStr);
|
||||
function compareMultiValue(guess, target) {
|
||||
const guessSet = toSet(guess);
|
||||
const targetSet = toSet(target);
|
||||
|
||||
if (guessSet.size === 0 && targetSet.size === 0) return "correct";
|
||||
if (guessSet.size === 0 || targetSet.size === 0) return "wrong";
|
||||
@@ -67,56 +72,33 @@ function compareMultiValue(guessStr, targetStr) {
|
||||
return "wrong";
|
||||
}
|
||||
|
||||
function compareYear(guessYear, targetYear) {
|
||||
const g = Number(guessYear);
|
||||
const t = Number(targetYear);
|
||||
function parseYear(val) {
|
||||
if (!val) return 0;
|
||||
const m = String(val).match(/^(\d{4})/);
|
||||
return m ? Number(m[1]) : 0;
|
||||
}
|
||||
|
||||
function compareYear(guess, target) {
|
||||
const g = parseYear(guess);
|
||||
const t = parseYear(target);
|
||||
if (!g || !t) return { result: "wrong" };
|
||||
if (g === t) return { result: "correct" };
|
||||
return { result: "wrong", direction: g < t ? "up" : "down" };
|
||||
}
|
||||
|
||||
function parseSet(str) {
|
||||
if (!str) return new Set();
|
||||
return new Set(
|
||||
String(str)
|
||||
.split(",")
|
||||
.map((s) => s.trim().toLowerCase())
|
||||
.filter(Boolean),
|
||||
);
|
||||
function toSet(val) {
|
||||
const arr = Array.isArray(val) ? val : String(val ?? "").split(",");
|
||||
return new Set(arr.map((s) => String(s).trim().toLowerCase()).filter(Boolean));
|
||||
}
|
||||
|
||||
function setsEqual(a, b) {
|
||||
if (a.size !== b.size) return false;
|
||||
for (const val of a) {
|
||||
if (!b.has(val)) return false;
|
||||
}
|
||||
for (const v of a) if (!b.has(v)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
function formatValue(key, value) {
|
||||
if (!value) return "—";
|
||||
const str = String(value);
|
||||
switch (key) {
|
||||
case "gender":
|
||||
return capitalize(str);
|
||||
case "attackType":
|
||||
return str === "close" ? "Melee" : "Ranged";
|
||||
case "region":
|
||||
return str
|
||||
.split(",")
|
||||
.map((s) => s.split("-").map(capitalize).join(" "))
|
||||
.join(", ");
|
||||
case "species":
|
||||
case "lane":
|
||||
return str
|
||||
.split(",")
|
||||
.map((s) => capitalize(s.trim()))
|
||||
.join(", ");
|
||||
default:
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
function capitalize(str) {
|
||||
return str.charAt(0).toUpperCase() + str.slice(1);
|
||||
function formatValue(val) {
|
||||
if (val == null || val === "") return "—";
|
||||
if (Array.isArray(val)) return val.length === 0 ? "—" : val.join(", ");
|
||||
return String(val);
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ async function getOrInitGame(db, subject) {
|
||||
async function startFreshGame(db, subject) {
|
||||
const target = pickRandom(champions);
|
||||
const fresh = {
|
||||
target: target.id,
|
||||
target: target.championName,
|
||||
guesses: [],
|
||||
solved: false,
|
||||
giveup: false,
|
||||
@@ -118,14 +118,14 @@ export async function handleLoldle(ctx, db) {
|
||||
const guess = findChampion(champions, arg);
|
||||
if (!guess) return ctx.reply(`Champion not found: "${arg}".`);
|
||||
|
||||
if (game.guesses.some((g) => g.champion === guess.name)) {
|
||||
if (game.guesses.some((g) => g.champion === guess.championName)) {
|
||||
return ctx.reply(
|
||||
`🔁 <b>${escapeHtml(guess.name)}</b> was already guessed this round — try another champion.`,
|
||||
`🔁 <b>${escapeHtml(guess.championName)}</b> was already guessed this round — try another champion.`,
|
||||
{ parse_mode: "HTML" },
|
||||
);
|
||||
}
|
||||
|
||||
const target = champions.find((c) => c.id === game.target);
|
||||
const target = champions.find((c) => c.championName === game.target);
|
||||
// champions.json can be refreshed between rounds — an active target may disappear.
|
||||
if (!target) {
|
||||
await startFreshGame(db, subject);
|
||||
@@ -134,14 +134,14 @@ export async function handleLoldle(ctx, db) {
|
||||
);
|
||||
}
|
||||
const results = compareChampions(guess, target);
|
||||
game.guesses.push({ champion: guess.name, results });
|
||||
const won = guess.id === target.id;
|
||||
game.guesses.push({ champion: guess.championName, results });
|
||||
const won = guess.championName === target.championName;
|
||||
if (won) game.solved = true;
|
||||
await saveGame(db, subject, game);
|
||||
|
||||
const reply = renderGuess(guess.name, results);
|
||||
const reply = renderGuess(guess.championName, results);
|
||||
const elapsed = formatDuration(Date.now() - (game.startedAt ?? Date.now()));
|
||||
const champ = escapeHtml(target.name);
|
||||
const champ = escapeHtml(target.championName);
|
||||
|
||||
if (won) {
|
||||
const s = await recordResult(db, subject, true);
|
||||
@@ -178,10 +178,10 @@ export async function handleGiveup(ctx, db) {
|
||||
game.giveup = true;
|
||||
await saveGame(db, subject, game);
|
||||
await recordResult(db, subject, false);
|
||||
const target = champions.find((c) => c.id === game.target);
|
||||
const target = champions.find((c) => c.championName === game.target);
|
||||
await startFreshGame(db, subject);
|
||||
await trySendSticker(ctx, GIVEUP_STICKERS);
|
||||
const answer = target ? escapeHtml(target.name) : escapeHtml(game.target);
|
||||
const answer = target ? escapeHtml(target.championName) : escapeHtml(game.target);
|
||||
return ctx.reply(`🏳️ Answer was ${answer}.\n${NEW_ROUND_HINT}`, { parse_mode: "HTML" });
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @file Champion name lookup — normalizes user input to a champion record.
|
||||
* Matches by exact id/name (case/space/punct-insensitive).
|
||||
* Falls back to prefix match when unique.
|
||||
* Matches championName case/space/punct-insensitive. Falls back to prefix
|
||||
* match when unique.
|
||||
*/
|
||||
|
||||
function normalize(s) {
|
||||
@@ -20,11 +20,9 @@ export function findChampion(champions, input) {
|
||||
if (!q) return null;
|
||||
|
||||
for (const c of champions) {
|
||||
if (normalize(c.id) === q || normalize(c.name) === q) return c;
|
||||
if (normalize(c.championName) === q) return c;
|
||||
}
|
||||
|
||||
const prefixMatches = champions.filter(
|
||||
(c) => normalize(c.id).startsWith(q) || normalize(c.name).startsWith(q),
|
||||
);
|
||||
const prefixMatches = champions.filter((c) => normalize(c.championName).startsWith(q));
|
||||
return prefixMatches.length === 1 ? prefixMatches[0] : null;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ function buildRows(championName, results) {
|
||||
for (const r of results) {
|
||||
const marker = MARKER[r.result] ?? MARKER.wrong;
|
||||
let value = String(r.guessValue ?? "");
|
||||
if (r.key === "releaseDate" && r.result !== "correct" && r.direction) {
|
||||
if (r.key === "release_date" && r.result !== "correct" && r.direction) {
|
||||
const arrow = ARROW[r.direction];
|
||||
if (arrow) value = `${value} ${arrow}`;
|
||||
}
|
||||
|
||||
@@ -2,36 +2,36 @@ import { describe, expect, it } from "vitest";
|
||||
import { CLASSIC_ATTRIBUTES, compareChampions } from "../../../src/modules/loldle/compare.js";
|
||||
|
||||
const aatrox = {
|
||||
id: "Aatrox",
|
||||
gender: "male",
|
||||
species: "darkin",
|
||||
attackType: "close",
|
||||
championName: "Aatrox",
|
||||
gender: "Male",
|
||||
species: ["Darkin"],
|
||||
range_type: ["Melee"],
|
||||
resource: "Manaless",
|
||||
region: "runeterra,shurima",
|
||||
lane: "top",
|
||||
releaseDate: 2013,
|
||||
regions: ["Runeterra", "Shurima"],
|
||||
positions: ["Top"],
|
||||
release_date: "2013-06-13",
|
||||
};
|
||||
|
||||
const ahri = {
|
||||
id: "Ahri",
|
||||
gender: "female",
|
||||
species: "vastayan",
|
||||
attackType: "range",
|
||||
championName: "Ahri",
|
||||
gender: "Female",
|
||||
species: ["Vastayan"],
|
||||
range_type: ["Ranged"],
|
||||
resource: "Mana",
|
||||
region: "ionia",
|
||||
lane: "mid",
|
||||
releaseDate: 2011,
|
||||
regions: ["Ionia"],
|
||||
positions: ["Middle"],
|
||||
release_date: "2011-12-14",
|
||||
};
|
||||
|
||||
const akali = {
|
||||
id: "Akali",
|
||||
gender: "female",
|
||||
species: "human",
|
||||
attackType: "close",
|
||||
championName: "Akali",
|
||||
gender: "Female",
|
||||
species: ["Human"],
|
||||
range_type: ["Melee"],
|
||||
resource: "Energy",
|
||||
region: "ionia",
|
||||
lane: "mid,top",
|
||||
releaseDate: 2010,
|
||||
regions: ["Ionia"],
|
||||
positions: ["Middle", "Top"],
|
||||
release_date: "2010-05-11",
|
||||
};
|
||||
|
||||
function byKey(results, key) {
|
||||
@@ -47,38 +47,34 @@ describe("compareChampions", () => {
|
||||
it("exact mismatch is wrong", () => {
|
||||
const r = compareChampions(aatrox, ahri);
|
||||
expect(byKey(r, "gender").result).toBe("wrong");
|
||||
expect(byKey(r, "attackType").result).toBe("wrong");
|
||||
expect(byKey(r, "resource").result).toBe("wrong");
|
||||
});
|
||||
|
||||
it("multi-value partial overlap is partial", () => {
|
||||
const r = compareChampions({ ...akali, lane: "mid,top" }, { ...ahri, lane: "mid" });
|
||||
expect(byKey(r, "lane").result).toBe("partial");
|
||||
const r2 = compareChampions(
|
||||
{ ...aatrox, region: "runeterra,shurima" },
|
||||
{ ...ahri, region: "runeterra,ionia" },
|
||||
);
|
||||
expect(byKey(r2, "region").result).toBe("partial");
|
||||
const r = compareChampions(akali, { ...ahri, positions: ["Middle"] });
|
||||
expect(byKey(r, "positions").result).toBe("partial");
|
||||
const r2 = compareChampions(aatrox, { ...ahri, regions: ["Runeterra", "Ionia"] });
|
||||
expect(byKey(r2, "regions").result).toBe("partial");
|
||||
});
|
||||
|
||||
it("multi-value identical sets are correct even if order/case differ", () => {
|
||||
const r = compareChampions(
|
||||
{ ...akali, species: "human,ninja" },
|
||||
{ ...akali, species: "Ninja,Human" },
|
||||
{ ...akali, species: ["Human", "Ninja"] },
|
||||
{ ...akali, species: ["ninja", "HUMAN"] },
|
||||
);
|
||||
expect(byKey(r, "species").result).toBe("correct");
|
||||
});
|
||||
|
||||
it("year direction hints up when guess < target", () => {
|
||||
const r = compareChampions(akali, aatrox); // 2010 vs 2013
|
||||
const y = byKey(r, "releaseDate");
|
||||
const y = byKey(r, "release_date");
|
||||
expect(y.result).toBe("wrong");
|
||||
expect(y.direction).toBe("up");
|
||||
});
|
||||
|
||||
it("year direction hints down when guess > target", () => {
|
||||
const r = compareChampions(aatrox, akali); // 2013 vs 2010
|
||||
const y = byKey(r, "releaseDate");
|
||||
const y = byKey(r, "release_date");
|
||||
expect(y.result).toBe("wrong");
|
||||
expect(y.direction).toBe("down");
|
||||
});
|
||||
|
||||
@@ -2,22 +2,23 @@ import { describe, expect, it } from "vitest";
|
||||
import { findChampion } from "../../../src/modules/loldle/lookup.js";
|
||||
|
||||
const champions = [
|
||||
{ id: "Aatrox", name: "Aatrox" },
|
||||
{ id: "Ahri", name: "Ahri" },
|
||||
{ id: "KhaZix", name: "Kha'Zix" },
|
||||
{ id: "MissFortune", name: "Miss Fortune" },
|
||||
{ championName: "Aatrox" },
|
||||
{ championName: "Ahri" },
|
||||
{ championName: "Kha'Zix" },
|
||||
{ championName: "Miss Fortune" },
|
||||
];
|
||||
|
||||
describe("findChampion", () => {
|
||||
it("matches by exact id (case-insensitive)", () => {
|
||||
expect(findChampion(champions, "aatrox").id).toBe("Aatrox");
|
||||
expect(findChampion(champions, "AATROX").id).toBe("Aatrox");
|
||||
it("matches championName (case-insensitive)", () => {
|
||||
expect(findChampion(champions, "aatrox").championName).toBe("Aatrox");
|
||||
expect(findChampion(champions, "AATROX").championName).toBe("Aatrox");
|
||||
});
|
||||
|
||||
it("normalizes punctuation and spaces", () => {
|
||||
expect(findChampion(champions, "kha'zix").id).toBe("KhaZix");
|
||||
expect(findChampion(champions, "miss fortune").id).toBe("MissFortune");
|
||||
expect(findChampion(champions, "MissFortune").id).toBe("MissFortune");
|
||||
expect(findChampion(champions, "kha'zix").championName).toBe("Kha'Zix");
|
||||
expect(findChampion(champions, "khazix").championName).toBe("Kha'Zix");
|
||||
expect(findChampion(champions, "miss fortune").championName).toBe("Miss Fortune");
|
||||
expect(findChampion(champions, "MissFortune").championName).toBe("Miss Fortune");
|
||||
});
|
||||
|
||||
it("returns null for non-matching input", () => {
|
||||
@@ -26,11 +27,11 @@ describe("findChampion", () => {
|
||||
});
|
||||
|
||||
it("falls back to unique prefix match", () => {
|
||||
expect(findChampion(champions, "aat").id).toBe("Aatrox");
|
||||
expect(findChampion(champions, "aat").championName).toBe("Aatrox");
|
||||
});
|
||||
|
||||
it("prefix match returns null on ambiguity", () => {
|
||||
const ambig = [...champions, { id: "Aatrox2", name: "Aatrox 2" }];
|
||||
const ambig = [...champions, { championName: "Aatrox Prime" }];
|
||||
expect(findChampion(ambig, "aa")).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -10,7 +10,7 @@ const sampleResults = [
|
||||
{ key: "region", label: "Region", result: "correct", guessValue: "Runeterra" },
|
||||
{ key: "lane", label: "Lane", result: "partial", guessValue: "Jungle, Support" },
|
||||
{
|
||||
key: "releaseDate",
|
||||
key: "release_date",
|
||||
label: "Year",
|
||||
result: "wrong",
|
||||
direction: "up",
|
||||
@@ -48,7 +48,7 @@ describe("renderGuess", () => {
|
||||
expect(up).toContain("2011 ⬆️");
|
||||
|
||||
const correctYear = sampleResults.map((r) =>
|
||||
r.key === "releaseDate" ? { ...r, result: "correct", direction: undefined } : r,
|
||||
r.key === "release_date" ? { ...r, result: "correct", direction: undefined } : r,
|
||||
);
|
||||
const out = renderGuess("Brand", correctYear);
|
||||
expect(out).not.toContain("⬆️");
|
||||
|
||||
Reference in New Issue
Block a user