ui improvements
This commit is contained in:
220
tests/debug.spec.ts
Normal file
220
tests/debug.spec.ts
Normal file
@@ -0,0 +1,220 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { DP2FormPage } from './utils/page-objects';
|
||||
import { TestDataFactory } from './utils/test-data';
|
||||
|
||||
/**
|
||||
* Debug test to help identify issues with the DP2 calculator
|
||||
* This test captures screenshots and detailed logs for debugging
|
||||
*/
|
||||
test.describe('DP2 Calculator - Debug Tests', () => {
|
||||
let formPage: DP2FormPage;
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
formPage = new DP2FormPage(page);
|
||||
await formPage.goto();
|
||||
await page.screenshot({ path: `debug-screenshots/initial-load.png` });
|
||||
});
|
||||
|
||||
test('debug theft calculation - step by step', async ({ page }) => {
|
||||
console.log('=== Starting Theft Debug Test ===');
|
||||
|
||||
// Fill basic info
|
||||
await formPage.fillPlayerInfo('DebugPlayer', 0);
|
||||
await page.screenshot({ path: `debug-screenshots/01-basic-info-filled.png` });
|
||||
|
||||
// Select theft
|
||||
await formPage.selectCrimeCategory('item');
|
||||
await formPage.selectSpecificOffense('theft');
|
||||
await page.screenshot({ path: `debug-screenshots/02-theft-selected.png` });
|
||||
|
||||
// Check if special items section is visible
|
||||
const specialItemsVisible = await formPage.specialItems.elytra.isVisible();
|
||||
console.log('Special items section visible:', specialItemsVisible);
|
||||
|
||||
// Fill special items
|
||||
await formPage.fillSpecialItems({
|
||||
elytra: 1,
|
||||
netherStar: 0,
|
||||
beacon: 0,
|
||||
netheriteBlock: 0,
|
||||
diamondBlock: 0
|
||||
});
|
||||
await page.screenshot({ path: `debug-screenshots/03-special-items-filled.png` });
|
||||
|
||||
// Add additional items
|
||||
await formPage.addAdditionalItem('diamond', 10);
|
||||
await page.screenshot({ path: `debug-screenshots/04-additional-items-added.png` });
|
||||
|
||||
// Calculate
|
||||
await formPage.calculatePunishment();
|
||||
await page.screenshot({ path: `debug-screenshots/05-calculate-clicked.png` });
|
||||
|
||||
// Wait for results and capture them
|
||||
try {
|
||||
await formPage.waitForResults();
|
||||
await page.screenshot({ path: `debug-screenshots/06-results-shown.png` });
|
||||
|
||||
const results = await formPage.getResults();
|
||||
const summary = await formPage.getSummaryValues();
|
||||
|
||||
console.log('=== RESULTS ===');
|
||||
console.log('Commands:', results.commands);
|
||||
console.log('Summary:', summary);
|
||||
console.log('Explanation:', results.explanation);
|
||||
|
||||
// Save results to file for analysis
|
||||
await page.evaluate((results) => {
|
||||
console.log('Detailed Results:', results);
|
||||
}, { commands: results.commands, summary, explanation: results.explanation });
|
||||
|
||||
} catch (error) {
|
||||
console.error('Failed to get results:', error);
|
||||
await page.screenshot({ path: `debug-screenshots/06-no-results-error.png` });
|
||||
|
||||
// Check if there are any console errors
|
||||
const consoleMessages: string[] = [];
|
||||
page.on('console', msg => consoleMessages.push(msg.text()));
|
||||
await page.waitForTimeout(1000);
|
||||
console.log('Console messages:', consoleMessages);
|
||||
}
|
||||
});
|
||||
|
||||
test('debug grief calculation - step by step', async ({ page }) => {
|
||||
console.log('=== Starting Grief Debug Test ===');
|
||||
|
||||
// Fill basic info
|
||||
await formPage.fillPlayerInfo('DebugPlayer2', 0);
|
||||
await page.screenshot({ path: `debug-screenshots/grief-01-basic-info.png` });
|
||||
|
||||
// Select grief
|
||||
await formPage.selectCrimeCategory('block');
|
||||
await formPage.selectSpecificOffense('grief');
|
||||
await page.screenshot({ path: `debug-screenshots/grief-02-grief-selected.png` });
|
||||
|
||||
// Fill block count
|
||||
await formPage.fillBlockCount(500);
|
||||
await page.screenshot({ path: `debug-screenshots/grief-03-block-count-filled.png` });
|
||||
|
||||
// Calculate
|
||||
await formPage.calculatePunishment();
|
||||
await page.screenshot({ path: `debug-screenshots/grief-04-calculate-clicked.png` });
|
||||
|
||||
// Wait for results
|
||||
try {
|
||||
await formPage.waitForResults();
|
||||
await page.screenshot({ path: `debug-screenshots/grief-05-results-shown.png` });
|
||||
|
||||
const results = await formPage.getResults();
|
||||
const summary = await formPage.getSummaryValues();
|
||||
|
||||
console.log('=== GRIEF RESULTS ===');
|
||||
console.log('Commands:', results.commands);
|
||||
console.log('Summary:', summary);
|
||||
console.log('Explanation:', results.explanation);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Failed to get grief results:', error);
|
||||
await page.screenshot({ path: `debug-screenshots/grief-05-no-results-error.png` });
|
||||
}
|
||||
});
|
||||
|
||||
test('debug all crime types - quick check', async ({ page }) => {
|
||||
const scenarios = TestDataFactory.getAllScenarios().slice(0, 5); // Just test first 5
|
||||
|
||||
for (let i = 0; i < scenarios.length; i++) {
|
||||
const scenario = scenarios[i];
|
||||
console.log(`\n=== Testing ${scenario.offense.crimeId} ===`);
|
||||
|
||||
// Reset form
|
||||
await formPage.resetForm();
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
// Fill player info
|
||||
await formPage.fillPlayerInfo(scenario.player.name, scenario.player.currentPoints);
|
||||
|
||||
// Select category and crime
|
||||
const category = getCrimeCategory(scenario.offense.crimeId);
|
||||
await formPage.selectCrimeCategory(category);
|
||||
await formPage.selectSpecificOffense(scenario.offense.crimeId);
|
||||
|
||||
// Fill specific details
|
||||
if (scenario.offense.specialItems) {
|
||||
await formPage.fillSpecialItems(scenario.offense.specialItems);
|
||||
}
|
||||
if (scenario.offense.itemDetails) {
|
||||
for (const item of scenario.offense.itemDetails) {
|
||||
await formPage.addAdditionalItem(item.type, item.quantity);
|
||||
}
|
||||
}
|
||||
if (scenario.offense.blockCount !== undefined) {
|
||||
await formPage.fillBlockCount(scenario.offense.blockCount);
|
||||
}
|
||||
if (scenario.offense.entityCount !== undefined) {
|
||||
await formPage.fillEntityCount(scenario.offense.entityCount);
|
||||
}
|
||||
if (scenario.offense.isSPP !== undefined) {
|
||||
await formPage.setSPP(scenario.offense.isSPP);
|
||||
}
|
||||
|
||||
// Calculate
|
||||
await formPage.calculatePunishment();
|
||||
|
||||
// Check if results appear
|
||||
try {
|
||||
await formPage.waitForResults();
|
||||
console.log(`✅ ${scenario.offense.crimeId} - Results generated`);
|
||||
} catch (error) {
|
||||
console.log(`❌ ${scenario.offense.crimeId} - No results generated`);
|
||||
await page.screenshot({ path: `debug-screenshots/error-${scenario.offense.crimeId}.png` });
|
||||
}
|
||||
|
||||
await page.waitForTimeout(1000); // Brief pause between tests
|
||||
}
|
||||
});
|
||||
|
||||
test('capture form HTML for debugging', async ({ page }) => {
|
||||
await formPage.fillPlayerInfo('HTMLDebug', 0);
|
||||
await formPage.selectCrimeCategory('item');
|
||||
await formPage.selectSpecificOffense('theft');
|
||||
|
||||
// Get the form HTML
|
||||
const formHtml = await page.locator('form').innerHTML();
|
||||
console.log('Form HTML:', formHtml);
|
||||
|
||||
// Also check for any error messages in the DOM
|
||||
const errorMessages = await page.locator('.text-red-500').allTextContents();
|
||||
console.log('Error messages:', errorMessages);
|
||||
});
|
||||
});
|
||||
|
||||
// Helper function to determine crime category
|
||||
function getCrimeCategory(crimeId: string): 'all' | 'item' | 'block' | 'hacking' | 'communication' {
|
||||
const categoryMap: { [key: string]: 'item' | 'block' | 'hacking' | 'communication' } = {
|
||||
'theft': 'item',
|
||||
'unconsensual_killing': 'item',
|
||||
'illegal_item_use': 'item',
|
||||
'inappropriate_item_names': 'item',
|
||||
'inappropriate_book_contents': 'item',
|
||||
'vandalism': 'block',
|
||||
'grief': 'block',
|
||||
'theft_grief': 'block',
|
||||
'vandalism_infrastructure': 'block',
|
||||
'trespassing': 'block',
|
||||
'trespassing_staff': 'block',
|
||||
'x_raying': 'hacking',
|
||||
'hacking_client': 'hacking',
|
||||
'lagging_server': 'hacking',
|
||||
'worldedit_misuse': 'hacking',
|
||||
'exploit_abuse': 'hacking',
|
||||
'abusive_chat': 'communication',
|
||||
'inciting_verbal_conflict': 'communication',
|
||||
'abusive_vc': 'communication',
|
||||
'lying_to_staff': 'communication',
|
||||
'manipulation': 'communication',
|
||||
'grand_manipulation': 'communication',
|
||||
'slander': 'communication',
|
||||
'violation_nca': 'communication',
|
||||
};
|
||||
|
||||
return categoryMap[crimeId] || 'all';
|
||||
}
|
||||
219
tests/dp2-form.spec.ts
Normal file
219
tests/dp2-form.spec.ts
Normal file
@@ -0,0 +1,219 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { DP2FormPage } from './utils/page-objects';
|
||||
import { TestDataFactory, TestScenario } from './utils/test-data';
|
||||
|
||||
test.describe('DP2 Form - Basic Functionality', () => {
|
||||
let formPage: DP2FormPage;
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
formPage = new DP2FormPage(page);
|
||||
await formPage.goto();
|
||||
});
|
||||
|
||||
test('should load the form correctly', async () => {
|
||||
await expect(formPage.playerNameInput).toBeVisible();
|
||||
await expect(formPage.currentPointsInput).toBeVisible();
|
||||
await expect(formPage.calculateButton).toBeVisible();
|
||||
});
|
||||
|
||||
test('should show crime category buttons', async () => {
|
||||
for (const [key, button] of Object.entries(formPage.crimeCategoryButtons)) {
|
||||
await expect(button).toBeVisible();
|
||||
}
|
||||
});
|
||||
|
||||
test('should filter crimes by category', async ({ page }) => {
|
||||
// Test item offenses
|
||||
await formPage.selectCrimeCategory('item');
|
||||
const itemOptions = await formPage.specificOffenseSelect.locator('option').allTextContents();
|
||||
expect(itemOptions.length).toBeGreaterThan(0);
|
||||
expect(itemOptions.some(option => option.includes('Theft') || option.includes('Killing'))).toBe(true);
|
||||
|
||||
// Test block offenses
|
||||
await formPage.selectCrimeCategory('block');
|
||||
const blockOptions = await formPage.specificOffenseSelect.locator('option').allTextContents();
|
||||
expect(blockOptions.length).toBeGreaterThan(0);
|
||||
expect(blockOptions.some(option => option.includes('Grief') || option.includes('Vandalism'))).toBe(true);
|
||||
|
||||
// Test hacking offenses
|
||||
await formPage.selectCrimeCategory('hacking');
|
||||
const hackingOptions = await formPage.specificOffenseSelect.locator('option').allTextContents();
|
||||
expect(hackingOptions.length).toBeGreaterThan(0);
|
||||
expect(hackingOptions.some(option => option.includes('X-Ray') || option.includes('Hacking'))).toBe(true);
|
||||
|
||||
// Test communication offenses
|
||||
await formPage.selectCrimeCategory('communication');
|
||||
const commOptions = await formPage.specificOffenseSelect.locator('option').allTextContents();
|
||||
expect(commOptions.length).toBeGreaterThan(0);
|
||||
expect(commOptions.some(option => option.includes('Abusive') || option.includes('Manipulation'))).toBe(true);
|
||||
});
|
||||
|
||||
test('should show offense details section when crime is selected', async () => {
|
||||
await formPage.selectCrimeCategory('item');
|
||||
await formPage.selectSpecificOffense('theft');
|
||||
|
||||
await expect(formPage.offenseDetailsSection).toBeVisible();
|
||||
});
|
||||
|
||||
test('should show special items section for theft', async () => {
|
||||
await formPage.selectCrimeCategory('item');
|
||||
await formPage.selectSpecificOffense('theft');
|
||||
|
||||
// Check that special item inputs are visible
|
||||
for (const [key, input] of Object.entries(formPage.specialItems)) {
|
||||
await expect(input).toBeVisible();
|
||||
}
|
||||
});
|
||||
|
||||
test('should show block count input for grief', async () => {
|
||||
await formPage.selectCrimeCategory('block');
|
||||
await formPage.selectSpecificOffense('grief');
|
||||
|
||||
await expect(formPage.blockCountInput).toBeVisible();
|
||||
});
|
||||
|
||||
test('should show SPP checkbox for applicable crimes', async () => {
|
||||
await formPage.selectCrimeCategory('block');
|
||||
await formPage.selectSpecificOffense('trespassing_staff');
|
||||
|
||||
await expect(formPage.sppCheckbox).toBeVisible();
|
||||
});
|
||||
|
||||
test('should allow adding additional items for theft', async () => {
|
||||
await formPage.selectCrimeCategory('item');
|
||||
await formPage.selectSpecificOffense('theft');
|
||||
|
||||
await formPage.addAdditionalItem('diamond_sword', 3);
|
||||
|
||||
// Verify the item was added
|
||||
const itemRows = formPage.additionalItemInputs.locator('div.flex.items-center.gap-2');
|
||||
await expect(itemRows).toHaveCount(1);
|
||||
|
||||
const inputs = itemRows.locator('input');
|
||||
await expect(inputs.nth(0)).toHaveValue('diamond_sword');
|
||||
await expect(inputs.nth(1)).toHaveValue('3');
|
||||
});
|
||||
|
||||
test('should validate required fields', async () => {
|
||||
await formPage.calculateButton.click();
|
||||
|
||||
// Should not show results without required fields
|
||||
await expect(formPage.resultsSection).not.toBeVisible();
|
||||
});
|
||||
|
||||
test('should reset form correctly', async () => {
|
||||
await formPage.fillPlayerInfo('TestPlayer', 10);
|
||||
await formPage.selectCrimeCategory('item');
|
||||
await formPage.selectSpecificOffense('theft');
|
||||
await formPage.calculatePunishment();
|
||||
await formPage.waitForResults();
|
||||
|
||||
await formPage.resetForm();
|
||||
|
||||
// Form should be cleared
|
||||
await expect(formPage.playerNameInput).toHaveValue('');
|
||||
await expect(formPage.currentPointsInput).toHaveValue('0');
|
||||
await expect(formPage.resultsSection).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('DP2 Form - Calculation Tests', () => {
|
||||
let formPage: DP2FormPage;
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
formPage = new DP2FormPage(page);
|
||||
await formPage.goto();
|
||||
});
|
||||
|
||||
// Test all scenarios from our test data factory
|
||||
const scenarios = TestDataFactory.getAllScenarios();
|
||||
|
||||
for (const scenario of scenarios) {
|
||||
test(`should calculate ${scenario.offense.crimeId} correctly for ${scenario.player.name}`, async () => {
|
||||
// Skip empty form validation test
|
||||
if (scenario.player.name === '' && scenario.offense.crimeId === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Fill player info
|
||||
await formPage.fillPlayerInfo(scenario.player.name, scenario.player.currentPoints);
|
||||
|
||||
// Determine category and select crime
|
||||
const crimeCategory = getCrimeCategory(scenario.offense.crimeId);
|
||||
await formPage.selectCrimeCategory(crimeCategory);
|
||||
await formPage.selectSpecificOffense(scenario.offense.crimeId);
|
||||
|
||||
// Fill offense-specific details
|
||||
if (scenario.offense.specialItems) {
|
||||
await formPage.fillSpecialItems(scenario.offense.specialItems);
|
||||
}
|
||||
|
||||
if (scenario.offense.itemDetails) {
|
||||
for (const item of scenario.offense.itemDetails) {
|
||||
await formPage.addAdditionalItem(item.type, item.quantity);
|
||||
}
|
||||
}
|
||||
|
||||
if (scenario.offense.blockCount !== undefined) {
|
||||
await formPage.fillBlockCount(scenario.offense.blockCount);
|
||||
}
|
||||
|
||||
if (scenario.offense.entityCount !== undefined) {
|
||||
await formPage.fillEntityCount(scenario.offense.entityCount);
|
||||
}
|
||||
|
||||
if (scenario.offense.isSPP !== undefined) {
|
||||
await formPage.setSPP(scenario.offense.isSPP);
|
||||
}
|
||||
|
||||
// Calculate and wait for results
|
||||
await formPage.calculatePunishment();
|
||||
await formPage.waitForResults();
|
||||
|
||||
// Verify results
|
||||
if (scenario.expected.hasCommands) {
|
||||
const summary = await formPage.getSummaryValues();
|
||||
|
||||
// Note: These expectations may need adjustment based on actual implementation
|
||||
// For now, we just verify that results are generated
|
||||
expect(summary).toBeDefined();
|
||||
expect(summary.crime).toBeDefined();
|
||||
expect(summary.totalPoints).toBeDefined();
|
||||
expect(summary.punishment).toBeDefined();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Helper function to determine crime category
|
||||
function getCrimeCategory(crimeId: string): 'all' | 'item' | 'block' | 'hacking' | 'communication' {
|
||||
// This is a simplified mapping - in real implementation, you'd import CRIMES from dp2-rules
|
||||
const categoryMap: { [key: string]: 'item' | 'block' | 'hacking' | 'communication' } = {
|
||||
'theft': 'item',
|
||||
'unconsensual_killing': 'item',
|
||||
'illegal_item_use': 'item',
|
||||
'inappropriate_item_names': 'item',
|
||||
'inappropriate_book_contents': 'item',
|
||||
'vandalism': 'block',
|
||||
'grief': 'block',
|
||||
'theft_grief': 'block',
|
||||
'vandalism_infrastructure': 'block',
|
||||
'trespassing': 'block',
|
||||
'trespassing_staff': 'block',
|
||||
'x_raying': 'hacking',
|
||||
'hacking_client': 'hacking',
|
||||
'lagging_server': 'hacking',
|
||||
'worldedit_misuse': 'hacking',
|
||||
'exploit_abuse': 'hacking',
|
||||
'abusive_chat': 'communication',
|
||||
'inciting_verbal_conflict': 'communication',
|
||||
'abusive_vc': 'communication',
|
||||
'lying_to_staff': 'communication',
|
||||
'manipulation': 'communication',
|
||||
'grand_manipulation': 'communication',
|
||||
'slander': 'communication',
|
||||
'violation_nca': 'communication',
|
||||
};
|
||||
|
||||
return categoryMap[crimeId] || 'all';
|
||||
}
|
||||
58
tests/inspect-select.spec.ts
Normal file
58
tests/inspect-select.spec.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test.describe('Inspect Select Component', () => {
|
||||
test('should inspect the select dropdown behavior', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
|
||||
// Wait for page to load
|
||||
await page.waitForLoadState('networkidle');
|
||||
|
||||
// Click the select trigger
|
||||
const selectTrigger = page.locator('button').filter({ hasText: 'select an offense' });
|
||||
await selectTrigger.click();
|
||||
|
||||
// Wait a bit for dropdown to appear
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
// Take screenshot of the opened dropdown
|
||||
await page.screenshot({ path: 'debug-screenshots/select-opened.png', fullPage: true });
|
||||
|
||||
// Get all elements in the viewport that contain crime names
|
||||
const allText = await page.locator('*').filter({ hasText: /theft|grief|hacking/i }).allTextContents();
|
||||
console.log('Elements with crime text:', allText);
|
||||
|
||||
// Try different locators for the dropdown content
|
||||
const possibleLocators = [
|
||||
'[data-radix-select-content]',
|
||||
'[role="listbox"]',
|
||||
'.select-content',
|
||||
'[data-slot="select-content"]'
|
||||
];
|
||||
|
||||
for (const locator of possibleLocators) {
|
||||
try {
|
||||
const count = await page.locator(locator).count();
|
||||
if (count > 0) {
|
||||
console.log(`Found ${count} elements with locator: ${locator}`);
|
||||
const text = await page.locator(locator).textContent();
|
||||
console.log(`Content: ${text?.substring(0, 200)}...`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(`Locator ${locator} failed:`, error instanceof Error ? error.message : String(error));
|
||||
}
|
||||
}
|
||||
|
||||
// Get the full page HTML to inspect
|
||||
const bodyHtml = await page.locator('body').innerHTML();
|
||||
console.log('Body HTML length:', bodyHtml.length);
|
||||
|
||||
// Look for any elements that might contain the dropdown
|
||||
const portalElements = await page.locator('[data-radix-portal]').count();
|
||||
console.log('Radix portal elements:', portalElements);
|
||||
|
||||
if (portalElements > 0) {
|
||||
const portalContent = await page.locator('[data-radix-portal]').textContent();
|
||||
console.log('Portal content preview:', portalContent?.substring(0, 300));
|
||||
}
|
||||
});
|
||||
});
|
||||
83
tests/minimal-submit.spec.ts
Normal file
83
tests/minimal-submit.spec.ts
Normal file
@@ -0,0 +1,83 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test.describe('Minimal Form Submission Test', () => {
|
||||
test('should submit minimal valid form', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
|
||||
// Wait for page to load
|
||||
await page.waitForLoadState('networkidle');
|
||||
|
||||
// Fill required fields with minimal valid data
|
||||
await page.fill('input[id="playerName"]', 'TestPlayer');
|
||||
await page.fill('input[id="currentPoints"]', '0');
|
||||
|
||||
// Select a simple crime that doesn't require additional inputs
|
||||
// Click "all" category first to show all crimes
|
||||
await page.locator('button').filter({ hasText: 'all' }).click();
|
||||
|
||||
// Wait for select trigger to be available
|
||||
await page.waitForSelector('button:has-text("select an offense")');
|
||||
|
||||
// Click the select trigger
|
||||
await page.locator('button').filter({ hasText: 'select an offense' }).click();
|
||||
|
||||
// Wait for dropdown and select "Abusive Chat" (simple crime)
|
||||
await page.locator('[data-slot="select-content"]').locator('text=Abusive Chat').click();
|
||||
|
||||
// Take screenshot before submit
|
||||
await page.screenshot({ path: 'debug-screenshots/minimal-before-submit.png', fullPage: true });
|
||||
|
||||
// Check if button is enabled before submitting
|
||||
const button = page.locator('button[type="submit"]');
|
||||
const isEnabled = await button.isEnabled();
|
||||
console.log('Submit button is enabled:', isEnabled);
|
||||
|
||||
// Check form validity by looking at the DOM
|
||||
const hasErrors = await page.locator('.text-red-500').count() > 0;
|
||||
console.log('Form has errors:', hasErrors);
|
||||
|
||||
// Submit the form
|
||||
await button.click();
|
||||
|
||||
// Wait for processing
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
// Take screenshot after submit
|
||||
await page.screenshot({ path: 'debug-screenshots/minimal-after-submit.png', fullPage: true });
|
||||
|
||||
// Listen for console messages after submit
|
||||
const consoleMessages: string[] = [];
|
||||
page.on('console', msg => {
|
||||
consoleMessages.push(msg.text());
|
||||
});
|
||||
|
||||
// Wait a bit more for any async operations
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
console.log('Console messages after submit:', consoleMessages);
|
||||
|
||||
// Check for results
|
||||
const resultsVisible = await page.locator('h3').filter({ hasText: 'results' }).count() > 0;
|
||||
console.log('Results visible:', resultsVisible);
|
||||
|
||||
if (resultsVisible) {
|
||||
console.log('SUCCESS: Form submission worked!');
|
||||
} else {
|
||||
console.log('FAILURE: Form submission did not work');
|
||||
|
||||
// Check for any form errors
|
||||
const formErrors = await page.locator('.text-red-500').allTextContents();
|
||||
console.log('Form errors:', formErrors);
|
||||
|
||||
// Check form data
|
||||
const playerName = await page.inputValue('input[id="playerName"]');
|
||||
const currentPoints = await page.inputValue('input[id="currentPoints"]');
|
||||
console.log('Form data - playerName:', playerName, 'currentPoints:', currentPoints);
|
||||
|
||||
// Check if crimeId is set
|
||||
const crimeTrigger = page.locator('button').filter({ hasText: 'select an offense' });
|
||||
const crimeTriggerText = await crimeTrigger.textContent();
|
||||
console.log('Crime trigger text:', crimeTriggerText);
|
||||
}
|
||||
});
|
||||
});
|
||||
70
tests/simple-submit.spec.ts
Normal file
70
tests/simple-submit.spec.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { DP2FormPage } from './utils/page-objects';
|
||||
|
||||
test.describe('Simple Form Submission Test', () => {
|
||||
let formPage: DP2FormPage;
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
formPage = new DP2FormPage(page);
|
||||
await formPage.goto();
|
||||
});
|
||||
|
||||
test('should submit theft form and check for any errors', async ({ page }) => {
|
||||
// Fill basic info
|
||||
await formPage.fillPlayerInfo('TestPlayer', 0);
|
||||
|
||||
// Select item category
|
||||
await formPage.selectCrimeCategory('item');
|
||||
|
||||
// Select theft
|
||||
await formPage.selectSpecificOffense('theft');
|
||||
|
||||
// Fill special items
|
||||
await formPage.fillSpecialItems({
|
||||
elytra: 1,
|
||||
netherStar: 0,
|
||||
beacon: 0,
|
||||
netheriteBlock: 0,
|
||||
diamondBlock: 0
|
||||
});
|
||||
|
||||
// Add additional items
|
||||
await formPage.addAdditionalItem('diamond', 10);
|
||||
|
||||
// Take screenshot before submit
|
||||
await page.screenshot({ path: 'debug-screenshots/before-submit.png', fullPage: true });
|
||||
|
||||
// Submit the form
|
||||
await formPage.calculateButton.click();
|
||||
|
||||
// Wait a bit for any processing
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
// Take screenshot after submit
|
||||
await page.screenshot({ path: 'debug-screenshots/after-submit.png', fullPage: true });
|
||||
|
||||
// Check for any error messages
|
||||
const errorMessages = await page.locator('.text-red-500').allTextContents();
|
||||
console.log('Error messages after submit:', errorMessages);
|
||||
|
||||
// Check console for any errors
|
||||
const consoleMessages: string[] = [];
|
||||
page.on('console', msg => {
|
||||
consoleMessages.push(msg.text());
|
||||
});
|
||||
|
||||
// Wait a bit more
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
console.log('Console messages:', consoleMessages);
|
||||
|
||||
// Check if results section exists at all
|
||||
const resultsExists = await formPage.resultsSection.count() > 0;
|
||||
console.log('Results section exists:', resultsExists);
|
||||
|
||||
if (resultsExists) {
|
||||
const isVisible = await formPage.resultsSection.isVisible();
|
||||
console.log('Results section is visible:', isVisible);
|
||||
}
|
||||
});
|
||||
});
|
||||
66
tests/simple-test.spec.ts
Normal file
66
tests/simple-test.spec.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test.describe('Simple Page Inspection', () => {
|
||||
test('should load page and inspect DOM', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
|
||||
// Wait for page to load
|
||||
await page.waitForLoadState('networkidle');
|
||||
|
||||
// Take screenshot
|
||||
await page.screenshot({ path: 'debug-screenshots/page-loaded.png', fullPage: true });
|
||||
|
||||
// Get page title
|
||||
const title = await page.title();
|
||||
console.log('Page title:', title);
|
||||
|
||||
// Get all headings
|
||||
const headings = await page.locator('h1, h2, h3, h4').allTextContents();
|
||||
console.log('Headings:', headings);
|
||||
|
||||
// Get all form elements
|
||||
const formElements = await page.locator('form input, form select, form button').allTextContents();
|
||||
console.log('Form elements text:', formElements);
|
||||
|
||||
// Get the form HTML
|
||||
const formHtml = await page.locator('form').innerHTML();
|
||||
console.log('Form HTML length:', formHtml.length);
|
||||
|
||||
// Save form HTML to file for inspection
|
||||
await page.evaluate((html) => {
|
||||
const blob = new Blob([html], { type: 'text/html' });
|
||||
const url = URL.createObjectURL(blob);
|
||||
console.log('Form HTML saved to blob:', url);
|
||||
return html.substring(0, 1000) + '...';
|
||||
}, formHtml);
|
||||
|
||||
// Check for specific elements
|
||||
const playerNameInput = page.locator('input[id="playerName"]');
|
||||
const exists = await playerNameInput.count() > 0;
|
||||
console.log('Player name input exists:', exists);
|
||||
|
||||
if (exists) {
|
||||
console.log('Player name input is visible:', await playerNameInput.isVisible());
|
||||
}
|
||||
|
||||
// Get all input IDs
|
||||
const inputIds = await page.locator('input[id]').evaluateAll(inputs =>
|
||||
inputs.map(input => input.id)
|
||||
);
|
||||
console.log('Input IDs:', inputIds);
|
||||
|
||||
// Get all select IDs
|
||||
const selectIds = await page.locator('select[id]').evaluateAll(selects =>
|
||||
selects.map(select => select.id)
|
||||
);
|
||||
console.log('Select IDs:', selectIds);
|
||||
|
||||
// Get all button texts
|
||||
const buttonTexts = await page.locator('button').allTextContents();
|
||||
console.log('Button texts:', buttonTexts);
|
||||
|
||||
// Look for crime category buttons
|
||||
const crimeButtons = await page.locator('button').filter({ hasText: /offenses/ }).allTextContents();
|
||||
console.log('Crime category buttons:', crimeButtons);
|
||||
});
|
||||
});
|
||||
49
tests/test-select-fix.spec.ts
Normal file
49
tests/test-select-fix.spec.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { DP2FormPage } from './utils/page-objects';
|
||||
|
||||
test.describe('Test Select Fix', () => {
|
||||
let formPage: DP2FormPage;
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
formPage = new DP2FormPage(page);
|
||||
await formPage.goto();
|
||||
});
|
||||
|
||||
test('should select theft correctly', async ({ page }) => {
|
||||
// Fill basic info
|
||||
await formPage.fillPlayerInfo('TestPlayer', 0);
|
||||
|
||||
// Select item category
|
||||
await formPage.selectCrimeCategory('item');
|
||||
|
||||
// Select theft
|
||||
await formPage.selectSpecificOffense('theft');
|
||||
|
||||
// Check if offense details section appears
|
||||
await expect(formPage.offenseDetailsSection).toBeVisible();
|
||||
|
||||
// Take screenshot
|
||||
await page.screenshot({ path: 'debug-screenshots/theft-selected-fixed.png', fullPage: true });
|
||||
|
||||
console.log('Theft selection successful!');
|
||||
});
|
||||
|
||||
test('should select grief correctly', async ({ page }) => {
|
||||
// Fill basic info
|
||||
await formPage.fillPlayerInfo('TestPlayer2', 0);
|
||||
|
||||
// Select block category
|
||||
await formPage.selectCrimeCategory('block');
|
||||
|
||||
// Select grief
|
||||
await formPage.selectSpecificOffense('grief');
|
||||
|
||||
// Check if block count input appears
|
||||
await expect(formPage.blockCountInput).toBeVisible();
|
||||
|
||||
// Take screenshot
|
||||
await page.screenshot({ path: 'debug-screenshots/grief-selected-fixed.png', fullPage: true });
|
||||
|
||||
console.log('Grief selection successful!');
|
||||
});
|
||||
});
|
||||
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;
|
||||
}
|
||||
}
|
||||
332
tests/utils/test-data.ts
Normal file
332
tests/utils/test-data.ts
Normal file
@@ -0,0 +1,332 @@
|
||||
import { CRIMES } from '@/lib/dp2-rules';
|
||||
|
||||
// Test data interfaces
|
||||
export interface TestPlayer {
|
||||
name: string;
|
||||
currentPoints: number;
|
||||
}
|
||||
|
||||
export interface TestOffense {
|
||||
crimeId: string;
|
||||
itemDetails?: Array<{ type: string; quantity: number }>;
|
||||
blockCount?: number;
|
||||
entityCount?: number;
|
||||
isSPP?: boolean;
|
||||
specialItems?: {
|
||||
elytra: number;
|
||||
netherStar: number;
|
||||
beacon: number;
|
||||
netheriteBlock: number;
|
||||
diamondBlock: number;
|
||||
};
|
||||
}
|
||||
|
||||
export interface TestScenario {
|
||||
player: TestPlayer;
|
||||
offense: TestOffense;
|
||||
expected: {
|
||||
basePoints: number;
|
||||
totalPoints: number;
|
||||
punishmentLevel: string;
|
||||
hasCommands: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
// Test data factories
|
||||
export class TestDataFactory {
|
||||
// Item Offenses Test Scenarios
|
||||
static getItemOffenseScenarios(): TestScenario[] {
|
||||
return [
|
||||
// Theft - Minor (< 50 item points)
|
||||
{
|
||||
player: { name: 'TestPlayer1', currentPoints: 0 },
|
||||
offense: {
|
||||
crimeId: 'theft',
|
||||
specialItems: { elytra: 0, netherStar: 0, beacon: 0, netheriteBlock: 0, diamondBlock: 0 },
|
||||
itemDetails: [{ type: 'diamond', quantity: 2 }] // 2 * 5 = 10 points
|
||||
},
|
||||
expected: { basePoints: 11, totalPoints: 11, punishmentLevel: 'warning', hasCommands: true }
|
||||
},
|
||||
// Theft - Moderate (50-500 item points)
|
||||
{
|
||||
player: { name: 'TestPlayer2', currentPoints: 0 },
|
||||
offense: {
|
||||
crimeId: 'theft',
|
||||
specialItems: { elytra: 1, netherStar: 0, beacon: 0, netheriteBlock: 0, diamondBlock: 0 }, // 20 points
|
||||
itemDetails: [{ type: 'diamond', quantity: 10 }] // 10 * 5 = 50 points, total 70
|
||||
},
|
||||
expected: { basePoints: 72, totalPoints: 72, punishmentLevel: 'warning', hasCommands: true }
|
||||
},
|
||||
// Theft - Severe (> 500 item points)
|
||||
{
|
||||
player: { name: 'TestPlayer3', currentPoints: 0 },
|
||||
offense: {
|
||||
crimeId: 'theft',
|
||||
specialItems: { elytra: 1, netherStar: 1, beacon: 1, netheriteBlock: 0, diamondBlock: 0 }, // 60 points
|
||||
itemDetails: [{ type: 'diamond_block', quantity: 50 }] // 50 * 10 = 500 points, total 560
|
||||
},
|
||||
expected: { basePoints: 563, totalPoints: 563, punishmentLevel: 'warning', hasCommands: true }
|
||||
},
|
||||
// Unconsensual Killing
|
||||
{
|
||||
player: { name: 'TestPlayer4', currentPoints: 0 },
|
||||
offense: { crimeId: 'unconsensual_killing' },
|
||||
expected: { basePoints: 2, totalPoints: 2, punishmentLevel: 'warning', hasCommands: true }
|
||||
},
|
||||
// Illegal Item Use
|
||||
{
|
||||
player: { name: 'TestPlayer5', currentPoints: 0 },
|
||||
offense: { crimeId: 'illegal_item_use' },
|
||||
expected: { basePoints: 1, totalPoints: 1, punishmentLevel: 'warning', hasCommands: true }
|
||||
},
|
||||
// Inappropriate Item Names
|
||||
{
|
||||
player: { name: 'TestPlayer6', currentPoints: 0 },
|
||||
offense: { crimeId: 'inappropriate_item_names' },
|
||||
expected: { basePoints: 1, totalPoints: 1, punishmentLevel: 'warning', hasCommands: true }
|
||||
},
|
||||
// Inappropriate Book Contents
|
||||
{
|
||||
player: { name: 'TestPlayer7', currentPoints: 0 },
|
||||
offense: { crimeId: 'inappropriate_book_contents' },
|
||||
expected: { basePoints: 1, totalPoints: 1, punishmentLevel: 'warning', hasCommands: true }
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
// Block Offenses Test Scenarios
|
||||
static getBlockOffenseScenarios(): TestScenario[] {
|
||||
return [
|
||||
// Vandalism (< 10 blocks)
|
||||
{
|
||||
player: { name: 'TestPlayer8', currentPoints: 0 },
|
||||
offense: {
|
||||
crimeId: 'vandalism',
|
||||
blockCount: 5,
|
||||
entityCount: 2
|
||||
},
|
||||
expected: { basePoints: 1, totalPoints: 1, punishmentLevel: 'warning', hasCommands: true }
|
||||
},
|
||||
// Grief - Minor (< 100 blocks)
|
||||
{
|
||||
player: { name: 'TestPlayer9', currentPoints: 0 },
|
||||
offense: {
|
||||
crimeId: 'grief',
|
||||
blockCount: 50,
|
||||
entityCount: 0
|
||||
},
|
||||
expected: { basePoints: 1, totalPoints: 1, punishmentLevel: 'warning', hasCommands: true }
|
||||
},
|
||||
// Grief - Moderate (100-1000 blocks)
|
||||
{
|
||||
player: { name: 'TestPlayer10', currentPoints: 0 },
|
||||
offense: {
|
||||
crimeId: 'grief',
|
||||
blockCount: 500,
|
||||
entityCount: 0
|
||||
},
|
||||
expected: { basePoints: 1, totalPoints: 1, punishmentLevel: 'warning', hasCommands: true }
|
||||
},
|
||||
// Grief - Large (1000-100000 blocks)
|
||||
{
|
||||
player: { name: 'TestPlayer11', currentPoints: 0 },
|
||||
offense: {
|
||||
crimeId: 'grief',
|
||||
blockCount: 50000,
|
||||
entityCount: 0
|
||||
},
|
||||
expected: { basePoints: 1, totalPoints: 1, punishmentLevel: 'warning', hasCommands: true }
|
||||
},
|
||||
// Grief - Massive (> 100000 blocks)
|
||||
{
|
||||
player: { name: 'TestPlayer12', currentPoints: 0 },
|
||||
offense: {
|
||||
crimeId: 'grief',
|
||||
blockCount: 200000,
|
||||
entityCount: 0
|
||||
},
|
||||
expected: { basePoints: 1, totalPoints: 1, punishmentLevel: 'warning', hasCommands: true }
|
||||
},
|
||||
// Theft-Grief
|
||||
{
|
||||
player: { name: 'TestPlayer13', currentPoints: 0 },
|
||||
offense: {
|
||||
crimeId: 'theft_grief',
|
||||
blockCount: 50
|
||||
},
|
||||
expected: { basePoints: 2, totalPoints: 2, punishmentLevel: 'warning', hasCommands: true }
|
||||
},
|
||||
// Vandalism of Infrastructure
|
||||
{
|
||||
player: { name: 'TestPlayer14', currentPoints: 0 },
|
||||
offense: {
|
||||
crimeId: 'vandalism_infrastructure',
|
||||
blockCount: 10
|
||||
},
|
||||
expected: { basePoints: 6, totalPoints: 6, punishmentLevel: 'warning', hasCommands: true }
|
||||
},
|
||||
// Trespassing
|
||||
{
|
||||
player: { name: 'TestPlayer15', currentPoints: 0 },
|
||||
offense: { crimeId: 'trespassing' },
|
||||
expected: { basePoints: 1, totalPoints: 1, punishmentLevel: 'warning', hasCommands: true }
|
||||
},
|
||||
// Trespassing on Staff/SPP Land
|
||||
{
|
||||
player: { name: 'TestPlayer16', currentPoints: 0 },
|
||||
offense: {
|
||||
crimeId: 'trespassing_staff',
|
||||
isSPP: true
|
||||
},
|
||||
expected: { basePoints: 3, totalPoints: 3, punishmentLevel: 'warning', hasCommands: true }
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
// Hacking Offenses Test Scenarios
|
||||
static getHackingOffenseScenarios(): TestScenario[] {
|
||||
return [
|
||||
// X-Raying
|
||||
{
|
||||
player: { name: 'TestPlayer17', currentPoints: 0 },
|
||||
offense: { crimeId: 'x_raying' },
|
||||
expected: { basePoints: 1, totalPoints: 1, punishmentLevel: 'warning', hasCommands: true }
|
||||
},
|
||||
// Hacking Client
|
||||
{
|
||||
player: { name: 'TestPlayer18', currentPoints: 0 },
|
||||
offense: { crimeId: 'hacking_client' },
|
||||
expected: { basePoints: 5, totalPoints: 5, punishmentLevel: 'kick', hasCommands: true }
|
||||
},
|
||||
// Lagging Server
|
||||
{
|
||||
player: { name: 'TestPlayer19', currentPoints: 0 },
|
||||
offense: { crimeId: 'lagging_server' },
|
||||
expected: { basePoints: 5, totalPoints: 5, punishmentLevel: 'warning', hasCommands: true }
|
||||
},
|
||||
// Worldedit Misuse
|
||||
{
|
||||
player: { name: 'TestPlayer20', currentPoints: 0 },
|
||||
offense: { crimeId: 'worldedit_misuse' },
|
||||
expected: { basePoints: 5, totalPoints: 5, punishmentLevel: 'warning', hasCommands: true }
|
||||
},
|
||||
// Exploit Abuse
|
||||
{
|
||||
player: { name: 'TestPlayer21', currentPoints: 0 },
|
||||
offense: { crimeId: 'exploit_abuse' },
|
||||
expected: { basePoints: 10, totalPoints: 10, punishmentLevel: 'warning', hasCommands: true }
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
// Communication Offenses Test Scenarios
|
||||
static getCommunicationOffenseScenarios(): TestScenario[] {
|
||||
return [
|
||||
// Abusive Chat
|
||||
{
|
||||
player: { name: 'TestPlayer22', currentPoints: 0 },
|
||||
offense: { crimeId: 'abusive_chat' },
|
||||
expected: { basePoints: 1, totalPoints: 1, punishmentLevel: 'warning', hasCommands: true }
|
||||
},
|
||||
// Inciting Verbal Conflict
|
||||
{
|
||||
player: { name: 'TestPlayer23', currentPoints: 0 },
|
||||
offense: { crimeId: 'inciting_verbal_conflict' },
|
||||
expected: { basePoints: 2, totalPoints: 2, punishmentLevel: 'warning', hasCommands: true }
|
||||
},
|
||||
// Abusive VC Language
|
||||
{
|
||||
player: { name: 'TestPlayer24', currentPoints: 0 },
|
||||
offense: { crimeId: 'abusive_vc' },
|
||||
expected: { basePoints: 1, totalPoints: 1, punishmentLevel: 'warning', hasCommands: true }
|
||||
},
|
||||
// Lying to Staff
|
||||
{
|
||||
player: { name: 'TestPlayer25', currentPoints: 0 },
|
||||
offense: { crimeId: 'lying_to_staff' },
|
||||
expected: { basePoints: 1, totalPoints: 1, punishmentLevel: 'warning', hasCommands: true }
|
||||
},
|
||||
// Manipulation
|
||||
{
|
||||
player: { name: 'TestPlayer26', currentPoints: 0 },
|
||||
offense: { crimeId: 'manipulation' },
|
||||
expected: { basePoints: 5, totalPoints: 5, punishmentLevel: 'warning', hasCommands: true }
|
||||
},
|
||||
// Grand Manipulation
|
||||
{
|
||||
player: { name: 'TestPlayer27', currentPoints: 0 },
|
||||
offense: { crimeId: 'grand_manipulation' },
|
||||
expected: { basePoints: 20, totalPoints: 20, punishmentLevel: 'permanent_ban', hasCommands: true }
|
||||
},
|
||||
// Slander (Against SPP)
|
||||
{
|
||||
player: { name: 'TestPlayer28', currentPoints: 0 },
|
||||
offense: {
|
||||
crimeId: 'slander',
|
||||
isSPP: true
|
||||
},
|
||||
expected: { basePoints: 3, totalPoints: 3, punishmentLevel: 'warning', hasCommands: true }
|
||||
},
|
||||
// Violation of NCA
|
||||
{
|
||||
player: { name: 'TestPlayer29', currentPoints: 0 },
|
||||
offense: { crimeId: 'violation_nca' },
|
||||
expected: { basePoints: 2, totalPoints: 2, punishmentLevel: 'warning', hasCommands: true }
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
// Point Decay Test Scenarios
|
||||
static getPointDecayScenarios(): TestScenario[] {
|
||||
return [
|
||||
// Points decay after 1 week
|
||||
{
|
||||
player: { name: 'DecayTest1', currentPoints: 10 },
|
||||
offense: { crimeId: 'abusive_chat' },
|
||||
expected: { basePoints: 1, totalPoints: 11, punishmentLevel: 'warning', hasCommands: true }
|
||||
},
|
||||
// Points decay after multiple weeks
|
||||
{
|
||||
player: { name: 'DecayTest2', currentPoints: 20 },
|
||||
offense: { crimeId: 'abusive_chat' },
|
||||
expected: { basePoints: 1, totalPoints: 21, punishmentLevel: 'warning', hasCommands: true }
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
// Edge Cases
|
||||
static getEdgeCaseScenarios(): TestScenario[] {
|
||||
return [
|
||||
// Zero points player
|
||||
{
|
||||
player: { name: 'EdgeCase1', currentPoints: 0 },
|
||||
offense: { crimeId: 'abusive_chat' },
|
||||
expected: { basePoints: 1, totalPoints: 1, punishmentLevel: 'warning', hasCommands: true }
|
||||
},
|
||||
// High point player
|
||||
{
|
||||
player: { name: 'EdgeCase2', currentPoints: 50 },
|
||||
offense: { crimeId: 'abusive_chat' },
|
||||
expected: { basePoints: 1, totalPoints: 51, punishmentLevel: 'warning', hasCommands: true }
|
||||
},
|
||||
// Empty form validation
|
||||
{
|
||||
player: { name: '', currentPoints: 0 },
|
||||
offense: { crimeId: '' },
|
||||
expected: { basePoints: 0, totalPoints: 0, punishmentLevel: '', hasCommands: false }
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
// Get all test scenarios
|
||||
static getAllScenarios(): TestScenario[] {
|
||||
return [
|
||||
...this.getItemOffenseScenarios(),
|
||||
...this.getBlockOffenseScenarios(),
|
||||
...this.getHackingOffenseScenarios(),
|
||||
...this.getCommunicationOffenseScenarios(),
|
||||
...this.getPointDecayScenarios(),
|
||||
...this.getEdgeCaseScenarios(),
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user