aboutsummaryrefslogtreecommitdiffstats
path: root/test/playwright/tests/symbols.spec.mjs
diff options
context:
space:
mode:
Diffstat (limited to 'test/playwright/tests/symbols.spec.mjs')
-rw-r--r--test/playwright/tests/symbols.spec.mjs77
1 files changed, 77 insertions, 0 deletions
diff --git a/test/playwright/tests/symbols.spec.mjs b/test/playwright/tests/symbols.spec.mjs
new file mode 100644
index 000000000..2a1cca74b
--- /dev/null
+++ b/test/playwright/tests/symbols.spec.mjs
@@ -0,0 +1,77 @@
+import {expect, test} from "@playwright/test";
+import {login} from "../helpers/auth.mjs";
+
+test.describe("Symbols", () => {
+ test.beforeEach(async ({page}, testInfo) => {
+ const {enablePassword} = testInfo.project.use.rspamdPasswords;
+ await login(page, enablePassword);
+ await page.locator("#symbols_nav").click();
+ await expect(page.locator("#symbolsTable")).toBeVisible();
+ // Ensure table data has been loaded before running tests
+ await expect(page.locator("#symbolsTable tbody tr").first()).toBeVisible();
+ });
+
+ test("shows list and allows filtering by group", async ({page}) => {
+ // Check filtering by group (if selector exists)
+ const groupSelect = page.locator(".footable-filtering select.form-select").first();
+ if (await groupSelect.count()) {
+ // Ensure there is at least one real group besides "Any group"
+ const optionCount = await groupSelect.evaluate((el) => el.options.length);
+ expect(optionCount).toBeGreaterThan(1);
+
+ // Read target group's value and text BEFORE selection to avoid FooTable redraw races
+ const target = await groupSelect.evaluate((el) => {
+ const [, op] = Array.from(el.options); // first non-default option
+ return {text: op.text, value: op.value};
+ });
+
+ const groupCells = page.locator("#symbolsTable tbody tr td.footable-first-visible");
+ const beforeTexts = await groupCells.allTextContents();
+
+ await groupSelect.selectOption({value: target.value});
+ const selectedGroup = target.text.toLowerCase();
+
+ // Wait until table content updates (using expect.poll with matcher)
+ await expect.poll(async () => {
+ const texts = await groupCells.allTextContents();
+ return texts.join("|");
+ }, {timeout: 5000}).not.toBe(beforeTexts.join("|"));
+
+ const afterTexts = await groupCells.allTextContents();
+
+ // Validate that all visible rows belong to the selected group
+ for (const text of afterTexts) {
+ expect(text.toLowerCase()).toContain(selectedGroup);
+ }
+ }
+ });
+
+ test.describe.configure({mode: "serial"});
+ test("edits score for the first symbol and saves", async ({page}) => {
+ const scoreInput = page.locator("#symbolsTable .scorebar").first();
+ const scoreInputId = await scoreInput.evaluate((element) => element.id);
+ const oldValue = await scoreInput.inputValue();
+
+ // Try to change the score value for the first symbol
+ await scoreInput.fill((parseFloat(oldValue) + 0.01).toFixed(2));
+ await scoreInput.blur();
+
+ // A save notification should appear
+ const saveAlert = page.locator("#save-alert");
+ await expect(saveAlert).toBeVisible();
+
+ // Save changes
+ await saveAlert.getByRole("button", {exact: true, name: "Save"}).click();
+
+ // A success alert should appear (wait for any alert-success)
+ const alertSuccess = page.locator(".alert-success, .alert-modal.alert-success");
+ await expect(alertSuccess).toBeVisible();
+
+ // Revert to the old value (clean up after the test)
+ await expect(alertSuccess).not.toBeVisible({timeout: 10000});
+ const revertedScoreInput = page.locator("#" + scoreInputId);
+ await revertedScoreInput.fill(oldValue);
+ await revertedScoreInput.blur();
+ await saveAlert.getByRole("button", {exact: true, name: "Save"}).click();
+ });
+});