test-wechat-follow-entry.mjs 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. import assert from 'node:assert/strict'
  2. import { readFileSync, existsSync } from 'node:fs'
  3. import { createRequire } from 'node:module'
  4. import test from 'node:test'
  5. const require = createRequire(new URL('../../web-admin/package.json', import.meta.url))
  6. const { ref } = require('vue')
  7. const { parse, compileTemplate } = require('@vue/compiler-sfc')
  8. const pageUrl = new URL('../pages/common/wechat-official-account.vue', import.meta.url)
  9. const read = (path) => readFileSync(new URL(path, import.meta.url), 'utf8')
  10. function source() {
  11. assert.ok(existsSync(pageUrl), '缺少服务号关注引导页')
  12. return readFileSync(pageUrl, 'utf8')
  13. }
  14. function page(profiles = []) {
  15. const { descriptor } = parse(source())
  16. const body = descriptor.scriptSetup.content.replace(/^import[^\n]+\n/gm, '')
  17. const calls = { toasts: [] }
  18. const uni = {
  19. showToast: (options) => calls.toasts.push(options)
  20. }
  21. const component = new Function('ref', 'uni', 'openWechatOfficialAccount', 'useWechatBinding', `${body}\nreturn {
  22. accountName,
  23. openAccountProfile, openingProfile, directOpenUnavailable
  24. }`)(ref, uni, (options) => profiles.push(options), () => ({}))
  25. return { ...component, calls }
  26. }
  27. test('workbench shortcut stays inside header at bottom right and has a registered route', () => {
  28. source()
  29. const workbench = read('../pages/workbench/workbench.vue')
  30. const header = workbench.slice(workbench.indexOf('<view class="mp-header mp-header--workbench"'), workbench.indexOf('<view class="mp-section">'))
  31. assert.ok(header.indexOf('关注服务号') > header.indexOf('退出登录'))
  32. assert.match(header, /@click="openOfficialAccount"/)
  33. assert.match(workbench, /\.mp-header__follow\s*\{[^}]*position:\s*absolute;[^}]*right:\s*32rpx;[^}]*bottom:\s*20rpx;/)
  34. assert.match(workbench, /background:\s*#d6a343/)
  35. assert.match(workbench, /openPage\(PAGE_PATHS\.wechatOfficialAccount\)/)
  36. assert.match(read('../config/api.js'), /wechatOfficialAccount:\s*'\/pages\/common\/wechat-official-account'/)
  37. assert.match(read('../pages.json'), /"path":\s*"pages\/common\/wechat-official-account"/)
  38. })
  39. test('guide covers all four notice types and compiles as a Vue template', () => {
  40. const content = source()
  41. for (const label of ['审批待办', '审批结果', '发放/支付完成', '证件到期提醒']) {
  42. assert.ok(content.includes(label), `未说明${label}`)
  43. }
  44. const { descriptor, errors } = parse(content)
  45. assert.deepEqual(errors, [])
  46. const result = compileTemplate({ source: descriptor.template.content, filename: 'wechat-official-account.vue',
  47. id: 'wechat-follow' })
  48. assert.deepEqual(result.errors, [])
  49. assert.match(content, /min-height:\s*44px/)
  50. })
  51. test('guide main action opens profile without copying and permits retry after failure', () => {
  52. const profiles = []
  53. const p = page(profiles)
  54. p.openAccountProfile()
  55. p.openAccountProfile()
  56. assert.equal(profiles.length, 1)
  57. assert.equal(p.openingProfile.value, true)
  58. profiles[0].onUnavailable()
  59. profiles[0].onComplete()
  60. assert.equal(p.directOpenUnavailable.value, true)
  61. assert.equal(p.openingProfile.value, false)
  62. p.openAccountProfile()
  63. assert.equal(profiles.length, 2)
  64. profiles[1].onComplete()
  65. assert.equal(p.calls.toasts.length, 0, '打开主页不显示关注成功')
  66. assert.match(source(), /@click="openAccountProfile"/)
  67. })