activity-detail-login-gate.test.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. import test from 'node:test'
  2. import assert from 'node:assert/strict'
  3. import fs from 'node:fs'
  4. import path from 'node:path'
  5. import vm from 'node:vm'
  6. function scriptSetup (file) {
  7. return fs.readFileSync(path.resolve(file), 'utf8')
  8. .match(/<script setup[^>]*>([\s\S]*?)<\/script>/)[1]
  9. .replace(/^\s*import\s+.*$/gm, '')
  10. }
  11. function mountActivityCard () {
  12. const navigations = []
  13. const context = {
  14. ref: value => ({ value }),
  15. computed: getter => ({ get value () { return getter() } }),
  16. defineProps: () => ({ item: { id: 'activity-1' }, index: 0 }),
  17. useUserStore: () => ({}),
  18. useGlobalShare: () => ({ isLogin: () => false }),
  19. uni: { navigateTo: options => navigations.push(options) }
  20. }
  21. vm.runInNewContext(
  22. scriptSetup('components/pages/nonprofitActivety/index.vue') +
  23. '\nglobalThis.__card = { handleDetail }',
  24. context
  25. )
  26. return { card: context.__card, navigations }
  27. }
  28. function mountActivityDetail ({ loggedIn = false, storage = {} } = {}) {
  29. const lifecycle = {}
  30. const navigations = []
  31. const apiRequests = []
  32. const modals = []
  33. let loginChecks = 0
  34. const userStore = {
  35. token: '',
  36. openLoginModal () {}
  37. }
  38. const context = {
  39. ref: value => ({ value }),
  40. reactive: value => value,
  41. onMounted: () => {},
  42. nextTick: callback => callback(),
  43. watch: (getter, callback) => { lifecycle.watchToken = callback },
  44. onLoad: callback => { lifecycle.load = callback },
  45. onShareAppMessage: callback => { lifecycle.shareApp = callback },
  46. onShareTimeline: callback => { lifecycle.shareTimeline = callback },
  47. getCurrentInstance: () => ({
  48. proxy: {
  49. $api: {
  50. get: (url) => {
  51. apiRequests.push(url)
  52. return new Promise(() => {})
  53. }
  54. },
  55. $showModal: () => {},
  56. $showToast: () => {},
  57. $refs: {}
  58. }
  59. }),
  60. useUserStore: () => userStore,
  61. useGlobalShare: () => ({
  62. isLogin: () => {
  63. loginChecks++
  64. return loggedIn
  65. }
  66. }),
  67. uni: {
  68. getStorageSync: key => storage[key] || '',
  69. showModal: options => modals.push(options),
  70. showToast: () => {},
  71. navigateTo: options => navigations.push(options),
  72. reLaunch: options => navigations.push(options)
  73. },
  74. setTimeout: callback => callback(),
  75. Date,
  76. JSON,
  77. console
  78. }
  79. vm.runInNewContext(
  80. scriptSetup('pagesHome/activityDetail.vue') +
  81. '\nglobalThis.__detail = { handleReviewMembers, handleApply, handleCancel, handleSignup, handleFill, showShareOptions, share }',
  82. context
  83. )
  84. return { detail: context.__detail, lifecycle, navigations, apiRequests, modals, getLoginChecks: () => loginChecks }
  85. }
  86. async function loadAuthSession () {
  87. const source = fs.readFileSync(path.resolve('common/utils/auth-session.js'), 'utf8')
  88. return import(`data:text/javascript;base64,${Buffer.from(source).toString('base64')}`)
  89. }
  90. test('未登录用户点击首页活动直接进入详情', () => {
  91. const { card, navigations } = mountActivityCard()
  92. card.handleDetail({ id: 'activity-1' })
  93. assert.equal(navigations.length, 1)
  94. assert.equal(navigations[0].url, '/pagesHome/activityDetail?id=activity-1')
  95. })
  96. test('未登录进入详情时直接加载活动且不自动弹登录框', () => {
  97. const { lifecycle, apiRequests, modals } = mountActivityDetail()
  98. lifecycle.load({ id: 'activity-1' })
  99. assert.deepEqual(apiRequests, ['/core/activity/activity-1'])
  100. assert.equal(modals.length, 0)
  101. })
  102. test('未登录点击身份相关操作时中止操作并触发登录判断', () => {
  103. const { detail, navigations, getLoginChecks } = mountActivityDetail({ loggedIn: false })
  104. detail.handleReviewMembers()
  105. detail.handleApply()
  106. detail.handleCancel()
  107. detail.handleSignup()
  108. detail.handleFill()
  109. detail.showShareOptions()
  110. assert.equal(navigations.length, 0)
  111. assert.equal(detail.share.value, false)
  112. assert.equal(getLoginChecks(), 6)
  113. })
  114. test('已登录点击身份相关操作时继续执行原操作', async () => {
  115. const { detail, navigations, getLoginChecks } = mountActivityDetail({ loggedIn: true })
  116. detail.handleReviewMembers()
  117. await detail.handleApply()
  118. detail.handleCancel()
  119. detail.handleSignup()
  120. detail.handleFill()
  121. detail.showShareOptions()
  122. assert.equal(navigations.length, 5)
  123. assert.equal(detail.share.value, true)
  124. assert.equal(getLoginChecks(), 6)
  125. })
  126. test('登录完成后重新获取当前活动详情', () => {
  127. const { lifecycle, apiRequests } = mountActivityDetail()
  128. lifecycle.load({ id: 'activity-1' })
  129. lifecycle.watchToken('', 'old-token')
  130. lifecycle.watchToken('new-token', '')
  131. assert.deepEqual(apiRequests, [
  132. '/core/activity/activity-1',
  133. '/core/activity/activity-1'
  134. ])
  135. })
  136. test('未登录浏览详情时原生分享回调不会因缺少用户信息报错', () => {
  137. const { lifecycle } = mountActivityDetail()
  138. const appShare = lifecycle.shareApp({ from: 'menu' })
  139. const timelineShare = lifecycle.shareTimeline()
  140. assert.match(appShare.path, /^\/pagesHome\/activityDetail\?shareADId=/)
  141. assert.match(timelineShare.query, /^shareADId=/)
  142. })
  143. test('登录态同时校验 token 和过期时间', async () => {
  144. const { hasValidSession } = await loadAuthSession()
  145. const now = 1000
  146. const storage = values => ({ getStorageSync: key => values[key] || '' })
  147. assert.equal(hasValidSession(storage({ token: 'token', expaireTime: 1001 }), now), true)
  148. assert.equal(hasValidSession(storage({ token: 'token', expaireTime: 999 }), now), false)
  149. assert.equal(hasValidSession(storage({ expaireTime: 1001 }), now), false)
  150. })