Dashboard users part 2 (#79)
* fix: add FigmaImage directory to .gitignore * feat: enhance dashboard tests and add new components for rendering * feat: add navigation functionality and UI enhancements to dashboard components * feat: add article preview and mentor contact modals, implement article builder and FAQ page * refactor: remove FAQ route and update settings layout for improved responsiveness * feat: enhance two-step authentication UI and functionality with improved styles and user feedback * feat: add mentoring detail and feedback modals, enhance mentoring page functionality and UI * fix: handle JSON parse failure in edit profile modal error handling
This commit is contained in:
@@ -58,9 +58,29 @@ test.describe('Automated Route Discovery & Screenshots', () => {
|
||||
console.log(`Processing: ${baseURL}${route}`);
|
||||
|
||||
try {
|
||||
// Mock auth session if accessing protected routes
|
||||
if (route.startsWith('/dashboard') || route.startsWith('/profile')) {
|
||||
await page.addInitScript(() => {
|
||||
window.localStorage.setItem('auth-storage', JSON.stringify({
|
||||
state: {
|
||||
session: {
|
||||
user: {
|
||||
id: 'sample-user-id',
|
||||
fullname: 'John Doe',
|
||||
email: 'john@example.com',
|
||||
avatar: '/image/mascot-character.webp'
|
||||
},
|
||||
token: 'mock-token'
|
||||
}
|
||||
},
|
||||
version: 0
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
await page.goto(`${baseURL}${route}`, {
|
||||
waitUntil: 'networkidle',
|
||||
timeout: 30000
|
||||
timeout: 60000
|
||||
});
|
||||
|
||||
// Wait for rendering
|
||||
@@ -75,6 +95,118 @@ test.describe('Automated Route Discovery & Screenshots', () => {
|
||||
});
|
||||
|
||||
console.log(`Success: ${fileName}.png`);
|
||||
|
||||
// --- Custom logic for Modals and Tabs ---
|
||||
|
||||
// 1. Mentoring Modals
|
||||
if (route === '/dashboard/mentoring') {
|
||||
// Detail modal
|
||||
const detailButton = page.getByRole('button', { name: 'Cek Detail' }).first();
|
||||
if (await detailButton.isVisible()) {
|
||||
await detailButton.click({ timeout: 5000 });
|
||||
const detailModal = page.locator('div.fixed.inset-0').filter({ hasText: 'Detail Sesi Mentoring' }).first();
|
||||
await detailModal.waitFor({ state: 'visible', timeout: 5000 });
|
||||
await page.waitForTimeout(500);
|
||||
await page.screenshot({ path: path.join(screenshotDir, 'dashboard_mentoring_modal_detail.png') });
|
||||
await detailModal.locator('button').first().click({ timeout: 5000 });
|
||||
await detailModal.waitFor({ state: 'hidden', timeout: 5000 });
|
||||
}
|
||||
|
||||
// Contact modal
|
||||
const cancelButton = page.getByRole('button', { name: 'Cancel' }).first();
|
||||
if (await cancelButton.isVisible()) {
|
||||
await cancelButton.click({ timeout: 5000 });
|
||||
const contactModal = page.locator('div.fixed.inset-0').filter({ hasText: 'Hubungi mentor melalui platform berikut' }).first();
|
||||
await contactModal.waitFor({ state: 'visible', timeout: 5000 });
|
||||
await page.waitForTimeout(500);
|
||||
await page.screenshot({ path: path.join(screenshotDir, 'dashboard_mentoring_modal_contact.png') });
|
||||
await contactModal.getByRole('button', { name: 'Tutup' }).click({ timeout: 5000 });
|
||||
await contactModal.waitFor({ state: 'hidden', timeout: 5000 });
|
||||
}
|
||||
|
||||
// Feedback modal
|
||||
const feedbackBtn = page.getByRole('button', { name: 'Kirim Feedback' }).first();
|
||||
if (await feedbackBtn.isVisible()) {
|
||||
await feedbackBtn.click({ timeout: 5000 });
|
||||
const feedbackModal = page
|
||||
.locator('div.fixed.inset-0')
|
||||
.filter({ hasText: /Beri Feedback|Feedback Mentor/ })
|
||||
.first();
|
||||
await feedbackModal.waitFor({ state: 'visible', timeout: 5000 });
|
||||
await page.waitForTimeout(500);
|
||||
await page.screenshot({ path: path.join(screenshotDir, 'dashboard_mentoring_modal_feedback.png') });
|
||||
const closeFeedbackBtn = feedbackModal.getByRole('button', { name: 'Batal' });
|
||||
if (await closeFeedbackBtn.isVisible()) {
|
||||
await closeFeedbackBtn.click({ timeout: 5000 });
|
||||
await feedbackModal.waitFor({ state: 'hidden', timeout: 5000 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Learning Path Tabs
|
||||
if (route === '/dashboard/learning-path') {
|
||||
await page.click('button:has-text("Article")');
|
||||
await page.waitForTimeout(500);
|
||||
await page.screenshot({ path: path.join(screenshotDir, 'dashboard_learning-path_tab_article.png') });
|
||||
}
|
||||
|
||||
// 3. Settings Sections & 2FA Modals
|
||||
if (route === '/dashboard/settings') {
|
||||
const sections = ['Privasi & Keamanan', 'FAQ', 'Laporkan Kendala', 'Umpan Balik'];
|
||||
for (const section of sections) {
|
||||
const sectionButton = page.getByRole('button', { name: section }).first();
|
||||
if (!(await sectionButton.isVisible())) {
|
||||
console.warn(`Section button not found: ${section}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
await sectionButton.click({ timeout: 5000 });
|
||||
await page.waitForTimeout(300);
|
||||
const slug = section
|
||||
.toLowerCase()
|
||||
.replace(/&/g, 'and')
|
||||
.replace(/\s+/g, '_')
|
||||
.replace(/[^a-z0-9_]/g, '');
|
||||
await page.screenshot({ path: path.join(screenshotDir, `dashboard_settings_section_${slug}.png`) });
|
||||
|
||||
// If in Privacy, test 2FA modal
|
||||
if (section === 'Privasi & Keamanan') {
|
||||
const enable2FaButton = page.getByRole('button', { name: 'Aktifkan 2FA' }).first();
|
||||
if (!(await enable2FaButton.isVisible())) {
|
||||
console.warn('2FA trigger button not found');
|
||||
continue;
|
||||
}
|
||||
|
||||
await enable2FaButton.click({ timeout: 5000 });
|
||||
const emailModal = page.locator('div.fixed.inset-0').filter({ hasText: 'Verifikasi Email' }).first();
|
||||
await emailModal.waitFor({ state: 'visible', timeout: 5000 });
|
||||
await page.waitForTimeout(500);
|
||||
await page.screenshot({ path: path.join(screenshotDir, 'dashboard_settings_modal_2fa_step1.png') });
|
||||
|
||||
await emailModal.getByRole('button', { name: 'Kirim Kode' }).click({ timeout: 5000 });
|
||||
const otpModal = page.locator('div.fixed.inset-0').filter({ hasText: 'Masukkan Kode OTP' }).first();
|
||||
await otpModal.waitFor({ state: 'visible', timeout: 5000 });
|
||||
await page.waitForTimeout(500);
|
||||
await page.screenshot({ path: path.join(screenshotDir, 'dashboard_settings_modal_2fa_step2.png') });
|
||||
|
||||
await otpModal.locator('button').first().click({ timeout: 5000 });
|
||||
await otpModal.waitFor({ state: 'hidden', timeout: 5000 });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Header Notifications
|
||||
if (route === '/dashboard') {
|
||||
const notificationButton = page.locator('header button').first();
|
||||
if (await notificationButton.isVisible()) {
|
||||
await notificationButton.click({ timeout: 5000 });
|
||||
await page.waitForTimeout(500);
|
||||
await page.screenshot({ path: path.join(screenshotDir, 'dashboard_header_notifications.png') });
|
||||
} else {
|
||||
console.warn('Notification button not found on dashboard header');
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error(`Failed to capture ${route}:`, error.message);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user