diff --git a/package-lock.json b/package-lock.json index 83fd30e..1937307 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,6 +28,7 @@ "cheerio": "^1.1.0", "dotenv": "^17.1.0", "node-cron": "^4.2.0", + "playwright": "^1.54.1", "qrcode": "^1.5.4", "ramda": "^0.31.3", "react": "^19.1.0", @@ -9293,6 +9294,50 @@ "node": ">=16.20.0" } }, + "node_modules/playwright": { + "version": "1.54.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.54.1.tgz", + "integrity": "sha512-peWpSwIBmSLi6aW2auvrUtf2DqY16YYcCMO8rTVx486jKmDTJg7UAhyrraP98GB8BoPURZP8+nxO7TSd4cPr5g==", + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.54.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.54.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.54.1.tgz", + "integrity": "sha512-Nbjs2zjj0htNhzgiy5wu+3w09YetDx5pkrpI/kZotDlDUaYk0HVA5xrBVPdow4SAUIlhgKcJeJg4GRKW6xHusA==", + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/playwright/node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/pngjs": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", diff --git a/package.json b/package.json index a80b53a..3855ccc 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "cheerio": "^1.1.0", "dotenv": "^17.1.0", "node-cron": "^4.2.0", + "playwright": "^1.54.1", "qrcode": "^1.5.4", "ramda": "^0.31.3", "react": "^19.1.0", diff --git a/test-auth-flow.js b/test-auth-flow.js new file mode 100644 index 0000000..9ff824b --- /dev/null +++ b/test-auth-flow.js @@ -0,0 +1,159 @@ +/** + * Authentication Flow Test Script + * Tests the login flow to verify no more flashing or redirect loops + */ + +import { chromium } from 'playwright'; + +async function testAuthFlow() { + console.log('๐Ÿงช Starting authentication flow tests...'); + + const browser = await chromium.launch({ + headless: true, // Headless mode for server environment + args: ['--no-sandbox', '--disable-setuid-sandbox'] // Additional args for server environments + }); + + const context = await browser.newContext({ + viewport: { width: 1280, height: 720 }, + // Record video for debugging + recordVideo: { + dir: './test-recordings/', + size: { width: 1280, height: 720 } + } + }); + + const page = await context.newPage(); + + try { + console.log('๐Ÿ“ Test 1: Accessing dashboard without authentication'); + + // Navigate to dashboard (should redirect to login) + await page.goto('http://localhost:3000/dashboard', { + waitUntil: 'networkidle', + timeout: 10000 + }); + + // Wait for any redirects to complete + await page.waitForTimeout(2000); + + // Check if we're on the login page + const currentUrl = page.url(); + console.log(`Current URL: ${currentUrl}`); + + if (currentUrl.includes('/login')) { + console.log('โœ… Dashboard correctly redirected to login page'); + } else { + console.log('โŒ Dashboard did not redirect to login page'); + } + + // Take screenshot of login page + await page.screenshot({ + path: './test-recordings/01-login-page.png', + fullPage: true + }); + + console.log('๐Ÿ“ Test 2: Testing login flow'); + + // Check if login form is visible + const emailInput = await page.locator('#email'); + const passwordInput = await page.locator('#password'); + const submitButton = await page.locator('button[type="submit"]'); + + if (await emailInput.isVisible() && await passwordInput.isVisible()) { + console.log('โœ… Login form is visible and ready'); + + // Note: We're not actually logging in since we don't have test credentials + // This test focuses on the redirect behavior and UI stability + + console.log('๐Ÿ“ Test 3: Checking for any flashing or unstable elements'); + + // Monitor for any sudden theme changes or content flashing + let themeChanges = 0; + page.on('console', msg => { + if (msg.text().includes('theme') || msg.text().includes('PROTECTED') || msg.text().includes('Auth')) { + console.log(`Console: ${msg.text()}`); + } + }); + + // Wait and observe the page for stability + await page.waitForTimeout(3000); + + // Take final screenshot + await page.screenshot({ + path: './test-recordings/02-login-stable.png', + fullPage: true + }); + + console.log('โœ… Login page appears stable (no visible flashing)'); + + } else { + console.log('โŒ Login form elements not found'); + } + + console.log('๐Ÿ“ Test 4: Testing auth test page'); + + // Navigate to the auth test page + await page.goto('http://localhost:3000/auth-test-unified', { + waitUntil: 'networkidle', + timeout: 10000 + }); + + await page.waitForTimeout(2000); + + // Take screenshot of auth test page + await page.screenshot({ + path: './test-recordings/03-auth-test-page.png', + fullPage: true + }); + + // Check if auth test page loaded properly + const authTestTitle = await page.locator('h1:has-text("Unified Authentication System Test")'); + if (await authTestTitle.isVisible()) { + console.log('โœ… Auth test page loaded successfully'); + } else { + console.log('โŒ Auth test page did not load properly'); + } + + console.log('๐Ÿ“ Test 5: Testing direct home page access'); + + // Test home page + await page.goto('http://localhost:3000/', { + waitUntil: 'networkidle', + timeout: 10000 + }); + + await page.waitForTimeout(2000); + + // Take screenshot of home page + await page.screenshot({ + path: './test-recordings/04-home-page.png', + fullPage: true + }); + + console.log('โœ… Home page loaded successfully'); + + } catch (error) { + console.error('โŒ Test failed:', error.message); + + // Take error screenshot + await page.screenshot({ + path: './test-recordings/error-screenshot.png', + fullPage: true + }); + } finally { + console.log('๐Ÿ Closing browser...'); + await context.close(); + await browser.close(); + } + + console.log('๐Ÿ“Š Test Summary:'); + console.log('- Dashboard redirect: Tested'); + console.log('- Login page stability: Tested'); + console.log('- Auth test page: Tested'); + console.log('- Home page: Tested'); + console.log('- Screenshots saved to: ./test-recordings/'); + console.log('โœ… Authentication flow tests completed!'); +} + +// Run the tests +testAuthFlow().catch(console.error); \ No newline at end of file