| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- const assert = require('assert');
- const http = require('http');
- const {
- startLoginFlowServer,
- stopLoginFlowServer
- } = require('../mcp/src/core/login-flow-server');
- async function body(req) {
- const chunks = [];
- for await (const chunk of req) chunks.push(chunk);
- if (!chunks.length) return {};
- return JSON.parse(Buffer.concat(chunks).toString('utf8'));
- }
- async function startGateway() {
- const requests = [];
- const server = http.createServer(async (req, res) => {
- const url = new URL(req.url, 'http://localhost');
- const input = await body(req);
- requests.push({ path: url.pathname, method: req.method, input, authorization: req.headers.authorization });
- let data;
- if (url.pathname === '/subscribe/status') {
- const quotedSeats = Number(url.searchParams.get('seats'));
- data = quotedSeats
- ? { subscribed: true, seats: 1, usedSeats: 1, quote: { seats: quotedSeats, amount: 125 } }
- : { subscribed: true, seats: 1, usedSeats: 1, price: 500 };
- } else if (url.pathname === '/login/accounts') {
- data = { seats: 1, usedSeats: 1, accounts: [{ id: `account_${'a'.repeat(40)}`, nickname: '原账号', corpName: '测试企业', online: false }] };
- } else if (url.pathname === '/login/status') {
- data = { configured: true, online: false, statusCode: -1 };
- } else if (url.pathname === '/login/select') {
- data = { selected: true, uid: input.uid, accountId: input.accountId, online: false };
- } else if (url.pathname === '/login/start') {
- data = { uid: input.newAccount ? 'qiwei-temporary-login' : input.uid, loginQrcodeBase64Data: Buffer.from('mock-png').toString('base64') };
- } else if (url.pathname === '/login/check') {
- data = {
- uid: input.uid,
- status: 2,
- detail: { corpId: 'corp-new', userId: 'user-new', nickname: '新账号' },
- decisionRequired: true,
- seats: 1,
- usedSeats: 1,
- account: { id: `account_${'b'.repeat(40)}`, nickname: '新账号' },
- accounts: [{ id: `account_${'a'.repeat(40)}`, nickname: '原账号' }],
- actions: ['purchase', 'replace', 'cancel']
- };
- } else if (url.pathname === '/login/resolve') {
- data = { resolved: true, action: input.action, cancelled: input.action === 'cancel' };
- } else if (url.pathname === '/subscribe') {
- data = { seats: input.seats, amount: input.expectedAmount, state: 'active' };
- } else {
- res.writeHead(404, { 'Content-Type': 'application/json' });
- res.end(JSON.stringify({ code: 404, mess: 'not found' }));
- return;
- }
- res.writeHead(200, { 'Content-Type': 'application/json' });
- res.end(JSON.stringify({ code: 200, data }));
- });
- await new Promise(resolve => server.listen(0, '127.0.0.1', resolve));
- return {
- apiBase: `http://127.0.0.1:${server.address().port}`,
- requests,
- close: () => new Promise(resolve => server.close(resolve))
- };
- }
- async function main() {
- const gateway = await startGateway();
- const port = 4397;
- try {
- const { url } = await startLoginFlowServer({
- token: 'sk-login-seat-smoke',
- apiBase: gateway.apiBase,
- uid: 'qiwei-client-one',
- port
- });
- const page = await fetch(url).then(res => res.text());
- const checkoutToken = JSON.parse(page.match(/const CHECKOUT_TOKEN = ("[^"]+")/)[1]);
- const origin = `http://127.0.0.1:${port}`;
- const state = await fetch(`${origin}/flow/state`).then(res => res.json());
- assert.strictEqual(state.subscribed, true);
- assert.strictEqual(state.accounts.length, 1);
- const select = await fetch(`${origin}/flow/select-account`, {
- method: 'POST', headers: { 'Content-Type': 'application/json', Origin: origin },
- body: JSON.stringify({ accountId: state.accounts[0].id })
- }).then(res => res.json());
- assert.strictEqual(select.selected, true);
- await fetch(`${origin}/flow/start-login`, {
- method: 'POST', headers: { 'Content-Type': 'application/json', Origin: origin },
- body: JSON.stringify({ newAccount: true })
- });
- const decision = await fetch(`${origin}/flow/check`).then(res => res.json());
- assert.strictEqual(decision.decisionRequired, true);
- assert.deepStrictEqual(decision.actions, ['purchase', 'replace', 'cancel']);
- const quote = await fetch(`${origin}/flow/upgrade-quote`).then(res => res.json());
- assert.strictEqual(quote.targetSeats, 2);
- assert.strictEqual(quote.quote.amount, 125);
- const cancel = await fetch(`${origin}/flow/resolve`, {
- method: 'POST', headers: { 'Content-Type': 'application/json', Origin: origin },
- body: JSON.stringify({ checkoutToken, action: 'cancel' })
- }).then(res => res.json());
- assert.strictEqual(cancel.cancelled, true);
- const refreshedPage = await fetch(origin).then(res => res.text());
- const upgradeToken = JSON.parse(refreshedPage.match(/const CHECKOUT_TOKEN = ("[^"]+")/)[1]);
- await fetch(`${origin}/flow/start-login`, {
- method: 'POST', headers: { 'Content-Type': 'application/json', Origin: origin },
- body: JSON.stringify({ newAccount: true })
- });
- await fetch(`${origin}/flow/check`);
- const upgraded = await fetch(`${origin}/flow/upgrade`, {
- method: 'POST', headers: { 'Content-Type': 'application/json', Origin: origin },
- body: JSON.stringify({ checkoutToken: upgradeToken, idempotencyKey: 'seat-upgrade-smoke-001' })
- }).then(res => res.json());
- assert.strictEqual(upgraded.resolved, true);
- assert(gateway.requests.some(request => request.path === '/subscribe' && request.input.expectedAmount === 125));
- assert(gateway.requests.some(request => request.path === '/login/resolve' && request.input.action === 'purchase'));
- const replacePage = await fetch(origin).then(res => res.text());
- const replaceToken = JSON.parse(replacePage.match(/const CHECKOUT_TOKEN = ("[^"]+")/)[1]);
- await fetch(`${origin}/flow/start-login`, {
- method: 'POST', headers: { 'Content-Type': 'application/json', Origin: origin },
- body: JSON.stringify({ newAccount: true })
- });
- await fetch(`${origin}/flow/check`);
- const replaced = await fetch(`${origin}/flow/resolve`, {
- method: 'POST', headers: { 'Content-Type': 'application/json', Origin: origin },
- body: JSON.stringify({ checkoutToken: replaceToken, action: 'replace', replaceAccountId: state.accounts[0].id })
- }).then(res => res.json());
- assert.strictEqual(replaced.resolved, true);
- assert(gateway.requests.some(request => request.path === '/login/resolve' && request.input.action === 'replace'));
- assert(gateway.requests.every(request => request.authorization === 'Bearer sk-login-seat-smoke'));
- console.log('[ok] account selection and purchase, replace, cancel seat decisions');
- } finally {
- stopLoginFlowServer();
- await gateway.close();
- }
- }
- main().catch(error => {
- console.error(error);
- process.exitCode = 1;
- });
|