Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion tests/browser/document-grounding.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { test } from "node:test";
import assert from "node:assert/strict";
import {
consumeGroundingPacket, groundingStorageKey, maxGroundingFileBytes, maxGroundingPacketBytes,
groundingConsentVersion, parseGroundingFile, selectedGroundingPacket, storeGroundingPacket,
groundingConsentVersion, parseGroundingFile, retainedSelection, selectedGroundingPacket, storeGroundingPacket,
} from "../../web/document-grounding.js";
import { memoryStorage } from "./source.js";

Expand Down Expand Up @@ -149,3 +149,11 @@ test("selection indexes outside the extracted list are dropped, not clamped", as
// Order follows the indexes as given, not the document.
assert.deepEqual(pickWith([2, 0]), ["Must have Go", "Must have Rust"]);
});

test("re-reading one document keeps the selection made in the other", () => {
Comment thread
ColtenOuO marked this conversation as resolved.
const selected = { requirements: [0, 2], skills: [1], anchors: [0] };
assert.deepEqual(retainedSelection(selected, "resume"), { requirements: [0, 2], skills: [], anchors: [] });
assert.deepEqual(retainedSelection(selected, "jd"), { requirements: [], skills: [1], anchors: [0] });
retainedSelection(selected, "jd").skills.push(5);
assert.deepEqual(selected.skills, [1]);
});
16 changes: 16 additions & 0 deletions tests/browser/lobby.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,22 @@ lobbyTest("a candidate explicitly chooses whether to share the practice focus",
);
});

lobbyTest("loading a resume keeps the JD requirements already checked", async (page) => {
await lobby(page);
await page.click("details.interview-context summary");
const txt = (name, text) => ({ name, mimeType: "text/plain", buffer: Buffer.from(text) });

await page.setInputFiles("#grounding-jd", txt("jd.txt", "Must know Rust\nMust know SQL"));
const jd = page.locator('#grounding-choices input[data-group="requirements"]');
await jd.first().waitFor();
await jd.nth(1).check();

await page.setInputFiles("#grounding-resume", txt("resume.txt", "Skills: Rust, Go\nBuilt a parser"));
await page.locator('#grounding-choices input[data-group="skills"]').first().waitFor();

assert.deepEqual(await jd.evaluateAll((boxes) => boxes.map((box) => box.checked)), [false, true]);
});

lobbyTest("a manually selected problem still receives the arriving practice focus", async (page) => {
reports = [focusedAttempt(EASY[0])];
const release = await heldLobby(page);
Expand Down
16 changes: 11 additions & 5 deletions web/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { clearReportHistory, readLocalHistory, renameLocalHistory } from "./hist
import { pickProblem, practiceFocus, storeSharedFocus, suggestDifficulty } from "./problem-picker.js";
import { buildProgressModel, pickerEntry } from "./progress.js";
import { loadPageMap } from "./problem-data.js";
import { parseGroundingFile, selectedGroundingPacket, storeGroundingPacket } from "./document-grounding.js";
import { parseGroundingFile, retainedSelection, selectedGroundingPacket, storeGroundingPacket } from "./document-grounding.js";

let problem;
let duration;
Expand Down Expand Up @@ -220,8 +220,7 @@ start.addEventListener("click", async () => {
if (profile.seniority) destination.searchParams.set("seniority", profile.seniority);
if (profile.targetCompany) destination.searchParams.set("company", profile.targetCompany);
const focus = nodes.practiceFocusShareInput.checked ? practiceFocus(reports) : null;
const selected = { requirements: [], skills: [], anchors: [] };
for (const input of nodes.groundingChoices.querySelectorAll("input:checked")) selected[input.dataset.group].push(Number(input.value));
const selected = checkedGrounding();
const consented = nodes.groundingConsent.checked;

starting = true;
Expand Down Expand Up @@ -271,10 +270,16 @@ async function loadGroundingFile(kind) {
else { grounding.skills = []; grounding.anchors = []; }
status.textContent = error.message;
}
renderGroundingChoices();
renderGroundingChoices(retainedSelection(checkedGrounding(), kind));
}

function checkedGrounding() {
const selected = { requirements: [], skills: [], anchors: [] };
for (const input of nodes.groundingChoices.querySelectorAll("input:checked")) selected[input.dataset.group].push(Number(input.value));
return selected;
}

function renderGroundingChoices() {
function renderGroundingChoices(selected) {
nodes.groundingChoices.replaceChildren();
for (const [group, label] of [["requirements", "JD requirements"], ["skills", "Resume skills"], ["anchors", "Resume experience/project anchors"]]) {
if (!grounding[group].length) continue;
Expand All @@ -288,6 +293,7 @@ function renderGroundingChoices() {
checkbox.type = "checkbox";
checkbox.dataset.group = group;
checkbox.value = String(index);
checkbox.checked = selected[group].includes(index);
row.append(checkbox, document.createTextNode(` ${snippet}`));
fieldset.append(row);
});
Expand Down
9 changes: 9 additions & 0 deletions web/document-grounding.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,15 @@ export async function parseGroundingFile(file, kind) {
return kind === "jd" ? parseJd(lines) : parseResume(lines);
}

export function retainedSelection(selected, kind) {
const replaced = kind === "jd" ? ["requirements"] : ["skills", "anchors"];
const retained = { requirements: [], skills: [], anchors: [] };
for (const group of Object.keys(retained)) {
if (!replaced.includes(group)) retained[group] = [...(selected[group] || [])];
}
return retained;
}

export function selectedGroundingPacket(extracted, selected, consent) {
const packet = {
consentVersion: groundingConsentVersion,
Expand Down