Files
dockergprompt/playwright-report/data/dd2e8ae9f36374fdbc4083f4ced15a0879b8266a.md
T
2026-09-01 09:22:30 -03:00

236 lines
11 KiB
Markdown
Executable File

# Instructions
- Following Playwright test failed.
- Explain why, be concise, respect Playwright best practices.
- Provide a snippet of code with the fix, if possible.
# Test info
- Name: application.spec.js >> Forms Validation and Error Messages >> Temperature field accepts only 0.0-1.0 range
- Location: tests/e2e/application.spec.js:543:3
# Error details
```
Error: expect(locator).toBeVisible() failed
Locator: locator('.text-danger')
Expected: visible
Error: strict mode violation: locator('.text-danger') resolved to 2 elements:
1) <div class="text-danger small">The title field is required.</div> aka getByText('The title field is required.')
2) <div class="text-danger small">The temperature field must not be greater than 1.</div> aka getByText('The temperature field must')
Call log:
- Expect "toBeVisible" with timeout 10000ms
- waiting for locator('.text-danger')
- waiting for navigation to finish...
- navigated to "http://localhost:16820/prompt-projects/create"
```
# Test source
```ts
460 | untestableFeatures.push('AI provider detail view: no providers exist to click');
461 | }
462 | });
463 |
464 | test('Edit AI provider', async () => {
465 | await adminPage.goto(`${BASE_URL}/ai-providers`);
466 | const firstEdit = adminPage.locator('a[href*="ai-providers/"][class*="btn-warning"]').first();
467 | const count = await firstEdit.count();
468 | if (count > 0) {
469 | await firstEdit.click();
470 | await adminPage.waitForURL((url) => url.pathname.includes('/ai-providers/') && !url.pathname.includes('/create'), { timeout: 10000 });
471 | await adminPage.waitForLoadState('networkidle').catch(() => {});
472 | await expect(adminPage.locator('#name')).toBeVisible();
473 | } else {
474 | untestableFeatures.push('AI provider edit: no providers exist to edit');
475 | }
476 | });
477 |
478 | test('Delete AI provider', async () => {
479 | await adminPage.goto(`${BASE_URL}/ai-providers`);
480 | const firstDelete = adminPage.locator('form[action*="ai-providers"][method="POST"]').first();
481 | const count = await firstDelete.count();
482 | if (count > 0) {
483 | adminPage.on('dialog', (dialog) => dialog.accept());
484 | await firstDelete.evaluate((form) => form.submit());
485 | await expect(adminPage.locator('.alert-success, .alert-danger')).toBeVisible({ timeout: 10000 });
486 | } else {
487 | untestableFeatures.push('AI provider delete: no providers exist to delete');
488 | }
489 | });
490 |
491 | test('API key visibility toggle works', async () => {
492 | await adminPage.goto(`${BASE_URL}/ai-providers/create`);
493 | const apiKeyInput = adminPage.locator('#api_key');
494 | const toggleBtn = adminPage.locator('#toggleApiKey');
495 | if (await toggleBtn.count() > 0) {
496 | await expect(apiKeyInput).toHaveAttribute('type', 'password');
497 | await toggleBtn.click();
498 | await expect(apiKeyInput).toHaveAttribute('type', 'text');
499 | await toggleBtn.click();
500 | await expect(apiKeyInput).toHaveAttribute('type', 'password');
501 | } else {
502 | untestableFeatures.push('API key toggle: toggle button not found');
503 | }
504 | });
505 | });
506 |
507 | // ========== FORMS VALIDATION ==========
508 | test.describe('Forms Validation and Error Messages', () => {
509 | let adminPage;
510 |
511 | test.beforeEach(async ({ context }) => {
512 | adminPage = await login(context, SUPERADMIN_EMAIL, SUPERADMIN_PASSWORD);
513 | });
514 |
515 | test.afterEach(async () => {
516 | await adminPage.close();
517 | });
518 |
519 | test('Prompt project form shows validation errors for missing fields', async () => {
520 | await adminPage.goto(`${BASE_URL}/prompt-projects/create`);
521 | await adminPage.evaluate(() => {
522 | const form = document.querySelector('form:has(#title)');
523 | if (form) {
524 | Array.from(form.querySelectorAll('[required]')).forEach(el => el.removeAttribute('required'));
525 | form.submit();
526 | }
527 | });
528 | await expect(adminPage.locator('.text-danger')).toHaveCount(2, { timeout: 10000 });
529 | });
530 |
531 | test('AI provider form shows validation errors for missing fields', async () => {
532 | await adminPage.goto(`${BASE_URL}/ai-providers/create`);
533 | await adminPage.evaluate(() => {
534 | const form = document.querySelector('form:has(#name)');
535 | if (form) {
536 | Array.from(form.querySelectorAll('[required]')).forEach(el => el.removeAttribute('required'));
537 | form.submit();
538 | }
539 | });
540 | await expect(adminPage.locator('.text-danger')).toHaveCount(4, { timeout: 10000 });
541 | });
542 |
543 | test('Temperature field accepts only 0.0-1.0 range', async () => {
544 | await adminPage.goto(`${BASE_URL}/prompt-projects/create`);
545 | await adminPage.fill('#temperature', '1.5');
546 | await adminPage.evaluate(() => {
547 | const form = document.querySelector('form:has(#title)');
548 | if (form) form.submit();
549 | });
550 | const providerSelect = adminPage.locator('#provider_id');
551 | const providerCount = await providerSelect.locator('option').count();
552 | if (providerCount > 1) {
553 | await providerSelect.selectOption({ index: 1 });
554 | }
555 | await adminPage.fill('#objective', 'Test');
556 | await adminPage.evaluate(() => {
557 | const form = document.querySelector('form:has(#title)');
558 | if (form) form.submit();
559 | });
> 560 | await expect(adminPage.locator('.text-danger')).toBeVisible({ timeout: 10000 });
| ^ Error: expect(locator).toBeVisible() failed
561 | });
562 |
563 | test('Max tokens must be a positive integer', async () => {
564 | await adminPage.goto(`${BASE_URL}/prompt-projects/create`);
565 | await adminPage.fill('#max_tokens', '-5');
566 | await adminPage.evaluate(() => {
567 | const form = document.querySelector('form:has(#title)');
568 | if (form) form.submit();
569 | });
570 | const providerSelect = adminPage.locator('#provider_id');
571 | const providerCount = await providerSelect.locator('option').count();
572 | if (providerCount > 1) {
573 | await providerSelect.selectOption({ index: 1 });
574 | }
575 | await adminPage.fill('#objective', 'Test');
576 | await adminPage.evaluate(() => {
577 | const form = document.querySelector('form:has(#title)');
578 | if (form) form.submit();
579 | });
580 | await expect(adminPage.locator('.text-danger')).toBeVisible({ timeout: 10000 });
581 | });
582 | });
583 |
584 | // ========== COOKIE CONSENT ==========
585 | test.describe('Cookie Consent Banner', () => {
586 | test('Banner appears on public pages', async ({ page }) => {
587 | await page.goto(BASE_URL);
588 | await expect(page.locator('#cookieConsentBanner')).toBeAttached();
589 | });
590 |
591 | test('Accept all cookies closes banner', async ({ page }) => {
592 | await page.goto(BASE_URL);
593 | await page.waitForSelector('#cookieConsentBanner', { state: 'visible', timeout: 5000 }).catch(() => {});
594 | const acceptBtn = page.locator('.cookie-btn-accept');
595 | if (await acceptBtn.count() > 0) {
596 | await acceptBtn.click();
597 | await page.waitForTimeout(500);
598 | await expect(page.locator('#cookieConsentBanner')).not.toBeVisible();
599 | } else {
600 | untestableFeatures.push('Cookie consent accept button not visible (banner may not have appeared)');
601 | }
602 | });
603 |
604 | test('Cookie preferences modal can be opened', async ({ page }) => {
605 | await page.goto(BASE_URL);
606 | await page.waitForSelector('#cookieConsentBanner', { state: 'visible', timeout: 5000 }).catch(() => {});
607 | const customizeBtn = page.locator('.cookie-btn-customize');
608 | if (await customizeBtn.count() > 0) {
609 | await customizeBtn.click();
610 | await expect(page.locator('#cookieConsentPreferences')).toBeVisible();
611 | await page.locator('.btn-close').click();
612 | } else {
613 | untestableFeatures.push('Cookie customize button not visible');
614 | }
615 | });
616 |
617 | test('Cookie consent persists across page navigation', async ({ page }) => {
618 | await page.goto(BASE_URL);
619 | await page.waitForSelector('#cookieConsentBanner', { state: 'visible', timeout: 5000 }).catch(() => {});
620 | const acceptBtn = page.locator('.cookie-btn-accept');
621 | if (await acceptBtn.count() > 0) {
622 | await acceptBtn.click();
623 | await page.waitForTimeout(500);
624 | await page.goto(`${BASE_URL}/login`);
625 | const banner = page.locator('#cookieConsentBanner');
626 | await expect(banner).not.toBeVisible({ timeout: 3000 }).catch(() => {});
627 | } else {
628 | untestableFeatures.push('Cookie consent accept button not visible for persistence test');
629 | }
630 | });
631 | });
632 |
633 | // ========== RESPONSIVENESS ==========
634 | test.describe('Responsiveness', () => {
635 | test('Desktop viewport 1920x1080: sidebar visible and layout stable', async ({ page }) => {
636 | await page.setViewportSize({ width: 1920, height: 1080 });
637 | await page.goto(`${BASE_URL}/login`);
638 | await expect(page.locator('.login-card')).toBeVisible();
639 | });
640 |
641 | test('Mobile viewport 375x667: login page adapts', async ({ page }) => {
642 | await page.setViewportSize({ width: 375, height: 667 });
643 | await page.goto(`${BASE_URL}/login`);
644 | await expect(page.locator('.login-card')).toBeVisible();
645 | await expect(page.locator('#email')).toBeVisible();
646 | });
647 |
648 | test('Mobile: hamburger menu toggles sidebar', async ({ context }) => {
649 | const page = await login(context, SUPERADMIN_EMAIL, SUPERADMIN_PASSWORD);
650 | await page.setViewportSize({ width: 375, height: 667 });
651 | await page.goto(`${BASE_URL}/dashboard`);
652 | const sidebar = page.locator('#sidebar');
653 | await expect(sidebar).toBeVisible();
654 | await page.click('#sidebarCollapse');
655 | await page.waitForTimeout(300);
656 | await page.close();
657 | });
658 |
659 | test('Mobile: dashboard cards stack vertically', async ({ page }) => {
660 | await page.setViewportSize({ width: 375, height: 667 });
```