# 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: workflows/complaint-lifecycle.spec.ts >> Complaint Lifecycle >> activate (self-assign) open complaint changes status to in_progress - Location: e2e/tests/workflows/complaint-lifecycle.spec.ts:96:7 # Error details ``` TypeError: Cannot read properties of undefined (reading 'email') ``` # Page snapshot ```yaml - generic [ref=e3]: - generic [ref=e4]: - img "HH Logo" [ref=e6] - heading "Welcome to PX360" [level=1] [ref=e7] - paragraph [ref=e8]: Patient Experience Management System - generic [ref=e10]: - generic [ref=e11]: - generic [ref=e12]: - img [ref=e13] - text: Email Address - generic [ref=e16]: - img [ref=e17] - textbox "Email Address" [active] [ref=e20]: - /placeholder: Enter your email - generic [ref=e21]: - generic [ref=e22]: - img [ref=e23] - text: Password - generic [ref=e26]: - img [ref=e27] - textbox "Password" [ref=e31]: - /placeholder: Enter your password - button [ref=e32] [cursor=pointer]: - img [ref=e33] - generic [ref=e36]: - generic [ref=e37] [cursor=pointer]: - checkbox "Remember me" [ref=e38] - generic [ref=e39]: Remember me - link "Forgot password?" [ref=e40] [cursor=pointer]: - /url: /accounts/password/reset/ - button "Sign In" [ref=e41] [cursor=pointer]: - img [ref=e42] - text: Sign In - generic [ref=e45]: - paragraph [ref=e46]: - text: Secure login powered by - link "tenhal.sa" [ref=e47] [cursor=pointer]: - /url: https://tenhal.sa - paragraph [ref=e48]: © 2026 Al Hammadi Hospital ``` # Test source ```ts 150 | export const ROLES: Record = { 151 | px_admin: { 152 | email: 'e2e-px-admin@px360.test', 153 | password: E2E_PASSWORD, 154 | groupName: 'PX Admin', 155 | hasHospital: false, 156 | canAccessConfig: true, 157 | canAccessAdmin: false, 158 | isSourceUser: false, 159 | }, 160 | hospital_admin: { 161 | email: 'e2e-hospital-admin@px360.test', 162 | password: E2E_PASSWORD, 163 | groupName: 'Hospital Admin', 164 | hasHospital: true, 165 | canAccessConfig: false, 166 | canAccessAdmin: false, 167 | isSourceUser: false, 168 | }, 169 | dept_manager: { 170 | email: 'e2e-dept-manager@px360.test', 171 | password: E2E_PASSWORD, 172 | groupName: 'Department Manager', 173 | hasHospital: true, 174 | canAccessConfig: false, 175 | canAccessAdmin: false, 176 | isSourceUser: false, 177 | }, 178 | px_employee: { 179 | email: 'e2e-px-employee@px360.test', 180 | password: E2E_PASSWORD, 181 | groupName: 'PX Employee', 182 | hasHospital: true, 183 | canAccessConfig: false, 184 | canAccessAdmin: false, 185 | isSourceUser: false, 186 | }, 187 | physician: { 188 | email: 'e2e-physician@px360.test', 189 | password: E2E_PASSWORD, 190 | groupName: 'Physician', 191 | hasHospital: true, 192 | canAccessConfig: false, 193 | canAccessAdmin: false, 194 | isSourceUser: false, 195 | }, 196 | nurse: { 197 | email: 'e2e-nurse@px360.test', 198 | password: E2E_PASSWORD, 199 | groupName: 'Nurse', 200 | hasHospital: true, 201 | canAccessConfig: false, 202 | canAccessAdmin: false, 203 | isSourceUser: false, 204 | }, 205 | staff: { 206 | email: 'e2e-staff@px360.test', 207 | password: E2E_PASSWORD, 208 | groupName: 'Staff', 209 | hasHospital: true, 210 | canAccessConfig: false, 211 | canAccessAdmin: false, 212 | isSourceUser: false, 213 | }, 214 | viewer: { 215 | email: 'e2e-viewer@px360.test', 216 | password: E2E_PASSWORD, 217 | groupName: 'Viewer', 218 | hasHospital: true, 219 | canAccessConfig: false, 220 | canAccessAdmin: false, 221 | isSourceUser: false, 222 | }, 223 | source_user: { 224 | email: 'e2e-source-user@px360.test', 225 | password: E2E_PASSWORD, 226 | groupName: 'PX Source User', 227 | hasHospital: true, 228 | canAccessConfig: false, 229 | canAccessAdmin: false, 230 | isSourceUser: true, 231 | }, 232 | champion: { 233 | email: 'e2e-champion@px360.test', 234 | password: E2E_PASSWORD, 235 | groupName: 'Champion', 236 | hasHospital: true, 237 | canAccessConfig: false, 238 | canAccessAdmin: false, 239 | isSourceUser: false, 240 | }, 241 | }; 242 | 243 | export class RoleAuthHelper { 244 | constructor(private page: Page) {} 245 | 246 | async login(role: RoleName) { 247 | const config = ROLES[role]; 248 | await this.page.goto('/accounts/login/'); 249 | await this.page.waitForSelector('#email'); > 250 | await this.page.fill('#email', config.email); | ^ TypeError: Cannot read properties of undefined (reading 'email') 251 | await this.page.fill('#password', config.password); 252 | await this.page.click('button[type="submit"]'); 253 | await this.page.waitForURL(/\/(?!accounts\/login)/, { timeout: 15000 }); 254 | await this.page.waitForLoadState('domcontentloaded'); 255 | } 256 | 257 | async loginAs(role: RoleName) { 258 | return this.login(role); 259 | } 260 | 261 | async logout() { 262 | await this.page.goto('/accounts/logout/'); 263 | await this.page.waitForURL(/\/accounts\/login\/?/, { timeout: 10000 }); 264 | } 265 | 266 | static config(role: RoleName): RoleConfig { 267 | return ROLES[role]; 268 | } 269 | } 270 | 271 | export async function submitContentForm(page: Page) { 272 | await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight)); 273 | await page.waitForTimeout(800); 274 | const formSelector = 'form:not([action*="logout"]):not([action*="login"])'; 275 | const formEl = page.locator(formSelector).first(); 276 | const count = await formEl.count(); 277 | if (count === 0) { 278 | const fallback = page.locator('form').last(); 279 | await fallback.evaluate((f: HTMLFormElement) => f.submit()); 280 | } else { 281 | await formEl.evaluate((f: HTMLFormElement) => f.submit()); 282 | } 283 | await page.waitForLoadState('domcontentloaded'); 284 | await page.waitForTimeout(3000); 285 | } 286 | ```