feat(gopay): support GoPay Plus checkout flow
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
const test = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
|
||||
const source = fs.readFileSync('background/steps/gopay-approve.js', 'utf8');
|
||||
|
||||
function extractFunction(name) {
|
||||
const markers = [`async function ${name}(`, `function ${name}(`];
|
||||
const start = markers
|
||||
.map((marker) => source.indexOf(marker))
|
||||
.find((index) => index >= 0);
|
||||
if (start < 0) throw new Error(`missing function ${name}`);
|
||||
let parenDepth = 0;
|
||||
let signatureEnded = false;
|
||||
let braceStart = -1;
|
||||
for (let index = start; index < source.length; index += 1) {
|
||||
const ch = source[index];
|
||||
if (ch === '(') parenDepth += 1;
|
||||
if (ch === ')') {
|
||||
parenDepth -= 1;
|
||||
if (parenDepth === 0) signatureEnded = true;
|
||||
}
|
||||
if (ch === '{' && signatureEnded) {
|
||||
braceStart = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
let depth = 0;
|
||||
let end = braceStart;
|
||||
for (; end < source.length; end += 1) {
|
||||
const ch = source[end];
|
||||
if (ch === '{') depth += 1;
|
||||
if (ch === '}') {
|
||||
depth -= 1;
|
||||
if (depth === 0) {
|
||||
end += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return source.slice(start, end);
|
||||
}
|
||||
|
||||
test('GoPay OTP always requests manual confirmation even when a previous code exists', () => {
|
||||
const body = extractFunction('requestManualGoPayOtp');
|
||||
assert.doesNotMatch(body, /if\s*\(existingCode\)\s*\{\s*return existingCode;\s*\}/);
|
||||
assert.match(body, /requestGoPayOtpInput\(\{ code: existingCode \}\)/);
|
||||
assert.match(body, /检测到上次保存的 GoPay 验证码/);
|
||||
});
|
||||
|
||||
|
||||
test('GoPay approve handles final payment details iframe as an action frame', () => {
|
||||
assert.match(source, /GOPAY_PAYMENT_FRAME_URL_PATTERN/);
|
||||
assert.match(source, /payment\\\/details/);
|
||||
assert.match(source, /app\\\/challenge/);
|
||||
assert.match(source, /inspectGoPayFramesByDom/);
|
||||
assert.match(source, /getGoPayDomFramePriority/);
|
||||
assert.match(source, /paymentFrames/);
|
||||
assert.match(source, /frameState\?\.hasPayNowButton/);
|
||||
assert.match(source, /getGoPayDomFrameKind/);
|
||||
assert.match(source, /return 'payment'/);
|
||||
assert.match(source, /sendGoPayFrameCommand\(tabId, actionFrameId, 'GOPAY_CLICK_PAY_NOW'/);
|
||||
assert.match(source, /getGoPayDebuggerTargets/);
|
||||
assert.match(source, /chrome\.debugger\.getTargets/);
|
||||
assert.match(source, /targetId: picked\.targetId/);
|
||||
assert.match(source, /sendGoPayDebuggerTargetCommand\(actionTargetId, 'GOPAY_CLICK_PAY_NOW'/);
|
||||
assert.match(source, /sendGoPayDebuggerTargetCommand\(actionTargetId, 'GOPAY_SUBMIT_PIN'/);
|
||||
assert.match(source, /Input\.insertText/);
|
||||
assert.match(source, /最终 Bayar 确认/);
|
||||
});
|
||||
|
||||
test('GoPay approve treats merchant validate-pin iframe as PIN entry frame', () => {
|
||||
assert.match(source, /GOPAY_PIN_FRAME_URL_PATTERN/);
|
||||
assert.match(source, /payment\\\/validate-pin/);
|
||||
assert.match(source, /kind: 'pin'/);
|
||||
assert.match(source, /GOPAY_SUBMIT_PIN/);
|
||||
});
|
||||
|
||||
|
||||
test('GoPay approve closes terminal checkout but does not restart on top-level Pay now alone', () => {
|
||||
assert.match(source, /GOPAY_RESTART_FROM_STEP6::/);
|
||||
assert.match(source, /restartGoPayCheckoutFromStep6/);
|
||||
assert.match(source, /chrome\?\.tabs\?\.remove/);
|
||||
assert.match(source, /handleGoPayTerminalError\(pageState, tabId\)/);
|
||||
assert.match(source, /nextState\.hasTerminalError/);
|
||||
assert.doesNotMatch(source, /GoPay 顶层 Pay now 兜底点击后仍未进入下一步,当前支付会话需要重新创建/);
|
||||
});
|
||||
|
||||
test('GoPay approve falls back to clicking Bayar inside any iframe before top-level Pay now retry', () => {
|
||||
assert.match(source, /clickGoPayPayButtonInAnyFrame/);
|
||||
assert.match(source, /data-testid/);
|
||||
assert.match(source, /pay-button/);
|
||||
assert.match(source, /已在 GoPay iframe 中点击 Bayar 按钮/);
|
||||
assert.match(source, /不再自动回退步骤 6/);
|
||||
});
|
||||
|
||||
test('GoPay approve does not treat phone linking page as debugger iframe action', () => {
|
||||
assert.match(source, /type === 'tel'/);
|
||||
assert.match(source, /const hasContinueButton = !hasPayNowButton && !hasPhoneInput/);
|
||||
assert.match(source, /filter\(\(target\) => target\.type === 'iframe'\)/);
|
||||
});
|
||||
|
||||
|
||||
test('background auto-run routes GoPay restart sentinel back to step 6', () => {
|
||||
const backgroundSource = fs.readFileSync('background.js', 'utf8');
|
||||
assert.match(backgroundSource, /isGoPayCheckoutRestartRequiredFailure/);
|
||||
assert.match(backgroundSource, /GOPAY_RESTART_FROM_STEP6::/);
|
||||
assert.match(backgroundSource, /step === 8 && isGoPayCheckoutRestartRequiredFailure\(err\)/);
|
||||
assert.match(backgroundSource, /step = 6/);
|
||||
assert.match(backgroundSource, /invalidateDownstreamAfterStepRestart\(5/);
|
||||
});
|
||||
Reference in New Issue
Block a user