|
17 | 17 | import {test, expect} from '@playwright/test'; |
18 | 18 | import {loginAsUser, BASE_URL, expectDualThemeScreenshot} from './utils'; |
19 | 19 |
|
20 | | -test.beforeEach(async () => {}); |
| 20 | +test('redirects unauthenticated user to home and shows toast', async ({ |
| 21 | + page, |
| 22 | +}) => { |
| 23 | + await page.goto(`${BASE_URL}/settings/notification-channels`); |
| 24 | + |
| 25 | + // Expect to be redirected to the home page. |
| 26 | + await expect(page).toHaveURL(`${BASE_URL}/`); |
| 27 | + // FYI: We do not assert the toast because it flashes on the screen due to the redirect. |
| 28 | +}); |
21 | 29 |
|
22 | 30 | test.describe('Notification Channels Page', () => { |
23 | | - test('redirects unauthenticated user to home and shows toast', async ({ |
24 | | - page, |
25 | | - }) => { |
| 31 | + test.beforeEach(async ({page}) => { |
| 32 | + await loginAsUser(page, 'test user 1'); |
26 | 33 | await page.goto(`${BASE_URL}/settings/notification-channels`); |
27 | | - |
28 | | - // Expect to be redirected to the home page. |
29 | | - await expect(page).toHaveURL(BASE_URL); |
30 | | - // FYI: We do not assert the toast because it flashes on the screen due to the redirect. |
31 | 34 | }); |
32 | 35 |
|
33 | 36 | test('authenticated user sees their email channel and coming soon messages', async ({ |
34 | 37 | page, |
35 | 38 | }) => { |
36 | | - // Log in as a test user |
37 | | - await loginAsUser(page, 'test user 1'); |
38 | | - |
39 | | - // Navigate to the notification channels page |
40 | | - await page.goto(`${BASE_URL}/settings/notification-channels`); |
41 | | - |
42 | | - // Move the mouse to a neutral position to avoid hover effects on the screenshot |
43 | | - await page.mouse.move(0, 0); |
44 | | - |
45 | | - // Expect the URL to be correct |
| 39 | + // Expect the URL to be correct. |
46 | 40 | await expect(page).toHaveURL(`${BASE_URL}/settings/notification-channels`); |
47 | 41 |
|
48 | | - // Verify Email panel content |
| 42 | + // Verify Email panel content. |
49 | 43 | const emailPanel = page.locator('webstatus-notification-email-channels'); |
50 | 44 | await expect(emailPanel).toBeVisible(); |
51 | 45 | await expect(emailPanel).toContainText('test.user.1@example.com'); |
52 | 46 | await expect(emailPanel).toContainText('Enabled'); |
53 | 47 |
|
54 | | - // Verify RSS panel content |
| 48 | + // Verify RSS panel content. |
55 | 49 | const rssPanel = page.locator('webstatus-notification-rss-channels'); |
56 | 50 | await expect(rssPanel).toBeVisible(); |
57 | 51 | await expect(rssPanel).toContainText('Coming soon'); |
58 | 52 |
|
59 | | - // Verify Webhook panel content |
| 53 | + // Verify Webhook panel content. |
60 | 54 | const webhookPanel = page.locator( |
61 | 55 | 'webstatus-notification-webhook-channels', |
62 | 56 | ); |
63 | 57 | await expect(webhookPanel).toBeVisible(); |
64 | | - await expect(webhookPanel).toContainText('Coming soon'); |
65 | 58 |
|
66 | | - // Take a screenshot for visual regression |
| 59 | + // Move the mouse to a neutral position to avoid hover effects on the screenshot. |
| 60 | + await page.mouse.move(0, 0); |
| 61 | + |
| 62 | + // Take a screenshot for visual regression. |
67 | 63 | const pageContainer = page.locator('.page-container'); |
68 | 64 | await expectDualThemeScreenshot( |
69 | 65 | page, |
70 | 66 | pageContainer, |
71 | 67 | 'notification-channels-authenticated', |
72 | 68 | ); |
73 | 69 | }); |
| 70 | + |
| 71 | + test('authenticated user can create and delete a slack webhook channel', async ({ |
| 72 | + page, |
| 73 | + }) => { |
| 74 | + const nonce = Date.now(); |
| 75 | + const webhookName = 'PlaywrightTestCreateDeleteTest ' + nonce; |
| 76 | + const webhookUrl = |
| 77 | + 'https://hooks.slack.com/services/PLAYWRIGHT/TEST/' + nonce; |
| 78 | + |
| 79 | + const webhookPanel = page.locator( |
| 80 | + 'webstatus-notification-webhook-channels', |
| 81 | + ); |
| 82 | + |
| 83 | + // Don't assert that no webhook channels are configured. |
| 84 | + // There may be some from previous test runs or from manual testing. |
| 85 | + |
| 86 | + // Click Create button. |
| 87 | + const createButton = webhookPanel.getByRole('button', { |
| 88 | + name: 'Create Webhook channel', |
| 89 | + }); |
| 90 | + await expect(createButton).toBeVisible(); |
| 91 | + await createButton.click(); |
| 92 | + |
| 93 | + // Fill the dialog. |
| 94 | + const dialog = webhookPanel |
| 95 | + .locator('webstatus-manage-notification-channel-dialog') |
| 96 | + .locator('sl-dialog'); |
| 97 | + await expect(dialog).toBeVisible(); |
| 98 | + |
| 99 | + await dialog.getByRole('textbox', {name: 'Name'}).fill(webhookName); |
| 100 | + await dialog |
| 101 | + .getByRole('textbox', {name: 'Slack Webhook URL'}) |
| 102 | + .fill(webhookUrl); |
| 103 | + |
| 104 | + await dialog.getByRole('button', {name: 'Create', exact: true}).click(); |
| 105 | + |
| 106 | + // Verify it's in the list. |
| 107 | + await expect(dialog).not.toBeVisible(); |
| 108 | + const channelItem = webhookPanel.locator('.channel-item', { |
| 109 | + hasText: webhookName, |
| 110 | + }); |
| 111 | + await expect(channelItem).toBeVisible(); |
| 112 | + |
| 113 | + await channelItem.getByLabel('Delete').click(); |
| 114 | + |
| 115 | + const deleteDialog = webhookPanel.locator( |
| 116 | + 'sl-dialog[label="Delete Webhook Channel"]', |
| 117 | + ); |
| 118 | + await expect(deleteDialog).toBeVisible(); |
| 119 | + await deleteDialog |
| 120 | + .getByRole('button', {name: 'Delete', exact: true}) |
| 121 | + .click(); |
| 122 | + |
| 123 | + // Verify it's gone. |
| 124 | + await expect(channelItem).not.toBeVisible(); |
| 125 | + }); |
| 126 | + |
| 127 | + test('authenticated user can update a slack webhook channel', async ({ |
| 128 | + page, |
| 129 | + }) => { |
| 130 | + // Use a nonce to make sure we don't have any stale data from previous test runs. |
| 131 | + // Avoid using resetUserData() since it's an expensive operation. |
| 132 | + const nonce = Date.now(); |
| 133 | + const originalName = 'PlaywrightTestUpdateOriginal ' + nonce; |
| 134 | + const originalUrl = |
| 135 | + 'https://hooks.slack.com/services/PLAYWRIGHT/TEST/original-' + nonce; |
| 136 | + const updatedName = 'PlaywrightTestUpdateUpdated ' + nonce; |
| 137 | + const updatedUrl = |
| 138 | + 'https://hooks.slack.com/services/PLAYWRIGHT/TEST/updated-' + nonce; |
| 139 | + |
| 140 | + // Create a channel first. |
| 141 | + const webhookPanel = page.locator( |
| 142 | + 'webstatus-notification-webhook-channels', |
| 143 | + ); |
| 144 | + await page.waitForLoadState('networkidle'); |
| 145 | + await webhookPanel |
| 146 | + .getByRole('button', {name: 'Create Webhook channel'}) |
| 147 | + .click(); |
| 148 | + const dialog = webhookPanel |
| 149 | + .locator('webstatus-manage-notification-channel-dialog') |
| 150 | + .locator('sl-dialog'); |
| 151 | + await expect(dialog).toBeVisible({timeout: 10000}); |
| 152 | + await dialog.getByRole('textbox', {name: 'Name'}).fill(originalName); |
| 153 | + await dialog |
| 154 | + .getByRole('textbox', {name: 'Slack Webhook URL'}) |
| 155 | + .fill(originalUrl); |
| 156 | + await dialog.getByRole('button', {name: 'Create', exact: true}).click(); |
| 157 | + |
| 158 | + // Verify it was created. |
| 159 | + await expect(dialog).not.toBeVisible({timeout: 10000}); |
| 160 | + const originalItem = webhookPanel.locator('.channel-item', { |
| 161 | + hasText: originalName, |
| 162 | + }); |
| 163 | + await expect(originalItem).toBeVisible(); |
| 164 | + |
| 165 | + await originalItem.getByLabel('Edit').click(); |
| 166 | + |
| 167 | + // Verify current values in dialog. |
| 168 | + await expect(dialog).toBeVisible(); |
| 169 | + await expect(dialog.getByRole('textbox', {name: 'Name'})).toHaveValue( |
| 170 | + originalName, |
| 171 | + ); |
| 172 | + await expect( |
| 173 | + dialog.getByRole('textbox', {name: 'Slack Webhook URL'}), |
| 174 | + ).toHaveValue(originalUrl); |
| 175 | + |
| 176 | + // Update the values. |
| 177 | + await dialog.getByRole('textbox', {name: 'Name'}).fill(updatedName); |
| 178 | + await dialog |
| 179 | + .getByRole('textbox', {name: 'Slack Webhook URL'}) |
| 180 | + .fill(updatedUrl); |
| 181 | + |
| 182 | + await dialog.getByRole('button', {name: 'Save', exact: true}).click(); |
| 183 | + |
| 184 | + // Verify it was updated. |
| 185 | + await expect(dialog).not.toBeVisible({timeout: 10000}); |
| 186 | + const updatedItem = webhookPanel.locator('.channel-item', { |
| 187 | + hasText: updatedName, |
| 188 | + }); |
| 189 | + await expect(updatedItem).toBeVisible(); |
| 190 | + await expect(originalItem).not.toBeVisible(); |
| 191 | + |
| 192 | + const deleteButton = updatedItem.locator('sl-button[aria-label="Delete"]'); |
| 193 | + await expect(deleteButton).toBeVisible(); |
| 194 | + await deleteButton.click(); |
| 195 | + |
| 196 | + const deleteDialog = webhookPanel.locator( |
| 197 | + 'sl-dialog[label="Delete Webhook Channel"]', |
| 198 | + ); |
| 199 | + await expect(deleteDialog).toBeVisible(); |
| 200 | + await deleteDialog |
| 201 | + .getByRole('button', {name: 'Delete', exact: true}) |
| 202 | + .click(); |
| 203 | + await expect(updatedItem).not.toBeVisible(); |
| 204 | + }); |
74 | 205 | }); |
0 commit comments