credential-vault.spec.ts 4.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. import { test, expect } from '@playwright/test'
  2. import { mkdirSync } from 'node:fs'
  3. test('a default installation creates and saves encrypted passwords through the settings UI', async ({ page }) => {
  4. const evidence='test-results/credential-vault-default';mkdirSync(evidence,{recursive:true})
  5. const master='DUMMY-browser-vault-master',secret='DUMMY-browser-entry-secret'
  6. await page.goto('/conversations')
  7. await page.getByRole('textbox',{name:'账号',exact:true}).fill('fixture')
  8. await page.getByRole('textbox',{name:'密码',exact:true}).fill('fixture-pass')
  9. await page.getByRole('button',{name:'登录',exact:true}).click()
  10. await page.locator('.desktop-sidebar .sidebar-account-switcher__main').click()
  11. await page.getByRole('menuitem',{name:'我的设置',exact:true}).click()
  12. await page.getByRole('button',{name:'密码管理',exact:true}).click()
  13. const panel=page.locator('.credential-vault')
  14. await expect(panel.getByText(/保存凭据无需配置独立服务/)).toBeVisible()
  15. await panel.getByLabel('主密码',{exact:true}).fill(master)
  16. await panel.getByLabel('确认主密码',{exact:true}).fill(master)
  17. await panel.getByRole('button',{name:'创建密码库',exact:true}).click()
  18. await expect(panel.getByRole('button',{name:'手动解锁 5 分钟',exact:true})).toBeVisible()
  19. await panel.getByLabel('主密码',{exact:true}).fill(master)
  20. await panel.getByRole('button',{name:'手动解锁 5 分钟',exact:true}).click()
  21. await panel.getByRole('button',{name:'添加凭据',exact:true}).click()
  22. await panel.getByLabel('名称',{exact:true}).fill('浏览器测试网站')
  23. await panel.getByLabel('用户名',{exact:true}).fill('dummy-user')
  24. await panel.getByLabel('准确网站 origin',{exact:true}).fill('https://example.test')
  25. await panel.getByLabel('密码',{exact:true}).fill(secret)
  26. await panel.getByRole('button',{name:'加密保存',exact:true}).click()
  27. await expect(panel.getByText('浏览器测试网站',{exact:true})).toBeVisible()
  28. await expect(panel.getByRole('status').filter({hasText:'凭据已加密保存'})).toBeVisible()
  29. await expect(panel.getByRole('button',{name:'授予本任务 60 秒引用权限'})).toHaveCount(0)
  30. expect(await panel.textContent()).not.toContain(secret)
  31. await panel.getByRole('button',{name:'添加凭据',exact:true}).click()
  32. await panel.getByRole('combobox',{name:/^用途/}).selectOption('ssh')
  33. await panel.getByRole('combobox',{name:/^SSH 认证方式/}).selectOption('password')
  34. await panel.getByLabel('名称',{exact:true}).fill('浏览器测试 SSH 密码')
  35. await panel.getByLabel('用户名',{exact:true}).fill('dummy-ssh-user')
  36. await panel.getByLabel('SSH 主机',{exact:true}).fill('ssh.example.test')
  37. await panel.getByLabel('已人工确认的 host key 指纹',{exact:true}).fill('SHA256:'+'A'.repeat(43))
  38. const sshPassword=panel.getByLabel(/^SSH 登录密码/)
  39. await expect(sshPassword).toHaveAttribute('type','password')
  40. await sshPassword.fill('DUMMY-browser-ssh-password')
  41. await expect(panel.getByLabel('私钥口令(可选)',{exact:true})).toHaveCount(0)
  42. await page.screenshot({path:evidence+'/ssh-password-editor.png'})
  43. await panel.getByRole('button',{name:'加密保存',exact:true}).click()
  44. const sshEntry=panel.locator('li').filter({hasText:'浏览器测试 SSH 密码'})
  45. await expect(sshEntry).toContainText('密码登录')
  46. expect(await panel.textContent()).not.toContain('DUMMY-browser-ssh-password')
  47. await sshEntry.getByRole('button',{name:'编辑',exact:true}).click()
  48. await expect(sshPassword).toHaveValue('')
  49. await expect(panel.getByRole('combobox',{name:/^SSH 认证方式/})).toHaveValue('password')
  50. await panel.getByRole('button',{name:'加密保存',exact:true}).click()
  51. await expect(sshEntry).toContainText('密码登录')
  52. await page.screenshot({path:evidence+'/desktop-saved.png'})
  53. await page.setViewportSize({width:375,height:812})
  54. await expect(panel.getByRole('button',{name:'添加凭据',exact:true})).toBeVisible()
  55. expect(await panel.evaluate(el=>el.scrollWidth<=el.clientWidth)).toBe(true)
  56. await page.screenshot({path:evidence+'/mobile-saved.png'})
  57. await page.setViewportSize({width:1440,height:1000})
  58. await panel.getByRole('button',{name:'立即锁定并撤销授权',exact:true}).click()
  59. await expect(panel.getByText('浏览器测试网站',{exact:true})).toHaveCount(0)
  60. await panel.getByLabel('主密码',{exact:true}).fill('DUMMY-wrong-master-password')
  61. await panel.getByRole('button',{name:'手动解锁 5 分钟',exact:true}).click()
  62. await expect(panel.getByRole('alert')).toContainText('主密码错误')
  63. await expect(page.getByRole('textbox',{name:'账号',exact:true})).toHaveCount(0)
  64. await expect(panel.getByLabel('主密码',{exact:true})).toHaveValue('')
  65. await page.screenshot({path:evidence+'/wrong-master-stays-signed-in.png'})
  66. })