sendou.ink/e2e/comp-analyzer.spec.ts
2026-07-29 12:15:09 +03:00

167 lines
5.6 KiB
TypeScript

import { expect, test } from "./helpers/playwright";
import { CompAnalyzerPage } from "./pages/comp-analyzer/comp-analyzer-page";
test.describe("Composition Analyzer", () => {
test("weapon selection, removal, and URL persistence", async ({ page }) => {
const compAnalyzer = new CompAnalyzerPage(page);
await compAnalyzer.goto();
await expect(compAnalyzer.locators.selectedWeapons).toBeVisible();
await expect(compAnalyzer.locators.emptyWeaponSlots).toHaveCount(4);
await compAnalyzer.selectWeapon(40);
// First slot should now have the weapon
await expect(compAnalyzer.selectedWeapon(0)).toBeVisible();
await expect(compAnalyzer.locators.emptyWeaponSlots).toHaveCount(3);
await compAnalyzer.removeWeapon(0);
await expect(compAnalyzer.locators.emptyWeaponSlots).toHaveCount(4);
// Select 4 weapons to test auto-collapse
await expect(compAnalyzer.locators.categorizationToggle).toBeVisible();
await compAnalyzer.selectWeapon(40);
await compAnalyzer.selectWeapon(50);
await compAnalyzer.selectWeapon(60);
await compAnalyzer.selectWeapon(70);
await expect(compAnalyzer.locators.categorizationToggle).not.toBeVisible();
expect(page.url()).toContain("weapons=");
// Weapons should still be selected after reload
await page.reload();
await expect(compAnalyzer.selectedWeapon(0)).toBeVisible();
await expect(compAnalyzer.selectedWeapon(1)).toBeVisible();
await expect(compAnalyzer.selectedWeapon(2)).toBeVisible();
await expect(compAnalyzer.selectedWeapon(3)).toBeVisible();
});
test("weapon grid controls and categorization", async ({ page }) => {
const compAnalyzer = new CompAnalyzerPage(page);
await compAnalyzer.goto();
await expect(compAnalyzer.categorizationRadio("category")).toBeChecked();
await compAnalyzer.selectCategorization("sub");
await expect(compAnalyzer.categorizationRadio("sub")).toBeChecked();
await compAnalyzer.selectCategorization("special");
await expect(compAnalyzer.categorizationRadio("special")).toBeChecked();
// Grid should be expanded
await expect(compAnalyzer.locators.categorizationToggle).toBeVisible();
await compAnalyzer.toggleWeaponGrid();
await expect(compAnalyzer.locators.categorizationToggle).not.toBeVisible();
await compAnalyzer.toggleWeaponGrid();
await expect(compAnalyzer.locators.categorizationToggle).toBeVisible();
// Switch categorization and test URL persistence
await compAnalyzer.selectCategorization("sub");
expect(page.url()).toContain("categorization=sub");
await page.reload();
await expect(compAnalyzer.categorizationRadio("sub")).toBeChecked();
});
test("analysis sections appear and can be collapsed", async ({ page }) => {
const compAnalyzer = new CompAnalyzerPage(page);
await compAnalyzer.goto();
const damageCombos = compAnalyzer.damageCombos;
// Both should not be visible initially
await expect(damageCombos.root).not.toBeVisible();
await expect(compAnalyzer.locators.rangeVisualization).not.toBeVisible();
// Select two weapons with range data (blaster - ID 210)
await compAnalyzer.selectWeapon(40);
await compAnalyzer.selectWeapon(210);
await expect(damageCombos.root).toBeVisible();
await expect(compAnalyzer.locators.rangeVisualization).toBeVisible();
// Should be expanded by default
await expect(damageCombos.content).toBeVisible();
await damageCombos.toggleCollapsed();
await expect(damageCombos.content).not.toBeVisible();
await damageCombos.toggleCollapsed();
await expect(damageCombos.content).toBeVisible();
});
test("damage combo sliders and filtering work correctly", async ({
page,
}) => {
const compAnalyzer = new CompAnalyzerPage(page);
await compAnalyzer.goto();
// Splattershot Jr. has Splat Bomb sub
await compAnalyzer.selectWeapon(10);
await compAnalyzer.selectWeapon(40);
const damageCombos = compAnalyzer.damageCombos;
await expect(damageCombos.root).toBeVisible();
// Part 1: Test Sub Defense slider
const initialDamageValues =
await damageCombos.damageValues.allTextContents();
await damageCombos.subDefenseSlider.fill("57");
// Damage of sub weapons should be reduced
const newDamageValues = await damageCombos.damageValues.allTextContents();
expect(initialDamageValues.join(",")).not.toEqual(
newDamageValues.join(","),
);
await damageCombos.subDefenseSlider.fill("0");
// Part 2: Test Ink Resistance slider
const initialInkTimes = await damageCombos.inkTimes.allTextContents();
await damageCombos.inkResistanceSlider.fill("57");
const newInkTimes = await damageCombos.inkTimes.allTextContents();
// If there were ink times, they should have increased or more ink combos should appear
if (initialInkTimes.length > 0 || newInkTimes.length > 0) {
const initialTotalFrames = initialInkTimes.reduce(
(sum, t) => sum + (Number.parseInt(t, 10) || 0),
0,
);
const newTotalFrames = newInkTimes.reduce(
(sum, t) => sum + (Number.parseInt(t, 10) || 0),
0,
);
expect(newTotalFrames).toBeGreaterThanOrEqual(initialTotalFrames);
}
// Part 3: Test damage type filtering
const firstDamageTypeLabel = damageCombos.damageTypeLabels.first();
const damageTypeText = await firstDamageTypeLabel.textContent();
await expect(damageCombos.filteredItems).toHaveCount(0);
await firstDamageTypeLabel.click();
const filteredCount = await damageCombos.filteredItems.count();
expect(filteredCount).toBeGreaterThan(0);
await expect(damageCombos.filteredItems.first()).toContainText(
damageTypeText ?? "",
);
// Clicking a filtered item restores it
await damageCombos.filteredItems.first().click();
await expect(damageCombos.filteredItems).toHaveCount(filteredCount - 1);
});
});