cloudflare-temp-email-provider.test.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. const test = require('node:test');
  2. const assert = require('node:assert/strict');
  3. const fs = require('fs');
  4. const source = fs.readFileSync('background.js', 'utf8');
  5. function extractFunction(name) {
  6. const markers = [`async function ${name}(`, `function ${name}(`];
  7. const start = markers
  8. .map((marker) => source.indexOf(marker))
  9. .find((index) => index >= 0);
  10. if (start < 0) {
  11. throw new Error(`missing function ${name}`);
  12. }
  13. let parenDepth = 0;
  14. let signatureEnded = false;
  15. let braceStart = -1;
  16. for (let i = start; i < source.length; i += 1) {
  17. const ch = source[i];
  18. if (ch === '(') {
  19. parenDepth += 1;
  20. } else if (ch === ')') {
  21. parenDepth -= 1;
  22. if (parenDepth === 0) {
  23. signatureEnded = true;
  24. }
  25. } else if (ch === '{' && signatureEnded) {
  26. braceStart = i;
  27. break;
  28. }
  29. }
  30. if (braceStart < 0) {
  31. throw new Error(`missing body for function ${name}`);
  32. }
  33. let depth = 0;
  34. let end = braceStart;
  35. for (; end < source.length; end += 1) {
  36. const ch = source[end];
  37. if (ch === '{') depth += 1;
  38. if (ch === '}') {
  39. depth -= 1;
  40. if (depth === 0) {
  41. end += 1;
  42. break;
  43. }
  44. }
  45. }
  46. return source.slice(start, end);
  47. }
  48. function createProviderApi(options = {}) {
  49. const {
  50. receiveMailbox = '',
  51. messages = [{
  52. id: 'mail-1',
  53. address: 'user@example.com',
  54. receivedDateTime: '2026-04-13T09:20:00.000Z',
  55. subject: 'OpenAI verification code',
  56. from: { emailAddress: { address: 'noreply@tm.openai.com' } },
  57. bodyPreview: 'Your verification code is 123456.',
  58. }],
  59. deleteShouldFail = false,
  60. } = options;
  61. const bundle = [
  62. extractFunction('isStopError'),
  63. extractFunction('throwIfStopped'),
  64. extractFunction('normalizeCloudflareTempEmailReceiveMailbox'),
  65. extractFunction('resolveCloudflareTempEmailPollTargetEmail'),
  66. extractFunction('summarizeCloudflareTempEmailMessagesForLog'),
  67. extractFunction('pollCloudflareTempEmailVerificationCode'),
  68. ].join('\n');
  69. return new Function('options', `
  70. let stopRequested = false;
  71. const STOP_ERROR_MESSAGE = '流程已被用户停止。';
  72. const CLOUDFLARE_TEMP_EMAIL_DEFAULT_PAGE_SIZE = 20;
  73. const logs = [];
  74. const listCalls = [];
  75. const messages = options.messages;
  76. function normalizeCloudflareTempEmailAddress(value) {
  77. return String(value || '').trim().toLowerCase();
  78. }
  79. async function addLog(message, level) {
  80. logs.push({ message, level });
  81. }
  82. async function sleepWithStop() {}
  83. function ensureCloudflareTempEmailConfig() {
  84. return { receiveMailbox: options.receiveMailbox };
  85. }
  86. async function listCloudflareTempEmailMessages(_state, config) {
  87. listCalls.push(config.address);
  88. return {
  89. config: {},
  90. messages,
  91. };
  92. }
  93. function pickVerificationMessageWithTimeFallback(currentMessages) {
  94. return {
  95. match: currentMessages[0]
  96. ? {
  97. code: String(currentMessages[0].bodyPreview).match(/(\\d{6})/)[1],
  98. receivedAt: Date.parse(currentMessages[0].receivedDateTime),
  99. message: currentMessages[0],
  100. }
  101. : null,
  102. usedRelaxedFilters: false,
  103. usedTimeFallback: false,
  104. };
  105. }
  106. async function deleteCloudflareTempEmailMail() {
  107. if (options.deleteShouldFail) {
  108. throw new Error('delete failed');
  109. }
  110. }
  111. ${bundle}
  112. return {
  113. pollCloudflareTempEmailVerificationCode,
  114. snapshot() {
  115. return { logs, listCalls };
  116. },
  117. };
  118. `)({
  119. ...options,
  120. receiveMailbox,
  121. messages,
  122. deleteShouldFail,
  123. });
  124. }
  125. test('pollCloudflareTempEmailVerificationCode returns code even if delete fails', async () => {
  126. const api = createProviderApi({ deleteShouldFail: true });
  127. const result = await api.pollCloudflareTempEmailVerificationCode(4, { email: 'user@example.com' }, {
  128. targetEmail: 'user@example.com',
  129. maxAttempts: 1,
  130. intervalMs: 1,
  131. });
  132. assert.equal(result.code, '123456');
  133. const state = api.snapshot();
  134. assert.equal(state.logs.some((entry) => entry.message.includes('删除 Cloudflare Temp Email 邮件失败')), true);
  135. assert.deepEqual(state.listCalls, ['user@example.com']);
  136. });
  137. test('pollCloudflareTempEmailVerificationCode requires target email or receive mailbox', async () => {
  138. const api = createProviderApi({ messages: [] });
  139. await assert.rejects(
  140. api.pollCloudflareTempEmailVerificationCode(4, {}, {}),
  141. /目标邮箱地址|邮件接收邮箱/
  142. );
  143. });
  144. test('pollCloudflareTempEmailVerificationCode prefers configured receive mailbox over registration email', async () => {
  145. const api = createProviderApi({
  146. receiveMailbox: 'forward-box@email.20021108.xyz',
  147. messages: [{
  148. id: 'mail-2',
  149. address: 'forward-box@email.20021108.xyz',
  150. receivedDateTime: '2026-04-13T10:20:00.000Z',
  151. subject: 'Login verification code',
  152. from: { emailAddress: { address: 'noreply@tm.openai.com' } },
  153. bodyPreview: 'Your verification code is 654321.',
  154. }],
  155. });
  156. const result = await api.pollCloudflareTempEmailVerificationCode(4, {
  157. email: 'duck-forwarded@duck.com',
  158. cloudflareTempEmailReceiveMailbox: 'forward-box@email.20021108.xyz',
  159. }, {
  160. targetEmail: 'duck-forwarded@duck.com',
  161. maxAttempts: 1,
  162. intervalMs: 1,
  163. });
  164. assert.equal(result.code, '654321');
  165. assert.deepEqual(api.snapshot().listCalls, ['forward-box@email.20021108.xyz']);
  166. });