# 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: features.spec.ts >> Mood Radio Page >> shows mood name - Location: e2e/features.spec.ts:12:7 # Error details ``` Error: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:5173/mood Call log: - navigating to "http://localhost:5173/mood", waiting until "load" ``` # Test source ```ts 1 | import { test, expect } from '@playwright/test'; 2 | 3 | test.describe('Mood Radio Page', () => { 4 | test.beforeEach(async ({ page }) => { > 5 | await page.goto('/mood'); | ^ Error: page.goto: net::ERR_CONNECTION_REFUSED at http://localhost:5173/mood 6 | }); 7 | 8 | test('shows mood radio title', async ({ page }) => { 9 | await expect(page.getByText('Mood Radio')).toBeVisible(); 10 | }); 11 | 12 | test('shows mood name', async ({ page }) => { 13 | // Should show one of the mood names 14 | await expect(page.getByText(/Sad|Happy|Energetic|Focused|Chill/)).toBeVisible(); 15 | }); 16 | 17 | test('shows play mood button', async ({ page }) => { 18 | await expect(page.getByText(/Play Mood|Playing/)).toBeVisible(); 19 | }); 20 | 21 | test('shows set the mood button', async ({ page }) => { 22 | await expect(page.getByText('Set the Mood')).toBeVisible(); 23 | }); 24 | 25 | test('clicking set the mood changes mood', async ({ page }) => { 26 | const currentMood = await page.getByRole('heading', { level: 2 }).textContent(); 27 | await page.getByText('Set the Mood').click(); 28 | await page.waitForTimeout(500); 29 | const newMood = await page.getByRole('heading', { level: 2 }).textContent(); 30 | // Mood should change (might rarely be same by random chance) 31 | }); 32 | 33 | test('shows circular progress indicator', async ({ page }) => { 34 | // SVG circle should be present 35 | const circle = page.locator('svg circle').last(); 36 | await expect(circle).toBeVisible(); 37 | }); 38 | }); 39 | 40 | test.describe('LoFi Channel Page', () => { 41 | test.beforeEach(async ({ page }) => { 42 | await page.goto('/lofi'); 43 | }); 44 | 45 | test('shows lofi channel title', async ({ page }) => { 46 | await expect(page.getByText('LoFi Channel')).toBeVisible(); 47 | }); 48 | 49 | test('shows lofi channels', async ({ page }) => { 50 | // Should show at least 3 channels 51 | const channels = page.locator('[class*="aspect-video"]'); 52 | await expect(channels).toHaveCount(atLeast(3)); 53 | }); 54 | 55 | test('shows LoFi label on channels', async ({ page }) => { 56 | await expect(page.getByText('LoFi')).toBeVisible(); 57 | }); 58 | 59 | function atLeast(n: number) { 60 | return { 61 | pass(received: number) { 62 | return received >= n; 63 | }, 64 | message: () => `expected at least ${n} elements`, 65 | }; 66 | } 67 | }); 68 | 69 | test.describe('Internet Radio Page', () => { 70 | test.beforeEach(async ({ page }) => { 71 | await page.goto('/radio'); 72 | }); 73 | 74 | test('shows internet radio title', async ({ page }) => { 75 | await expect(page.getByText('Internet Radio')).toBeVisible(); 76 | }); 77 | 78 | test('shows search bar', async ({ page }) => { 79 | const searchInput = page.getByPlaceholder(/What music is calling/); 80 | await expect(searchInput).toBeVisible(); 81 | }); 82 | 83 | test('shows stations section', async ({ page }) => { 84 | await expect(page.getByText('Stations')).toBeVisible(); 85 | }); 86 | }); 87 | 88 | test.describe('New Releases Page', () => { 89 | test.beforeEach(async ({ page }) => { 90 | await page.goto('/releases'); 91 | }); 92 | 93 | test('shows new releases title', async ({ page }) => { 94 | await expect(page.getByText('New Releases')).toBeVisible(); 95 | }); 96 | 97 | test('shows empty state or releases', async ({ page }) => { 98 | // Either shows releases or empty state with "Add music" message 99 | const hasContent = await page.locator('h2.font-display').count(); 100 | expect(hasContent >= 0).toBeTruthy(); 101 | }); 102 | }); 103 | 104 | test.describe('SharePlay Page', () => { 105 | test.beforeEach(async ({ page }) => { ```