Build Analyzer
analyzes a build and links to new build page with same abilities
Renders/analyzer/u/:identifier/u/:identifier/builds/new
Analyzer page Act
Open the analyzer page
await analyzer.goto();
Assert
new build prompt is not visible
await isNotVisible(analyzer.locators.newBuildPrompt);
Act
Pick weapon “Splattershot”
await analyzer.pickWeapon("Splattershot");Open stat category “movement-category”
await analyzer.openStatCategory("movement-category");Stat card “swim-speed” → swimSpeed
const swimSpeed = analyzer.statCard("swim-speed");swimSpeedSplattershot = (await swimSpeed.baseValue.textContent())!
const swimSpeedSplattershot = (await swimSpeed.baseValue.textContent())!;
Change weapon “Luna Blaster”
await analyzer.changeWeapon("Luna Blaster");Open stat category “movement-category”
await analyzer.openStatCategory("movement-category");
Analyzer stat card Assert
Luna Blaster is a light weapon so it should have lower base swim speed than Splattershot
base value does not read swimSpeedSplattershot
await expect(swimSpeed.baseValue).not.toHaveText(swimSpeedSplattershot);
build value title is not visible
await isNotVisible(swimSpeed.buildValueTitle);
Analyzer page Act
Add ability “SSU”
await analyzer.addAbility("SSU");
Analyzer stat card Assert
build value title is visible
await expect(swimSpeed.buildValueTitle).toBeVisible();
Analyzer page Act
Open new build prompt → buildForm
const buildForm = await analyzer.openNewBuildPrompt();
Build form page Assert
gear select “HEAD” is visible
await expect(buildForm.gearSelect("HEAD")).toBeVisible();weapon pool item “Luna Blaster” is visible
await expect(buildForm.weaponPoolItem("Luna Blaster")).toBeVisible();ability “SSU” is visible
await expect(buildForm.ability("SSU")).toBeVisible();
Source
test("analyzes a build and links to new build page with same abilities", async ({
page,
}) => {
await impersonate(page, NZAP_TEST_ID);
const analyzer = new AnalyzerPage(page);
await analyzer.goto();
await isNotVisible(analyzer.locators.newBuildPrompt);
await analyzer.pickWeapon("Splattershot");
await analyzer.openStatCategory("movement-category");
const swimSpeed = analyzer.statCard("swim-speed");
const swimSpeedSplattershot = (await swimSpeed.baseValue.textContent())!;
await analyzer.changeWeapon("Luna Blaster");
await analyzer.openStatCategory("movement-category");
// Luna Blaster is a light weapon so it should have lower base swim speed than Splattershot
await expect(swimSpeed.baseValue).not.toHaveText(swimSpeedSplattershot);
await isNotVisible(swimSpeed.buildValueTitle);
await analyzer.addAbility("SSU");
await expect(swimSpeed.buildValueTitle).toBeVisible();
const buildForm = await analyzer.openNewBuildPrompt();
await expect(buildForm.gearSelect("HEAD")).toBeVisible();
await expect(buildForm.weaponPoolItem("Luna Blaster")).toBeVisible();
await expect(buildForm.ability("SSU")).toBeVisible();
})Renders/analyzer
Analyzer page Act
Open the analyzer page
await analyzer.goto();
Pick weapon “Splattershot”
await analyzer.pickWeapon("Splattershot");Select tab “build2”
await analyzer.selectTab("build2");Selected ability “SSU” → swimSpeedAbility
const swimSpeedAbility = analyzer.selectedAbility("SSU");Add ability “SSU”
await analyzer.addAbility("SSU");
Assert
swimSpeedAbility is visible
await expect(swimSpeedAbility).toBeVisible();
Act
can't add abilities to build 2 if build 1 is empty -> they automatically go to build 1
Select tab “build2”
await analyzer.selectTab("build2");
Assert
swimSpeedAbility is not visible
await isNotVisible(swimSpeedAbility);
Act
Add ability “SSU”
await analyzer.addAbility("SSU");
Assert
swimSpeedAbility is visible
await expect(swimSpeedAbility).toBeVisible();
Act
Add ability “SSU”
await analyzer.addAbility("SSU");
Assert
swimSpeedAbility count is 2
await expect(swimSpeedAbility).toHaveCount(2);
Act
Select tab “ap”
await analyzer.selectTab("ap");
Assert
first ap comparison 1 contains “10AP”
await expect(analyzer.apComparison(1).first()).toContainText("10AP");first ap comparison 2 contains “13AP”
await expect(analyzer.apComparison(2).first()).toContainText("13AP");build value title contains “Build 2”
await expect(analyzer.statCard("swim-speed").buildValueTitle).toContainText(
"Build 2",
);
Source
test("compares builds", async ({ page }) => {
const analyzer = new AnalyzerPage(page);
await analyzer.goto();
await analyzer.pickWeapon("Splattershot");
await analyzer.selectTab("build2");
const swimSpeedAbility = analyzer.selectedAbility("SSU");
await analyzer.addAbility("SSU");
await expect(swimSpeedAbility).toBeVisible();
// can't add abilities to build 2 if build 1 is empty
// -> they automatically go to build 1
await analyzer.selectTab("build2");
await isNotVisible(swimSpeedAbility);
await analyzer.addAbility("SSU");
await expect(swimSpeedAbility).toBeVisible();
await analyzer.addAbility("SSU");
await expect(swimSpeedAbility).toHaveCount(2);
await analyzer.selectTab("ap");
await expect(analyzer.apComparison(1).first()).toContainText("10AP");
await expect(analyzer.apComparison(2).first()).toContainText("13AP");
await expect(analyzer.statCard("swim-speed").buildValueTitle).toContainText(
"Build 2",
);
})keeps ability effects switched on while either build is edited
Renders/analyzer
Analyzer page Act
Open the analyzer page
await analyzer.goto();
Pick weapon “Splattershot”
await analyzer.pickWeapon("Splattershot");Effect switch “Opening Gambit” → openingGambit
const openingGambit = analyzer.effectSwitch("Opening Gambit");Effect switch “Drop Roller” → dropRoller
const dropRoller = analyzer.effectSwitch("Drop Roller");Add ability “OG”
await analyzer.addAbility("OG");Toggle effect “Opening Gambit”
await analyzer.toggleEffect("Opening Gambit");
Assert
openingGambit is checked
await expect(openingGambit).toBeChecked();
Act
Select tab “build2”
await analyzer.selectTab("build2");Add ability “DR”
await analyzer.addAbility("DR");Toggle effect “Drop Roller”
await analyzer.toggleEffect("Drop Roller");
Assert
dropRoller is checked
await expect(dropRoller).toBeChecked();
Act
Add ability “SSU”
await analyzer.addAbility("SSU");
Assert
selected ability “SSU” is visible
await expect(analyzer.selectedAbility("SSU")).toBeVisible();openingGambit is checked
await expect(openingGambit).toBeChecked();
dropRoller is checked
await expect(dropRoller).toBeChecked();
Act
Select tab “build1”
await analyzer.selectTab("build1");Add ability “SSU”
await analyzer.addAbility("SSU");
Assert
selected ability “SSU” is visible
await expect(analyzer.selectedAbility("SSU")).toBeVisible();openingGambit is checked
await expect(openingGambit).toBeChecked();
dropRoller is checked
await expect(dropRoller).toBeChecked();
Act
Drop Roller's 30AP on top of the SSU main build 2 has
Select tab “ap”
await analyzer.selectTab("ap");
Assert
filter has text /^40AP$/ count is 1
await expect(
analyzer.apComparison(2).filter({ hasText: /^40AP$/ }),
).toHaveCount(1);
Source
test("keeps ability effects switched on while either build is edited", async ({
page,
}) => {
const analyzer = new AnalyzerPage(page);
await analyzer.goto();
await analyzer.pickWeapon("Splattershot");
const openingGambit = analyzer.effectSwitch("Opening Gambit");
const dropRoller = analyzer.effectSwitch("Drop Roller");
await analyzer.addAbility("OG");
await analyzer.toggleEffect("Opening Gambit");
await expect(openingGambit).toBeChecked();
await analyzer.selectTab("build2");
await analyzer.addAbility("DR");
await analyzer.toggleEffect("Drop Roller");
await expect(dropRoller).toBeChecked();
await analyzer.addAbility("SSU");
await expect(analyzer.selectedAbility("SSU")).toBeVisible();
await expect(openingGambit).toBeChecked();
await expect(dropRoller).toBeChecked();
await analyzer.selectTab("build1");
await analyzer.addAbility("SSU");
await expect(analyzer.selectedAbility("SSU")).toBeVisible();
await expect(openingGambit).toBeChecked();
await expect(dropRoller).toBeChecked();
// Drop Roller's 30AP on top of the SSU main build 2 has
await analyzer.selectTab("ap");
await expect(
analyzer.apComparison(2).filter({ hasText: /^40AP$/ }),
).toHaveCount(1);
})AnalyzerPage.gotoe2e/pages/analyzer/analyzer-page.ts:27
No JSDoc
async goto() {
await navigate({ page: this.page, url: ANALYZER_URL });
}AnalyzerPage.locators.newBuildPrompte2e/pages/analyzer/analyzer-page.ts:17
No JSDoc
page.getByTestId("new-build-prompt")isNotVisiblee2e/helpers/playwright.ts:745
No JSDoc
export function isNotVisible(locator: Locator) {
return expect(locator).toHaveCount(0);
}AnalyzerPage.pickWeapone2e/pages/analyzer/analyzer-page.ts:49
async pickWeapon(name: string) {
const { weaponLanding } = this.locators;
await weaponLanding.getByRole("searchbox").fill(name);
await weaponLanding.getByText(name, { exact: true }).click();
}AnalyzerPage.openStatCategorye2e/pages/analyzer/analyzer-page.ts:60
No JSDoc
async openStatCategory(testId: string) {
await this.page.getByTestId(testId).click();
}AnalyzerPage.statCarde2e/pages/analyzer/analyzer-page.ts:31
No JSDoc
statCard(testId: string) {
return new AnalyzerStatCard(this.page, testId);
}AnalyzerPage.changeWeapone2e/pages/analyzer/analyzer-page.ts:55
No JSDoc
async changeWeapon(name: string) {
await this.locators.backToWeaponLandingLink.click();
await this.pickWeapon(name);
}AnalyzerStatCard.baseValuee2e/pages/analyzer/analyzer-page.ts:101
No JSDoc
get baseValue() {
return this.root.getByTestId(`${this.testId}-base`);
}AnalyzerStatCard.buildValueTitlee2e/pages/analyzer/analyzer-page.ts:105
No JSDoc
get buildValueTitle() {
return this.root.getByTestId(`${this.testId}-build-title`);
}AnalyzerPage.addAbilitye2e/pages/analyzer/analyzer-page.ts:68
No JSDoc
async addAbility(ability: Ability) {
await this.page.getByTestId(`${ability}-ability-button`).click();
}AnalyzerPage.openNewBuildPrompte2e/pages/analyzer/analyzer-page.ts:76
No JSDoc
async openNewBuildPrompt() {
await this.locators.newBuildPrompt.click();
return new BuildFormPage(this.page);
}BuildFormPage.gearSelecte2e/pages/builds/build-form-page.ts:21
No JSDoc
gearSelect(type: GearType) {
return this.page.getByTestId(`${type}-gear-select`);
}BuildFormPage.weaponPoolIteme2e/pages/builds/build-form-page.ts:29
No JSDoc
weaponPoolItem(weaponName: string) {
return this.page.getByRole("listitem").getByText(weaponName);
}BuildFormPage.abilitye2e/pages/builds/build-form-page.ts:25
No JSDoc
ability(ability: Ability) {
return this.page.getByTestId(`${ability}-ability`);
}AnalyzerPagee2e/pages/analyzer/analyzer-page.ts:10
No JSDoc
AnalyzerStatCarde2e/pages/analyzer/analyzer-page.ts:92
No JSDoc
BuildFormPagee2e/pages/builds/build-form-page.ts:8
No JSDoc
AnalyzerPage.selectTabe2e/pages/analyzer/analyzer-page.ts:64
No JSDoc
async selectTab(tab: AnalyzerTab) {
await this.page.getByTestId(`${tab}-tab`).click();
}AnalyzerPage.selectedAbilitye2e/pages/analyzer/analyzer-page.ts:35
No JSDoc
selectedAbility(ability: Ability) {
return this.locators.abilitySelector.getByTestId(`${ability}-ability`);
}AnalyzerPage.apComparisone2e/pages/analyzer/analyzer-page.ts:44
No JSDoc
apComparison(buildNumber: 1 | 2) {
return this.page.getByTestId(`ap-compare-${buildNumber}`);
}AnalyzerPage.effectSwitche2e/pages/analyzer/analyzer-page.ts:40
effectSwitch(name: string) {
return this.page.getByRole("switch", { name, exact: true });
}AnalyzerPage.toggleEffecte2e/pages/analyzer/analyzer-page.ts:72
No JSDoc
async toggleEffect(name: string) {
await this.effectSwitch(name).click({ force: true });
}