Frontend: - Refactored CSS architecture with new utility classes - Updated dashboard components styling - Improved responsive grid system - Enhanced typography and variables - Updated E2E and integration tests Added: - Claude Code slash commands for validation - SSH tunnel and start test scripts 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
191 lines
6.8 KiB
JavaScript
191 lines
6.8 KiB
JavaScript
import { test } from '@playwright/test';
|
|
import { LoginPage } from '../page-objects/LoginPage.js';
|
|
|
|
test.describe('🔧 Button Fix Test - Identify Disabled State Issue', () => {
|
|
let loginPage;
|
|
|
|
test.beforeEach(async ({ page }) => {
|
|
loginPage = new LoginPage(page);
|
|
await loginPage.navigate();
|
|
});
|
|
|
|
test('🐛 Debug Button Disabled State Logic', async ({ page }) => {
|
|
console.log('\n=== DEBUGGING BUTTON DISABLED STATE ===');
|
|
|
|
// Helper function to get detailed button state
|
|
const getButtonState = async () => {
|
|
return await page.evaluate(() => {
|
|
const usernameInput = document.getElementById('username');
|
|
const passwordInput = document.querySelector('#password input');
|
|
const button = document.querySelector('button[type="submit"]');
|
|
|
|
// Get Vue component data if available
|
|
let vueData = null;
|
|
|
|
try {
|
|
// Try to access Vue component state
|
|
const loginComponent = document.querySelector('.login-container').__vueParentComponent;
|
|
if (loginComponent && loginComponent.setupState) {
|
|
vueData = {
|
|
credentials: loginComponent.setupState.credentials?.value,
|
|
formErrors: loginComponent.setupState.formErrors?.value,
|
|
isFormValid: loginComponent.setupState.isFormValid?.value
|
|
};
|
|
}
|
|
} catch (e) {
|
|
console.log('Could not access Vue state:', e.message);
|
|
}
|
|
|
|
return {
|
|
dom: {
|
|
usernameValue: usernameInput?.value || '',
|
|
passwordValue: passwordInput?.value || '',
|
|
buttonDisabled: button?.disabled,
|
|
buttonClasses: button?.className,
|
|
usernameRequired: usernameInput?.required,
|
|
passwordRequired: passwordInput?.required
|
|
},
|
|
vue: vueData
|
|
};
|
|
});
|
|
};
|
|
|
|
// Test 1: Initial state
|
|
console.log('\n--- Test 1: Initial State ---');
|
|
let state = await getButtonState();
|
|
console.log('Initial state:', JSON.stringify(state, null, 2));
|
|
|
|
// Test 2: Fill only username
|
|
console.log('\n--- Test 2: Username Only ---');
|
|
await page.fill('#username', 'test_user');
|
|
await page.waitForTimeout(500); // Wait for Vue reactivity
|
|
state = await getButtonState();
|
|
console.log('Username only state:', JSON.stringify(state, null, 2));
|
|
|
|
// Test 3: Fill both fields
|
|
console.log('\n--- Test 3: Both Fields ---');
|
|
await page.fill('#password input', 'test_password');
|
|
await page.waitForTimeout(500); // Wait for Vue reactivity
|
|
state = await getButtonState();
|
|
console.log('Both fields state:', JSON.stringify(state, null, 2));
|
|
|
|
// Test 4: Check if validation triggers
|
|
console.log('\n--- Test 4: Trigger Validation ---');
|
|
await page.click('.login-card'); // Click outside to blur
|
|
await page.waitForTimeout(500);
|
|
state = await getButtonState();
|
|
console.log('After blur state:', JSON.stringify(state, null, 2));
|
|
|
|
// Test 5: Manual button click attempt
|
|
console.log('\n--- Test 5: Button Click Attempt ---');
|
|
const isClickable = await page.evaluate(() => {
|
|
const button = document.querySelector('button[type="submit"]');
|
|
return !button.disabled;
|
|
});
|
|
console.log('Button is clickable:', isClickable);
|
|
|
|
if (isClickable) {
|
|
console.log('✅ Button should be clickable');
|
|
} else {
|
|
console.log('❌ Button is still disabled - investigating why...');
|
|
|
|
// Check validation logic
|
|
const validationState = await page.evaluate(() => {
|
|
const usernameInput = document.getElementById('username');
|
|
const passwordInput = document.querySelector('#password input');
|
|
|
|
return {
|
|
usernameEmpty: !usernameInput.value.trim(),
|
|
passwordEmpty: !passwordInput.value.trim(),
|
|
usernameLength: usernameInput.value.length,
|
|
passwordLength: passwordInput.value.length,
|
|
formValidity: usernameInput.form?.checkValidity()
|
|
};
|
|
});
|
|
|
|
console.log('Validation details:', JSON.stringify(validationState, null, 2));
|
|
}
|
|
|
|
// Take screenshot for analysis
|
|
await page.screenshot({ path: 'button-debug.png', fullPage: true });
|
|
});
|
|
|
|
test('🔄 Test Button Reactivity with Real Input', async ({ page }) => {
|
|
console.log('\n=== TESTING BUTTON REACTIVITY ===');
|
|
|
|
// Monitor button state changes
|
|
const buttonStates = [];
|
|
|
|
const checkButton = async (action) => {
|
|
const disabled = await page.locator('button[type="submit"]').isDisabled();
|
|
buttonStates.push({ action, disabled });
|
|
console.log(`After ${action}: disabled = ${disabled}`);
|
|
};
|
|
|
|
await checkButton('initial load');
|
|
|
|
// Type character by character to see when button enables
|
|
const username = 'test';
|
|
const password = 'pass';
|
|
|
|
for (let i = 0; i < username.length; i++) {
|
|
await page.fill('#username', username.substring(0, i + 1));
|
|
await page.waitForTimeout(100);
|
|
await checkButton(`username: "${username.substring(0, i + 1)}"`);
|
|
}
|
|
|
|
for (let i = 0; i < password.length; i++) {
|
|
await page.fill('#password input', password.substring(0, i + 1));
|
|
await page.waitForTimeout(100);
|
|
await checkButton(`password: "${password.substring(0, i + 1)}"`);
|
|
}
|
|
|
|
console.log('\nButton state progression:');
|
|
buttonStates.forEach((state, index) => {
|
|
console.log(`${index + 1}. ${state.action}: ${state.disabled ? 'DISABLED' : 'ENABLED'}`);
|
|
});
|
|
});
|
|
|
|
test('🎯 Force Button Enable Test', async ({ page }) => {
|
|
console.log('\n=== TESTING FORCED BUTTON ENABLE ===');
|
|
|
|
// Fill valid data
|
|
await page.fill('#username', 'valid_user');
|
|
await page.fill('#password input', 'valid_password');
|
|
|
|
// Wait for Vue reactivity
|
|
await page.waitForTimeout(1000);
|
|
|
|
// Force enable button via JavaScript if needed
|
|
const buttonEnabled = await page.evaluate(() => {
|
|
const button = document.querySelector('button[type="submit"]');
|
|
const wasDisabled = button.disabled;
|
|
|
|
// Try to force enable for testing
|
|
button.disabled = false;
|
|
button.classList.remove('p-disabled');
|
|
|
|
return { wasDisabled, nowDisabled: button.disabled };
|
|
});
|
|
|
|
console.log('Button enable attempt:', buttonEnabled);
|
|
|
|
if (!buttonEnabled.nowDisabled) {
|
|
console.log('✅ Button was successfully enabled');
|
|
|
|
// Try to click it now
|
|
await page.click('button[type="submit"]');
|
|
console.log('✅ Button click succeeded');
|
|
|
|
// Wait for potential API call
|
|
await page.waitForTimeout(2000);
|
|
|
|
// Check if login was attempted
|
|
const currentUrl = page.url();
|
|
console.log('Current URL after click:', currentUrl);
|
|
|
|
} else {
|
|
console.log('❌ Could not enable button');
|
|
}
|
|
});
|
|
}); |