background-step11-payurl.test.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. const test = require('node:test');
  2. const assert = require('node:assert/strict');
  3. const fs = require('node:fs');
  4. function loadStep11(fetchImpl) {
  5. const source = fs.readFileSync('background/steps/get-plus-link.js', 'utf8');
  6. const scope = {};
  7. new Function('self', 'fetch', `${source}; return self.MultiPageBackgroundStep11;`)(scope, fetchImpl);
  8. return scope.MultiPageBackgroundStep11;
  9. }
  10. test('step 6 fetches ChatGPT session token and retries payurl checkout', async () => {
  11. const fetchCalls = [];
  12. const eventsOrder = [];
  13. const fetchImpl = async (url, options = {}) => {
  14. eventsOrder.push(`fetch:${url}`);
  15. fetchCalls.push({ url, options });
  16. if (url === 'https://chatgpt.com/api/auth/session') {
  17. return {
  18. ok: true,
  19. status: 200,
  20. text: async () => JSON.stringify({ accessToken: 'session-token' }),
  21. };
  22. }
  23. if (url === 'https://payurl.ark2.cn/api/checkout' && fetchCalls.filter((call) => call.url === url).length === 1) {
  24. return {
  25. ok: false,
  26. status: 502,
  27. text: async () => JSON.stringify({ error: 'temporary' }),
  28. };
  29. }
  30. if (url === 'https://payurl.ark2.cn/api/checkout') {
  31. return {
  32. ok: true,
  33. status: 200,
  34. text: async () => JSON.stringify({
  35. checkout_session_id: 'cs_test_123',
  36. url: 'https://pay.openai.com/c/pay/cs_test_123#token',
  37. chatgpt_checkout_url: 'https://chatgpt.com/checkout/openai_llc/cs_test_123',
  38. openai_payurl: 'https://pay.openai.com/c/pay/cs_test_123#token',
  39. }),
  40. };
  41. }
  42. throw new Error(`unexpected fetch: ${url}`);
  43. };
  44. const api = loadStep11(fetchImpl);
  45. const events = {
  46. logs: [],
  47. completed: null,
  48. navigatedUrl: '',
  49. };
  50. const executor = api.createStep11Executor({
  51. addLog: async (message, level = 'info') => events.logs.push({ message, level }),
  52. chrome: {
  53. scripting: {
  54. executeScript: async () => {
  55. throw new Error('page fallback should not be used when background session fetch succeeds');
  56. },
  57. },
  58. },
  59. completeStepFromBackground: async (step, payload) => {
  60. events.completed = { step, payload };
  61. },
  62. getTabId: async () => 123,
  63. reuseOrCreateTab: async (source, url) => {
  64. events.navigatedUrl = url;
  65. assert.equal(source, 'signup-page');
  66. },
  67. waitForTabStableComplete: async (tabId, options) => {
  68. eventsOrder.push('wait-stable');
  69. assert.equal(tabId, 123);
  70. assert.equal(options.stableMs, 1500);
  71. return { id: tabId, status: 'complete', url: 'https://chatgpt.com/' };
  72. },
  73. });
  74. await executor.executeStep11();
  75. const payurlCalls = fetchCalls.filter((call) => call.url === 'https://payurl.ark2.cn/api/checkout');
  76. assert.equal(payurlCalls.length, 2);
  77. assert.deepEqual(eventsOrder.slice(0, 2), [
  78. 'wait-stable',
  79. 'fetch:https://chatgpt.com/api/auth/session',
  80. ]);
  81. assert.equal(events.navigatedUrl, 'https://pay.openai.com/c/pay/cs_test_123#token');
  82. assert.deepEqual(events.completed, {
  83. step: 6,
  84. payload: {
  85. checkoutUrl: 'https://pay.openai.com/c/pay/cs_test_123#token',
  86. checkoutSessionId: 'cs_test_123',
  87. chatgptCheckoutUrl: 'https://chatgpt.com/checkout/openai_llc/cs_test_123',
  88. openaiPayUrl: 'https://pay.openai.com/c/pay/cs_test_123#token',
  89. },
  90. });
  91. const payload = JSON.parse(payurlCalls[1].options.body);
  92. assert.equal(payload.token, 'session-token');
  93. assert.equal(payload.plan, 'plus');
  94. assert.equal(payload.checkout_ui_mode, 'hosted');
  95. assert.equal(payload.promo_code, 'STRIPEATLASGPT4BIZ050126');
  96. assert.equal(payload.workspace_name, 'linux-do');
  97. assert.equal(payload.seat_quantity, 2);
  98. });