Skip to content

Commit 23d79fd

Browse files
[107] bug fixes
- URL overlap when copying motion more than once - URL params/config fields discrepancies - predefined clock images not working as parameters
1 parent 27cbb2f commit 23d79fd

File tree

2 files changed

+190
-18
lines changed

2 files changed

+190
-18
lines changed

src/app/oxford-debate/setup/page.tsx

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -97,17 +97,20 @@ export default function OxfordDebateSetup() {
9797
parseInt(urlParams.get("adVocemTime") || "") ||
9898
defaultDebateConf.adVocemTime,
9999
endProtectedTime:
100-
parseInt(urlParams.get("protectedTime") || "") ||
100+
parseInt(urlParams.get("endProtectedTime") || "") ||
101101
defaultDebateConf.endProtectedTime,
102102
startProtectedTime:
103103
parseInt(urlParams.get("startProtectedTime") || "") ||
104104
defaultDebateConf.startProtectedTime,
105105
beepOnSpeechEnd: getBooleanParamValue("beepOnSpeechEnd", urlParams),
106106
beepProtectedTime: getBooleanParamValue("beepProtectedTime", urlParams),
107107
visualizeProtectedTimes: false,
108-
clockImageName: urlParams.get("clockImage") ? "custom" : "null",
108+
clockImageName: parseClockImageName(
109+
urlParams.get("clockImageName"),
110+
urlParams.get("customClockImageLink")
111+
),
109112
customClockImageBase64: "",
110-
customClockImageLink: urlParams.get("clockImage") || "",
113+
customClockImageLink: urlParams.get("customClockImageLink") || "",
111114
soundPack: getSoundPack(urlParams),
112115
};
113116
return conf;
@@ -161,6 +164,17 @@ export default function OxfordDebateSetup() {
161164
}
162165
}
163166

167+
function parseClockImageName(
168+
name: string | null,
169+
clockImageLink: string | null
170+
): displayImageType {
171+
if (displayImageTypeArray.includes(name as any)) {
172+
return name as displayImageType;
173+
} else if (!displayImageTypeArray.includes(name as any) && clockImageLink) {
174+
return "custom";
175+
} else return "null";
176+
}
177+
164178
function copyDebateConfigurationLink() {
165179
const currentDebateConf = debateContext.conf;
166180
const params = [];
@@ -173,10 +187,13 @@ export default function OxfordDebateSetup() {
173187
params.push(`${param}=${currentDebateConf[param]}`);
174188
}
175189
}
190+
let link = `${
191+
location.protocol + "//" + location.host + location.pathname
192+
}`;
176193
if (params.length == 0) {
177-
navigator.clipboard.writeText(window.location.href);
194+
navigator.clipboard.writeText(link);
178195
} else {
179-
let link = `${window.location.href}?`;
196+
link += "?";
180197
params.forEach((param) => {
181198
link += `&${param}`;
182199
});
@@ -186,6 +203,7 @@ export default function OxfordDebateSetup() {
186203
link += `&soundPack=${currentDebateConf.soundPack.name}`;
187204
}
188205
navigator.clipboard.writeText(encodeURI(link));
206+
console.log(link);
189207
}
190208
toast.success(debateCopiedMessage);
191209
}

tests/e2e/url-params-parsing.test.ts

