ui improvements
This commit is contained in:
224
tests/utils/page-objects.ts
Normal file
224
tests/utils/page-objects.ts
Normal file
@@ -0,0 +1,224 @@
|
||||
import { Page, Locator } from '@playwright/test';
|
||||
|
||||
export class DP2FormPage {
|
||||
readonly page: Page;
|
||||
|
||||
// Form fields
|
||||
readonly playerNameInput: Locator;
|
||||
readonly currentPointsInput: Locator;
|
||||
readonly crimeCategoryButtons: { [key: string]: Locator };
|
||||
readonly specificOffenseSelectTrigger: Locator;
|
||||
|
||||
// Crime details sections
|
||||
readonly offenseDetailsSection: Locator;
|
||||
|
||||
// Special item inputs (for theft)
|
||||
readonly specialItems: {
|
||||
elytra: Locator;
|
||||
netherStar: Locator;
|
||||
beacon: Locator;
|
||||
netheriteBlock: Locator;
|
||||
diamondBlock: Locator;
|
||||
};
|
||||
|
||||
// Additional item inputs
|
||||
readonly additionalItemInputs: Locator;
|
||||
|
||||
// Block/Entity count inputs
|
||||
readonly blockCountInput: Locator;
|
||||
readonly entityCountInput: Locator;
|
||||
|
||||
// SPP checkbox
|
||||
readonly sppCheckbox: Locator;
|
||||
|
||||
// Submit button
|
||||
readonly calculateButton: Locator;
|
||||
|
||||
// Results section
|
||||
readonly resultsSection: Locator;
|
||||
readonly commandsList: Locator;
|
||||
readonly summarySection: Locator;
|
||||
readonly explanationTextarea: Locator;
|
||||
readonly resetButton: Locator;
|
||||
|
||||
constructor(page: Page) {
|
||||
this.page = page;
|
||||
|
||||
// Form fields
|
||||
this.playerNameInput = page.locator('input[id="playerName"]');
|
||||
this.currentPointsInput = page.locator('input[id="currentPoints"]');
|
||||
|
||||
// Crime category buttons
|
||||
this.crimeCategoryButtons = {
|
||||
all: page.locator('button').filter({ hasText: 'all' }),
|
||||
item: page.locator('button').filter({ hasText: 'item offenses' }),
|
||||
block: page.locator('button').filter({ hasText: 'block offenses' }),
|
||||
hacking: page.locator('button').filter({ hasText: 'hacking offenses' }),
|
||||
communication: page.locator('button').filter({ hasText: 'communication offenses' }),
|
||||
};
|
||||
|
||||
this.specificOffenseSelectTrigger = page.locator('button').filter({ hasText: 'select an offense' });
|
||||
|
||||
// Crime details
|
||||
this.offenseDetailsSection = page.locator('h3').filter({ hasText: 'offense details' }).locator('..');
|
||||
|
||||
// Special items
|
||||
this.specialItems = {
|
||||
elytra: page.locator('input').filter({ has: page.locator('xpath=preceding-sibling::span[text()="elytra (20 points)"]') }),
|
||||
netherStar: page.locator('input').filter({ has: page.locator('xpath=preceding-sibling::span[text()="nether star (20 points)"]') }),
|
||||
beacon: page.locator('input').filter({ has: page.locator('xpath=preceding-sibling::span[text()="beacon (20 points)"]') }),
|
||||
netheriteBlock: page.locator('input').filter({ has: page.locator('xpath=preceding-sibling::span[text()="netherite block (10 points)"]') }),
|
||||
diamondBlock: page.locator('input').filter({ has: page.locator('xpath=preceding-sibling::span[text()="diamond block (10 points)"]') }),
|
||||
};
|
||||
|
||||
// Additional items
|
||||
this.additionalItemInputs = page.locator('label').filter({ hasText: 'additional items stolen' }).locator('..');
|
||||
|
||||
// Block/Entity inputs
|
||||
this.blockCountInput = page.locator('input[id="blockCount"]');
|
||||
this.entityCountInput = page.locator('input[id="entityCount"]');
|
||||
|
||||
// SPP checkbox
|
||||
this.sppCheckbox = page.locator('input[id="isSPP"]');
|
||||
|
||||
// Submit button
|
||||
this.calculateButton = page.locator('button[type="submit"]');
|
||||
|
||||
// Results
|
||||
this.resultsSection = page.locator('h3').filter({ hasText: 'results' }).locator('..').locator('..');
|
||||
this.commandsList = this.resultsSection.locator('label').filter({ hasText: 'commands' }).locator('..');
|
||||
this.summarySection = this.resultsSection.locator('label').filter({ hasText: 'summary' }).locator('..');
|
||||
this.explanationTextarea = this.resultsSection.locator('textarea');
|
||||
this.resetButton = this.resultsSection.locator('button').filter({ hasText: 'reset form' });
|
||||
}
|
||||
|
||||
async goto() {
|
||||
await this.page.goto('/');
|
||||
}
|
||||
|
||||
async fillPlayerInfo(playerName: string, currentPoints: number = 0) {
|
||||
await this.playerNameInput.fill(playerName);
|
||||
await this.currentPointsInput.fill(currentPoints.toString());
|
||||
}
|
||||
|
||||
async selectCrimeCategory(category: 'all' | 'item' | 'block' | 'hacking' | 'communication') {
|
||||
await this.crimeCategoryButtons[category].click();
|
||||
}
|
||||
|
||||
async selectSpecificOffense(offenseId: string) {
|
||||
// Click the select trigger to open dropdown
|
||||
await this.specificOffenseSelectTrigger.click();
|
||||
|
||||
// Find the crime name from the CRIMES array (we need to import this or map it)
|
||||
const crimeName = this.getCrimeNameFromId(offenseId);
|
||||
|
||||
// Click the option with the matching text (exact match)
|
||||
await this.page.locator('[data-slot="select-content"]').locator('text=' + crimeName).first().click();
|
||||
}
|
||||
|
||||
private getCrimeNameFromId(crimeId: string): string {
|
||||
// This is a simplified mapping - in production, you'd want to import the CRIMES array
|
||||
const crimeMap: { [key: string]: string } = {
|
||||
'inappropriate_item_names': 'Inappropriate Item Names',
|
||||
'inappropriate_book_contents': 'Inappropriate Book Contents',
|
||||
'theft': 'Theft',
|
||||
'unconsensual_killing': 'Unconsensual Killing',
|
||||
'illegal_item_use': 'Using Illegal Item',
|
||||
'vandalism': 'Vandalism',
|
||||
'grief': 'Grief',
|
||||
'theft_grief': 'Theft-Grief',
|
||||
'vandalism_infrastructure': 'Vandalism of Public Infrastructure',
|
||||
'trespassing': 'Trespassing',
|
||||
'trespassing_staff': 'Trespassing on Staff/SPP Land',
|
||||
'x_raying': 'X-Raying',
|
||||
'hacking_client': 'Use of Hacking Client',
|
||||
'lagging_server': 'Deliberately Lagging Server',
|
||||
'worldedit_misuse': 'Misuse of Worldedit',
|
||||
'exploit_abuse': 'Abuse of Exploits',
|
||||
'abusive_chat': 'Abusive Chat',
|
||||
'inciting_verbal_conflict': 'Inciting Verbal Conflict',
|
||||
'abusive_vc': 'Abusive VC Language',
|
||||
'lying_to_staff': 'Lying to Staff Member',
|
||||
'manipulation': 'Manipulation',
|
||||
'grand_manipulation': 'Grand Manipulation',
|
||||
'slander': 'Slander (Against SPP Only)',
|
||||
'violation_nca': 'Violation of NCA',
|
||||
};
|
||||
|
||||
return crimeMap[crimeId] || crimeId;
|
||||
}
|
||||
|
||||
async fillSpecialItems(items: { elytra?: number; netherStar?: number; beacon?: number; netheriteBlock?: number; diamondBlock?: number }) {
|
||||
if (items.elytra !== undefined) await this.specialItems.elytra.fill(items.elytra.toString());
|
||||
if (items.netherStar !== undefined) await this.specialItems.netherStar.fill(items.netherStar.toString());
|
||||
if (items.beacon !== undefined) await this.specialItems.beacon.fill(items.beacon.toString());
|
||||
if (items.netheriteBlock !== undefined) await this.specialItems.netheriteBlock.fill(items.netheriteBlock.toString());
|
||||
if (items.diamondBlock !== undefined) await this.specialItems.diamondBlock.fill(items.diamondBlock.toString());
|
||||
}
|
||||
|
||||
async addAdditionalItem(type: string, quantity: number) {
|
||||
// Click "add item" button
|
||||
const addButton = this.additionalItemInputs.locator('button').filter({ hasText: 'add item' });
|
||||
await addButton.click();
|
||||
|
||||
// Fill in the last added item row
|
||||
const itemRows = this.additionalItemInputs.locator('div.flex.items-center.gap-2');
|
||||
const lastRow = itemRows.last();
|
||||
const inputs = lastRow.locator('input');
|
||||
await inputs.nth(0).fill(type);
|
||||
await inputs.nth(1).fill(quantity.toString());
|
||||
}
|
||||
|
||||
async fillBlockCount(count: number) {
|
||||
await this.blockCountInput.fill(count.toString());
|
||||
}
|
||||
|
||||
async fillEntityCount(count: number) {
|
||||
await this.entityCountInput.fill(count.toString());
|
||||
}
|
||||
|
||||
async setSPP(isSPP: boolean) {
|
||||
if (isSPP) {
|
||||
await this.sppCheckbox.check();
|
||||
} else {
|
||||
await this.sppCheckbox.uncheck();
|
||||
}
|
||||
}
|
||||
|
||||
async calculatePunishment() {
|
||||
await this.calculateButton.click();
|
||||
}
|
||||
|
||||
async resetForm() {
|
||||
await this.resetButton.click();
|
||||
}
|
||||
|
||||
async waitForResults() {
|
||||
await this.resultsSection.waitFor({ state: 'visible' });
|
||||
}
|
||||
|
||||
async getResults() {
|
||||
const commands = await this.commandsList.locator('code').allTextContents();
|
||||
const summary = await this.summarySection.locator('div.text-sm.space-y-1').textContent();
|
||||
const explanation = await this.explanationTextarea.inputValue();
|
||||
|
||||
return {
|
||||
commands,
|
||||
summary,
|
||||
explanation,
|
||||
};
|
||||
}
|
||||
|
||||
async getSummaryValues() {
|
||||
const summaryDiv = this.summarySection.locator('div.text-sm.space-y-1');
|
||||
const lines = await summaryDiv.locator('div').allTextContents();
|
||||
|
||||
const values: { [key: string]: string } = {};
|
||||
for (const line of lines) {
|
||||
const [key, value] = line.split(': ');
|
||||
values[key] = value;
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user