e2e-tests: Remove unchecked casts of DOM objects.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
Anders Kaseorg
2023-10-24 17:19:36 -07:00
committed by Tim Abbott
parent af8465b7fd
commit da80661592
7 changed files with 49 additions and 57 deletions

View File

@@ -1,6 +1,6 @@
import {strict as assert} from "assert"; import {strict as assert} from "assert";
import type {ElementHandle, Page} from "puppeteer"; import type {Page} from "puppeteer";
import * as common from "./lib/common"; import * as common from "./lib/common";
@@ -156,11 +156,9 @@ async function test_organization_permissions(page: Page): Promise<void> {
async function test_add_emoji(page: Page): Promise<void> { async function test_add_emoji(page: Page): Promise<void> {
await common.fill_form(page, "#add-custom-emoji-form", {name: "zulip logo"}); await common.fill_form(page, "#add-custom-emoji-form", {name: "zulip logo"});
const emoji_upload_handle = await page.$("#emoji_file_input"); const emoji_upload_handle = await page.$("input#emoji_file_input");
assert.ok(emoji_upload_handle); assert.ok(emoji_upload_handle);
await (emoji_upload_handle as ElementHandle<HTMLInputElement>).uploadFile( await emoji_upload_handle.uploadFile("static/images/logo/zulip-icon-128x128.png");
"static/images/logo/zulip-icon-128x128.png",
);
await page.click("#add-custom-emoji-modal .dialog_submit_button"); await page.click("#add-custom-emoji-modal .dialog_submit_button");
await common.wait_for_micromodal_to_close(page); await common.wait_for_micromodal_to_close(page);
@@ -194,11 +192,9 @@ async function test_custom_realm_emoji(page: Page): Promise<void> {
} }
async function test_upload_realm_icon_image(page: Page): Promise<void> { async function test_upload_realm_icon_image(page: Page): Promise<void> {
const upload_handle = await page.$("#realm-icon-upload-widget .image_file_input"); const upload_handle = await page.$("#realm-icon-upload-widget input.image_file_input");
assert.ok(upload_handle); assert.ok(upload_handle);
await (upload_handle as ElementHandle<HTMLInputElement>).uploadFile( await upload_handle.uploadFile("static/images/logo/zulip-icon-128x128.png");
"static/images/logo/zulip-icon-128x128.png",
);
await page.waitForSelector("#realm-icon-upload-widget .upload-spinner-background", { await page.waitForSelector("#realm-icon-upload-widget .upload-spinner-background", {
visible: true, visible: true,

View File

@@ -37,7 +37,7 @@ async function copy_messages(
ctrlKey: true, ctrlKey: true,
keyCode: 67, keyCode: 67,
which: 67, which: 67,
} as KeyboardEventInit), }),
); );
// find temp div with copied text // find temp div with copied text

View File

@@ -140,13 +140,12 @@ export async function fill_form(
return (await page.$(`select[name="${CSS.escape(name)}"]`)) !== null; return (await page.$(`select[name="${CSS.escape(name)}"]`)) !== null;
} }
for (const name of Object.keys(params)) { for (const name of Object.keys(params)) {
const name_selector = `${form_selector} [name="${name}"]`;
const value = params[name]; const value = params[name];
if (typeof value === "boolean") { if (typeof value === "boolean") {
await page.$eval( await page.$eval(
name_selector, `${form_selector} input[name="${CSS.escape(name)}"]`,
(el, value) => { (el, value) => {
if (el instanceof HTMLInputElement && el.checked !== value) { if (el.checked !== value) {
el.click(); el.click();
} }
}, },
@@ -156,13 +155,9 @@ export async function fill_form(
if (typeof value !== "string") { if (typeof value !== "string") {
throw new TypeError(`Expected string for ${name}`); throw new TypeError(`Expected string for ${name}`);
} }
await page.select(name_selector, value); await page.select(`${form_selector} select[name="${CSS.escape(name)}"]`, value);
} else { } else {
// clear any existing text in the input field before filling. await clear_and_type(page, `${form_selector} [name="${CSS.escape(name)}"`, value);
await page.$eval(name_selector, (el) => {
(el as HTMLInputElement).value = "";
});
await page.type(name_selector, value);
} }
} }
} }
@@ -173,17 +168,24 @@ export async function check_form_contents(
params: Record<string, boolean | string>, params: Record<string, boolean | string>,
): Promise<void> { ): Promise<void> {
for (const name of Object.keys(params)) { for (const name of Object.keys(params)) {
const name_selector = `${form_selector} [name="${name}"]`;
const expected_value = params[name]; const expected_value = params[name];
if (typeof expected_value === "boolean") { if (typeof expected_value === "boolean") {
assert.equal( assert.equal(
await page.$eval(name_selector, (el) => (el as HTMLInputElement).checked), await page.$eval(
`${form_selector} input[name="${CSS.escape(name)}"]`,
(el) => el.checked,
),
expected_value, expected_value,
"Form content is not as expected.", "Form content is not as expected.",
); );
} else { } else {
assert.equal( assert.equal(
await page.$eval(name_selector, (el) => (el as HTMLInputElement).value), await page.$eval(`${form_selector} [name="${CSS.escape(name)}"]`, (el) => {
if (!(el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement)) {
throw new TypeError("Expected <input> or <textarea>");
}
return el.value;
}),
expected_value, expected_value,
"Form content is not as expected.", "Form content is not as expected.",
); );
@@ -266,8 +268,8 @@ export async function log_in(
username: credentials.username, username: credentials.username,
password: credentials.password, password: credentials.password,
}; };
await fill_form(page, "#login_form", params); await fill_form(page, "form#login_form", params);
await page.$eval("#login_form", (form) => (form as HTMLFormElement).submit()); await page.$eval("form#login_form", (form) => form.submit());
await page.waitForSelector("#recent_view_filter_buttons", {visible: true}); await page.waitForSelector("#recent_view_filter_buttons", {visible: true});
} }
@@ -295,8 +297,8 @@ export function set_realm_url(new_realm_url: string): void {
export async function ensure_enter_does_not_send(page: Page): Promise<void> { export async function ensure_enter_does_not_send(page: Page): Promise<void> {
// NOTE: Caller should ensure that the compose box is already open. // NOTE: Caller should ensure that the compose box is already open.
const enter_sends = await page.$eval( const enter_sends = await page.$eval(
".enter_sends_true", "span.enter_sends_true",
(el) => (el as HTMLElement).style.display !== "none", (el) => el.style.display !== "none",
); );
if (enter_sends) { if (enter_sends) {
@@ -311,13 +313,12 @@ export async function assert_compose_box_content(
page: Page, page: Page,
expected_value: string, expected_value: string,
): Promise<void> { ): Promise<void> {
const compose_box_element = await page.waitForSelector("#compose-textarea"); const compose_box_element = await page.waitForSelector("textarea#compose-textarea");
const compose_box_content = await page.evaluate((element) => { assert(compose_box_element !== null);
if (!(element instanceof HTMLTextAreaElement)) { const compose_box_content = await page.evaluate(
throw new TypeError("expected HTMLTextAreaElement"); (element) => element.value,
} compose_box_element,
return element.value; );
}, compose_box_element);
assert.equal( assert.equal(
compose_box_content, compose_box_content,
expected_value, expected_value,

View File

@@ -15,11 +15,11 @@ async function realm_creation_tests(page: Page): Promise<void> {
await page.waitForSelector("#email"); await page.waitForSelector("#email");
await page.type("#email", email); await page.type("#email", email);
await page.type("#id_team_name", organization_name); await page.type("#id_team_name", organization_name);
await page.$eval("#realm_in_root_domain", (el) => (el as HTMLInputElement).click()); await page.$eval("input#realm_in_root_domain", (el) => el.click());
await Promise.all([ await Promise.all([
page.waitForNavigation(), page.waitForNavigation(),
page.$eval("#create_realm", (form) => (form as HTMLFormElement).submit()), page.$eval("form#create_realm", (form) => form.submit()),
]); ]);
// Make sure confirmation email is sent. // Make sure confirmation email is sent.
@@ -59,7 +59,7 @@ async function realm_creation_tests(page: Page): Promise<void> {
// For some reason, page.click() does not work this for particular checkbox // For some reason, page.click() does not work this for particular checkbox
// so use page.$eval here to call the .click method in the browser. // so use page.$eval here to call the .click method in the browser.
await common.fill_form(page, "#registration", params); await common.fill_form(page, "#registration", params);
await page.$eval("#registration", (form) => (form as HTMLFormElement).submit()); await page.$eval("form#registration", (form) => form.submit());
// Check if realm is created and user is logged in by checking if // Check if realm is created and user is logged in by checking if
// element of id `lightbox_overlay` exists. // element of id `lightbox_overlay` exists.

View File

@@ -20,7 +20,7 @@ async function _add_playground_and_return_status(page: Page, payload: Playground
await common.fill_form(page, "form.admin-playground-form", payload); await common.fill_form(page, "form.admin-playground-form", payload);
// Not sure why, but page.click() doesn't seem to always click the submit button. // Not sure why, but page.click() doesn't seem to always click the submit button.
// So we resort to using eval with the button ID instead. // So we resort to using eval with the button ID instead.
await page.$eval("#submit_playground_button", (el) => (el as HTMLInputElement).click()); await page.$eval("button#submit_playground_button", (el) => el.click());
// We return the success/failure status message back to the caller. // We return the success/failure status message back to the caller.
await page.waitForSelector(admin_playground_status_selector, {visible: true}); await page.waitForSelector(admin_playground_status_selector, {visible: true});

View File

@@ -1,6 +1,6 @@
import {strict as assert} from "assert"; import {strict as assert} from "assert";
import type {ElementHandle, Page} from "puppeteer"; import type {Page} from "puppeteer";
import {test_credentials} from "../../var/puppeteer/test_credentials"; import {test_credentials} from "../../var/puppeteer/test_credentials";
@@ -13,8 +13,8 @@ const zuliprc_regex =
/^data:application\/octet-stream;charset=utf-8,\[api]\nemail=.+\nkey=.+\nsite=.+\n$/; /^data:application\/octet-stream;charset=utf-8,\[api]\nemail=.+\nkey=.+\nsite=.+\n$/;
async function get_decoded_url_in_selector(page: Page, selector: string): Promise<string> { async function get_decoded_url_in_selector(page: Page, selector: string): Promise<string> {
const a = (await page.$(selector)) as ElementHandle<HTMLAnchorElement>; const a = await page.$(`a:is(${selector})`);
return decodeURIComponent(await (await a.getProperty("href")).jsonValue()); return decodeURIComponent(await (await a!.getProperty("href")).jsonValue());
} }
async function open_settings(page: Page): Promise<void> { async function open_settings(page: Page): Promise<void> {
@@ -198,9 +198,8 @@ async function test_edit_bot_form(page: Page): Promise<void> {
const edit_form_selector = `#bot-edit-form[data-email="${CSS.escape(bot1_email)}"]`; const edit_form_selector = `#bot-edit-form[data-email="${CSS.escape(bot1_email)}"]`;
await page.waitForSelector(edit_form_selector, {visible: true}); await page.waitForSelector(edit_form_selector, {visible: true});
const name_field_selector = edit_form_selector + " [name=full_name]";
assert.equal( assert.equal(
await page.$eval(name_field_selector, (el) => (el as HTMLInputElement).value), await page.$eval(`${edit_form_selector} input[name=full_name]`, (el) => el.value),
"Bot 1", "Bot 1",
); );
@@ -233,9 +232,8 @@ async function test_invalid_edit_bot_form(page: Page): Promise<void> {
const edit_form_selector = `#bot-edit-form[data-email="${CSS.escape(bot1_email)}"]`; const edit_form_selector = `#bot-edit-form[data-email="${CSS.escape(bot1_email)}"]`;
await page.waitForSelector(edit_form_selector, {visible: true}); await page.waitForSelector(edit_form_selector, {visible: true});
const name_field_selector = edit_form_selector + " [name=full_name]";
assert.equal( assert.equal(
await page.$eval(name_field_selector, (el) => (el as HTMLInputElement).value), await page.$eval(`${edit_form_selector} input[name=full_name]`, (el) => el.value),
"Bot one", "Bot one",
); );

View File

@@ -3,21 +3,18 @@ import type {Page} from "puppeteer";
import * as common from "./lib/common"; import * as common from "./lib/common";
async function open_set_user_status_modal(page: Page): Promise<void> { async function open_set_user_status_modal(page: Page): Promise<void> {
const menu_icon_selector = ".user_sidebar_entry:first-child .user-list-sidebar-menu-icon";
// We are clicking on the menu icon with the help of `waitForFunction` because the list // We are clicking on the menu icon with the help of `waitForFunction` because the list
// re-renders many times and can cause the element to become stale. // re-renders many times and can cause the element to become stale.
await page.waitForFunction( await page.waitForFunction((): boolean => {
(selector: string): boolean => { const menu_icon = document.querySelector<HTMLSpanElement>(
const menu_icon = document.querySelector(selector); ".user_sidebar_entry:first-child span.user-list-sidebar-menu-icon",
if (menu_icon) { );
(menu_icon as HTMLSpanElement).click(); if (menu_icon) {
return true; menu_icon.click();
} return true;
return false; }
}, return false;
{}, });
menu_icon_selector,
);
await page.waitForSelector(".user_popover_email", {visible: true}); await page.waitForSelector(".user_popover_email", {visible: true});
// We are using evaluate to click because it is very hard to detect if the user info popover has opened. // We are using evaluate to click because it is very hard to detect if the user info popover has opened.
await page.evaluate(() => await page.evaluate(() =>