Lines changed: 167 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ test.describe("it should be possible to configure debate setups via URL params",
6262
test("time inputs", async ({ page }) => {
6363
// GIVEN
6464
const url =
65-
"http://localhost:3000/oxford-debate/setup?speechTime=240&protectedTime=15&adVocemTime=90";
65+
"http://localhost:3000/oxford-debate/setup?speechTime=240&endProtectedTime=15&adVocemTime=90";
6666
await page.goto(url);
6767
await page.waitForURL(url);
6868

@@ -110,7 +110,7 @@ test.describe("it should be possible to configure debate setups via URL params",
110110
const newOppositionTeam = "Gorsze Wyścigówki Kubicy";
111111
const newMotion = "Należy żałować.";
112112
const url = encodeURI(
113-
`http://localhost:3000/oxford-debate/setup?proTeam=${oldPropositionTeam}&oppTeam=${oldOppositionTeam}&speechTime=240&protectedTime=15&adVocemTime=90&motion=${oldMotion}`
113+
`http://localhost:3000/oxford-debate/setup?proTeam=${oldPropositionTeam}&oppTeam=${oldOppositionTeam}&speechTime=240&endProtectedTime=15&adVocemTime=90&motion=${oldMotion}`
114114
);
115115
await page.goto(url);
116116
await page.waitForURL(url);
@@ -193,10 +193,10 @@ test.describe("it should be possible to configure debate setups via URL params",
193193
).toBe(true);
194194
});
195195

196-
test("url params: clock image", async ({ page }, testinfo) => {
196+
test("clock image from link", async ({ page }, testinfo) => {
197197
// GIVEN
198198
const url =
199-
"http://localhost:3000/oxford-debate/setup?clockImage=https://upload.wikimedia.org/wikipedia/commons/thumb/8/8f/Orange_lambda.svg/459px-Orange_lambda.svg.png";
199+
"http://localhost:3000/oxford-debate/setup?customClockImageLink=https://upload.wikimedia.org/wikipedia/commons/thumb/8/8f/Orange_lambda.svg/459px-Orange_lambda.svg.png";
200200
await page.goto(url);
201201
await page.waitForURL(url);
202202

@@ -215,6 +215,44 @@ test.describe("it should be possible to configure debate setups via URL params",
215215
});
216216
});
217217

218+
test("predefined clock image", async ({ page }, testinfo) => {
219+
// GIVEN
220+
const url = "http://localhost:3000/oxford-debate/setup?&clockImageName=ZSK";
221+
await page.goto(url);
222+
await page.waitForURL(url);
223+
224+
// WHEN
225+
await page.getByRole("button", { name: "Start debate" }).click();
226+
await page.waitForURL("http://localhost:3000/oxford-debate");
227+
const img = await page.getByRole("img", { name: "ZSK" });
228+
229+
// THEN
230+
await expect(img).toHaveJSProperty("complete", true);
231+
await expect(img).toHaveAttribute("data-loaded", "true");
232+
const screenshot = await page.screenshot({ fullPage: true });
233+
await testinfo.attach("url params: custom clock image from link", {
234+
body: screenshot,
235+
contentType: "image/jpg",
236+
});
237+
});
238+
239+
test("soundPacks", async ({ page }) => {
240+
// GIVEN
241+
const soundPackName = "ZTM Poznań";
242+
const url = encodeURI(
243+
`http://localhost:3000/oxford-debate/setup?soundPack=${soundPackName}`
244+
);
245+
await page.goto(url);
246+
await page.waitForURL(url);
247+
248+
// THEN
249+
expect(await getConfiguredSoundPack(soundPackName, page)).toBe(
250+
soundPackName
251+
);
252+
});
253+
});
254+
255+
test.describe("it should be possible to copy configured debate setup as a link", () => {
218256
test("copy motion to clipboard", async ({ page, context, browserName }) => {
219257
// GIVEN
220258
if (browserName == "chromium") {
@@ -271,36 +309,152 @@ test.describe("it should be possible to configure debate setups via URL params",
271309
expect(await getTimeAsSeenByUser("Ad vocem", 2, "minute", page)).toBe(
272310
"2 minutes"
273311
);
274-
expect(await getTimeAsSeenByUser("Protected", 0, "minute", page)).toBe(
275-
"0 minutes"
312+
expect(await getTimeAsSeenByUser("Protected", 1, "minute", page)).toBe(
313+
"1 minute"
276314
);
277315
expect(await getTimeAsSeenByUser("Speech", 15, "second", page)).toBe(
278316
"15 seconds"
279317
);
280318
expect(await getTimeAsSeenByUser("Ad vocem", 15, "second", page)).toBe(
281319
"15 seconds"
282320
);
283-
expect(await getTimeAsSeenByUser("Protected", 30, "second", page)).toBe(
284-
"30 seconds"
321+
expect(await getTimeAsSeenByUser("Protected", 15, "second", page)).toBe(
322+
"15 seconds"
285323
);
286324
expect(await getBooleanButtonValue("Beep on speech end", false, page)).toBe(
287325
false
288326
);
289327
expect(await getConfiguredSoundPack(soundPackName, page));
290328
});
291329

292-
test("soundPacks", async ({ page }) => {
330+
test("copy motion more than once", async ({
331+
page,
332+
context,
333+
browserName,
334+
}, testinfo) => {
293335
// GIVEN
336+
if (browserName == "chromium") {
337+
context.grantPermissions(["clipboard-read", "clipboard-write"]);
338+
// Clipboard permissions are chromium-only
339+
} else {
340+
return;
341+
}
342+
343+
const url = "http://localhost:3000/oxford-debate/setup";
344+
const propositionTeam = "Wyścigówki Kubicy";
345+
const oppositionTeam = "Gorsze Wyścigówki Kubicy";
346+
const motion = "Należy żałować.";
294347
const soundPackName = "ZTM Poznań";
295-
const url = encodeURI(
296-
`http://localhost:3000/oxford-debate/setup?soundPack=${soundPackName}`
297-
);
348+
const newPropositionTeam = "Debate Team Buster";
349+
const newOppositionTeam = "Delusional Debaters";
350+
const newMotion = "Oprogramowanie powinno być dokładnie testowane.";
351+
352+
// WHEN
298353
await page.goto(url);
299354
await page.waitForURL(url);
355+
const propositionTextBox = page.getByPlaceholder("Proposition Team");
356+
await fillAndCheckTextBox(propositionTextBox, propositionTeam, page);
357+
const oppositionTextBox = page.getByPlaceholder("Opposition Team");
358+
await fillAndCheckTextBox(oppositionTextBox, oppositionTeam, page);
359+
const motionTextBox = page.getByPlaceholder("Debate motion");
360+
await fillAndCheckTextBox(motionTextBox, motion, page);
361+
await manuallyChangeTime("Speech", "minute", "decrease", page);
362+
await manuallyChangeTime("Speech", "second", "increase", page);
363+
await manuallyChangeTime("Ad vocem", "minute", "increase", page);
364+
await manuallyChangeTime("Ad vocem", "second", "increase", page);
365+
await manuallyChangeTime("Protected", "minute", "increase", page);
366+
await manuallyChangeTime("Protected", "second", "decrease", page);
367+
await page.getByRole("button", { name: "Beep on speech end" }).click();
368+
await page.getByRole("button", { name: "Default" }).click();
369+
await page.getByText(soundPackName).click();
370+
await page.getByRole("button", { name: "Copy debate" }).click();
371+
page.getByText("Debate link copied to clipboard").waitFor();
300372

301-
// THEN
373+
const clipboardContent = await page.evaluate(() =>
374+
navigator.clipboard.readText()
375+
);
376+
await page.goto(clipboardContent);
377+
await page.waitForURL(clipboardContent);
378+
379+
// Midway sanity check
380+
expect(await getConfiguredTeamName("Proposition", page)).toBe(
381+
propositionTeam
382+
);
383+
expect(await getConfiguredTeamName("Opposition", page)).toBe(
384+
oppositionTeam
385+
);
302386
expect(await getConfiguredSoundPack(soundPackName, page)).toBe(
303387
soundPackName
304388
);
389+
390+
await fillAndCheckTextBox(propositionTextBox, newPropositionTeam, page);
391+
await fillAndCheckTextBox(oppositionTextBox, newOppositionTeam, page);
392+
await fillAndCheckTextBox(motionTextBox, newMotion, page);
393+
await manuallyChangeTime("Speech", "minute", "decrease", page);
394+
await manuallyChangeTime("Speech", "second", "increase", page);
395+
await manuallyChangeTime("Ad vocem", "minute", "increase", page);
396+
await manuallyChangeTime("Ad vocem", "second", "increase", page);
397+
await manuallyChangeTime("Protected", "minute", "increase", page);
398+
await manuallyChangeTime("Protected", "second", "decrease", page);
399+
await page.getByRole("button", { name: "Beep on speech end" }).click();
400+
await page.getByRole("button", { name: soundPackName }).click();
401+
await page.getByText("Default").click();
402+
await page.getByRole("button", { name: "None" }).click();
403+
await page.getByRole("button", { name: "ZSK" }).click();
404+
await page.getByRole("button", { name: "Copy debate" }).click();
405+
page.getByText("Debate link copied to clipboard").waitFor();
406+
407+
const newClipboardContent = await page.evaluate(() =>
408+
navigator.clipboard.readText()
409+
);
410+
await page.goto(newClipboardContent);
411+
await page.waitForURL(newClipboardContent);
412+
413+
// THEN
414+
expect(await getConfiguredMotion(page)).toBe(newMotion);
415+
expect(await getConfiguredTeamName("Proposition", page)).toBe(
416+
newPropositionTeam
417+
);
418+
expect(await getConfiguredTeamName("Opposition", page)).toBe(
419+
newOppositionTeam
420+
);
421+
expect(await getTimeAsSeenByUser("Speech", 3, "minute", page)).toBe(
422+
"3 minutes"
423+
);
424+
expect(await getTimeAsSeenByUser("Ad vocem", 3, "minute", page)).toBe(
425+
"3 minutes"
426+
);
427+
expect(await getTimeAsSeenByUser("Protected", 2, "minute", page)).toBe(
428+
"2 minutes"
429+
);
430+
expect(await getTimeAsSeenByUser("Speech", 30, "second", page)).toBe(
431+
"30 seconds"
432+
);
433+
expect(await getTimeAsSeenByUser("Ad vocem", 30, "second", page)).toBe(
434+
"30 seconds"
435+
);
436+
expect(await getTimeAsSeenByUser("Protected", 0, "second", page)).toBe(
437+
"0 seconds"
438+
);
439+
expect(await getBooleanButtonValue("Beep on speech end", true, page)).toBe(
440+
true
441+
);
442+
expect(await getConfiguredSoundPack("Default", page)).toBe("Default");
443+
await page.getByRole("button", { name: "ZSK" }).waitFor();
444+
445+
await page.getByRole("button", { name: "Start debate" }).click();
446+
await page.waitForURL("http://localhost:3000/oxford-debate");
447+
const img = await page.getByRole("img", { name: "ZSK" });
448+
449+
await expect(img).toHaveJSProperty("complete", true);
450+
await expect(img).toHaveAttribute("data-loaded", "true");
451+
const screenshot = await page.screenshot({ fullPage: true });
452+
await testinfo.attach(
453+
"clock image selected after loading a debate config from link",
454+
{
455+
body: screenshot,
456+
contentType: "image/jpg",
457+
}
458+
);
305459
});
306460
});

0 commit comments

Comments
 (0)