1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
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();
});
});
|