verification-flow-polling.test.js 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. const test = require('node:test');
  2. const assert = require('node:assert/strict');
  3. const fs = require('node:fs');
  4. const source = fs.readFileSync('background/verification-flow.js', 'utf8');
  5. const globalScope = {};
  6. const api = new Function('self', `${source}; return self.MultiPageBackgroundVerificationFlow;`)(globalScope);
  7. test('verification flow extends 2925 polling window', () => {
  8. const helpers = api.createVerificationFlowHelpers({
  9. addLog: async () => {},
  10. chrome: { tabs: { update: async () => {} } },
  11. CLOUDFLARE_TEMP_EMAIL_PROVIDER: 'cloudflare-temp-email',
  12. completeStepFromBackground: async () => {},
  13. confirmCustomVerificationStepBypassRequest: async () => ({ confirmed: true }),
  14. getHotmailVerificationPollConfig: () => ({}),
  15. getHotmailVerificationRequestTimestamp: () => 0,
  16. getState: async () => ({}),
  17. getTabId: async () => 1,
  18. HOTMAIL_PROVIDER: 'hotmail-api',
  19. isStopError: () => false,
  20. LUCKMAIL_PROVIDER: 'luckmail-api',
  21. MAIL_2925_VERIFICATION_INTERVAL_MS: 15000,
  22. MAIL_2925_VERIFICATION_MAX_ATTEMPTS: 15,
  23. pollCloudflareTempEmailVerificationCode: async () => ({}),
  24. pollHotmailVerificationCode: async () => ({}),
  25. pollLuckmailVerificationCode: async () => ({}),
  26. sendToContentScript: async () => ({}),
  27. sendToMailContentScriptResilient: async () => ({}),
  28. setState: async () => {},
  29. setStepStatus: async () => {},
  30. sleepWithStop: async () => {},
  31. throwIfStopped: () => {},
  32. VERIFICATION_POLL_MAX_ROUNDS: 5,
  33. });
  34. const step4Payload = helpers.getVerificationPollPayload(4, { email: 'user@example.com', mailProvider: '2925' });
  35. const step7Payload = helpers.getVerificationPollPayload(7, { email: 'user@example.com', mailProvider: '2925' });
  36. assert.equal(step4Payload.maxAttempts, 15);
  37. assert.equal(step4Payload.intervalMs, 15000);
  38. assert.equal(step7Payload.maxAttempts, 15);
  39. assert.equal(step7Payload.intervalMs, 15000);
  40. });
  41. test('verification flow runs beforeSubmit hook before filling the code', async () => {
  42. const events = [];
  43. const helpers = api.createVerificationFlowHelpers({
  44. addLog: async () => {},
  45. chrome: {
  46. tabs: {
  47. update: async () => {},
  48. },
  49. },
  50. CLOUDFLARE_TEMP_EMAIL_PROVIDER: 'cloudflare-temp-email',
  51. completeStepFromBackground: async (_step, payload) => {
  52. events.push(['complete', payload.code]);
  53. },
  54. confirmCustomVerificationStepBypassRequest: async () => ({ confirmed: true }),
  55. getHotmailVerificationPollConfig: () => ({}),
  56. getHotmailVerificationRequestTimestamp: () => 0,
  57. getState: async () => ({}),
  58. getTabId: async () => 1,
  59. HOTMAIL_PROVIDER: 'hotmail-api',
  60. isStopError: () => false,
  61. LUCKMAIL_PROVIDER: 'luckmail-api',
  62. MAIL_2925_VERIFICATION_INTERVAL_MS: 15000,
  63. MAIL_2925_VERIFICATION_MAX_ATTEMPTS: 15,
  64. pollCloudflareTempEmailVerificationCode: async () => ({}),
  65. pollHotmailVerificationCode: async () => ({}),
  66. pollLuckmailVerificationCode: async () => ({}),
  67. sendToContentScript: async (_source, message) => {
  68. if (message.type === 'FILL_CODE') {
  69. events.push(['submit', message.payload.code]);
  70. return {};
  71. }
  72. return {};
  73. },
  74. sendToMailContentScriptResilient: async () => ({
  75. code: '654321',
  76. emailTimestamp: 123,
  77. }),
  78. setState: async (payload) => {
  79. events.push(['state', payload.lastLoginCode || payload.lastSignupCode]);
  80. },
  81. setStepStatus: async () => {},
  82. sleepWithStop: async () => {},
  83. throwIfStopped: () => {},
  84. VERIFICATION_POLL_MAX_ROUNDS: 5,
  85. });
  86. await helpers.resolveVerificationStep(
  87. 7,
  88. { email: 'user@example.com', lastLoginCode: null },
  89. { provider: 'qq', label: 'QQ 邮箱' },
  90. {
  91. beforeSubmit: async (result) => {
  92. events.push(['beforeSubmit', result.code]);
  93. },
  94. }
  95. );
  96. assert.deepStrictEqual(events, [
  97. ['beforeSubmit', '654321'],
  98. ['submit', '654321'],
  99. ['state', '654321'],
  100. ['complete', '654321'],
  101. ]);
  102. });
  103. test('verification flow keeps Hotmail request timestamp filtering on the first poll', async () => {
  104. const pollPayloads = [];
  105. const helpers = api.createVerificationFlowHelpers({
  106. addLog: async () => {},
  107. chrome: { tabs: { update: async () => {} } },
  108. CLOUDFLARE_TEMP_EMAIL_PROVIDER: 'cloudflare-temp-email',
  109. completeStepFromBackground: async () => {},
  110. confirmCustomVerificationStepBypassRequest: async () => ({ confirmed: true }),
  111. getHotmailVerificationPollConfig: () => ({}),
  112. getHotmailVerificationRequestTimestamp: () => 87654,
  113. getState: async () => ({}),
  114. getTabId: async () => 1,
  115. HOTMAIL_PROVIDER: 'hotmail-api',
  116. isStopError: () => false,
  117. LUCKMAIL_PROVIDER: 'luckmail-api',
  118. MAIL_2925_VERIFICATION_INTERVAL_MS: 15000,
  119. MAIL_2925_VERIFICATION_MAX_ATTEMPTS: 15,
  120. pollCloudflareTempEmailVerificationCode: async () => ({}),
  121. pollHotmailVerificationCode: async (_step, _state, payload) => {
  122. pollPayloads.push(payload);
  123. return { code: '654321', emailTimestamp: 123 };
  124. },
  125. pollLuckmailVerificationCode: async () => ({}),
  126. sendToContentScript: async (_source, message) => {
  127. if (message.type === 'FILL_CODE') {
  128. return {};
  129. }
  130. return {};
  131. },
  132. sendToMailContentScriptResilient: async () => ({}),
  133. setState: async () => {},
  134. setStepStatus: async () => {},
  135. sleepWithStop: async () => {},
  136. throwIfStopped: () => {},
  137. VERIFICATION_POLL_MAX_ROUNDS: 5,
  138. });
  139. await helpers.resolveVerificationStep(
  140. 7,
  141. {
  142. email: 'user@example.com',
  143. loginVerificationRequestedAt: 100000,
  144. lastLoginCode: null,
  145. },
  146. { provider: 'hotmail-api', label: 'Hotmail' },
  147. {}
  148. );
  149. assert.equal(pollPayloads.length, 1);
  150. assert.equal(pollPayloads[0].filterAfterTimestamp, 87654);
  151. });
  152. test('verification flow refreshes Hotmail signup filter timestamp after step 4 resend', async () => {
  153. const pollPayloads = [];
  154. const realDateNow = Date.now;
  155. Date.now = () => 200000;
  156. let submitCount = 0;
  157. const helpers = api.createVerificationFlowHelpers({
  158. addLog: async () => {},
  159. chrome: { tabs: { update: async () => {} } },
  160. CLOUDFLARE_TEMP_EMAIL_PROVIDER: 'cloudflare-temp-email',
  161. completeStepFromBackground: async () => {},
  162. confirmCustomVerificationStepBypassRequest: async () => ({ confirmed: true }),
  163. getHotmailVerificationPollConfig: () => ({}),
  164. getHotmailVerificationRequestTimestamp: (_step, state) => Math.max(0, Number(state.signupVerificationRequestedAt || 0) - 15000),
  165. getState: async () => ({}),
  166. getTabId: async () => 1,
  167. HOTMAIL_PROVIDER: 'hotmail-api',
  168. isStopError: () => false,
  169. LUCKMAIL_PROVIDER: 'luckmail-api',
  170. MAIL_2925_VERIFICATION_INTERVAL_MS: 15000,
  171. MAIL_2925_VERIFICATION_MAX_ATTEMPTS: 15,
  172. pollCloudflareTempEmailVerificationCode: async () => ({}),
  173. pollHotmailVerificationCode: async (_step, _state, payload) => {
  174. pollPayloads.push(payload);
  175. return {
  176. code: pollPayloads.length === 1 ? '111111' : '222222',
  177. emailTimestamp: pollPayloads.length,
  178. };
  179. },
  180. pollLuckmailVerificationCode: async () => ({}),
  181. sendToContentScript: async (_source, message) => {
  182. if (message.type === 'FILL_CODE') {
  183. submitCount += 1;
  184. return submitCount === 1
  185. ? { invalidCode: true, errorText: '旧验证码' }
  186. : {};
  187. }
  188. if (message.type === 'RESEND_VERIFICATION_CODE') {
  189. return {};
  190. }
  191. return {};
  192. },
  193. sendToMailContentScriptResilient: async () => ({}),
  194. setState: async () => {},
  195. setStepStatus: async () => {},
  196. sleepWithStop: async () => {},
  197. throwIfStopped: () => {},
  198. VERIFICATION_POLL_MAX_ROUNDS: 5,
  199. });
  200. try {
  201. await helpers.resolveVerificationStep(
  202. 4,
  203. {
  204. email: 'user@example.com',
  205. signupVerificationRequestedAt: 100000,
  206. lastSignupCode: null,
  207. },
  208. { provider: 'hotmail-api', label: 'Hotmail' },
  209. {}
  210. );
  211. } finally {
  212. Date.now = realDateNow;
  213. }
  214. assert.equal(pollPayloads.length, 2);
  215. assert.equal(pollPayloads[0].filterAfterTimestamp, 85000);
  216. assert.equal(pollPayloads[1].filterAfterTimestamp, 185000);
  217. });