Skip to content

Commit 0b3b48f

Browse files
committed
refactor: replace legacy share fragment logic with shareRouteForTarget and add comprehensive form submission e2e tests
1 parent 8e63e7f commit 0b3b48f

4 files changed

Lines changed: 243 additions & 102 deletions

File tree

test/e2e/proxy.test.js

Lines changed: 130 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1876,8 +1876,8 @@ test('browser traffic uses internal SOCKS5 mode and covers proxied runtime integ
18761876
}
18771877
return last;
18781878
})();
1879-
assert.match(rawDynamicRelativeLink && rawDynamicRelativeLink.href || '', /^\/zp\/p\//);
1880-
assert.match(rawDynamicRelativeLink && rawDynamicRelativeLink.href || '', /#k=/);
1879+
assert.match((rawDynamicRelativeLink && rawDynamicRelativeLink.href) || '', /^\/zp\/p\//);
1880+
assert.match((rawDynamicRelativeLink && rawDynamicRelativeLink.href) || '', /#k=/);
18811881
assert.equal(
18821882
rawDynamicRelativeLink && rawDynamicRelativeLink['data-zp-target-url'],
18831883
`http://${targetHost}:${targetPort}/next`,
@@ -3477,6 +3477,122 @@ test('browser traffic uses internal SOCKS5 mode and covers proxied runtime integ
34773477
assert.match(multipartForm.echo.contentType, /^multipart\/form-data; boundary=/);
34783478
assert.match(multipartForm.echo.body, /name="upload"; filename="hello.txt"/);
34793479
assert.match(multipartForm.echo.body, /file-body/);
3480+
const preventedForm = await page.evaluate(
3481+
() =>
3482+
new Promise((resolve) => {
3483+
const before = location.href;
3484+
const f = document.createElement('form');
3485+
f.method = 'POST';
3486+
f.action = '/form-echo?kind=prevented';
3487+
const input = document.createElement('input');
3488+
input.name = 'alpha';
3489+
input.value = 'blocked';
3490+
f.appendChild(input);
3491+
const button = document.createElement('button');
3492+
button.type = 'submit';
3493+
f.appendChild(button);
3494+
f.addEventListener('submit', (ev) => ev.preventDefault());
3495+
document.body.appendChild(f);
3496+
f.requestSubmit(button);
3497+
setTimeout(() => resolve({ before, after: location.href }), 100);
3498+
}),
3499+
);
3500+
assert.equal(preventedForm.after, preventedForm.before);
3501+
await page.evaluate(() => {
3502+
const f = document.createElement('form');
3503+
f.method = 'POST';
3504+
f.action = '/form-echo?kind=script-post-wrong';
3505+
const input = document.createElement('input');
3506+
input.name = 'alpha';
3507+
input.value = 'one';
3508+
f.appendChild(input);
3509+
const button = document.createElement('button');
3510+
button.type = 'submit';
3511+
button.name = 'submitter';
3512+
button.value = 'script-post';
3513+
f.appendChild(button);
3514+
f.addEventListener('submit', () => {
3515+
f.action = '/form-echo?kind=script-post';
3516+
input.value = 'two';
3517+
});
3518+
document.body.appendChild(f);
3519+
f.requestSubmit(button);
3520+
});
3521+
await waitForPage(page, () => window.__formEcho && window.__formEcho.kind === 'script-post');
3522+
const scriptPostForm = await page.evaluate(() => window.__formEcho);
3523+
assert.equal(scriptPostForm.method, 'POST');
3524+
assert.equal(scriptPostForm.body, 'alpha=two&submitter=script-post');
3525+
await page.evaluate(() => {
3526+
const f = document.createElement('form');
3527+
f.method = 'POST';
3528+
f.action = '/form-echo?kind=formdata';
3529+
const input = document.createElement('input');
3530+
input.name = 'alpha';
3531+
input.value = 'one';
3532+
f.appendChild(input);
3533+
const button = document.createElement('button');
3534+
button.type = 'submit';
3535+
button.name = 'submitter';
3536+
button.value = 'formdata';
3537+
f.appendChild(button);
3538+
f.addEventListener('formdata', (ev) => {
3539+
ev.formData.set('alpha', 'from-formdata');
3540+
ev.formData.append('beta', 'two');
3541+
});
3542+
document.body.appendChild(f);
3543+
f.requestSubmit(button);
3544+
});
3545+
await waitForPage(page, () => window.__formEcho && window.__formEcho.kind === 'formdata');
3546+
const formdataForm = await page.evaluate(() => window.__formEcho);
3547+
assert.equal(formdataForm.body, 'alpha=from-formdata&submitter=formdata&beta=two');
3548+
await page.evaluate(() => {
3549+
const f = document.createElement('form');
3550+
f.method = 'POST';
3551+
f.action = '/form-echo?kind=form-submit';
3552+
const input = document.createElement('input');
3553+
input.name = 'alpha';
3554+
input.value = 'one';
3555+
f.appendChild(input);
3556+
f.addEventListener('submit', () => {
3557+
const marker = document.createElement('input');
3558+
marker.name = 'submitEvent';
3559+
marker.value = 'fired';
3560+
f.appendChild(marker);
3561+
});
3562+
f.addEventListener('formdata', (ev) => {
3563+
ev.formData.append('formdata', 'yes');
3564+
});
3565+
document.body.appendChild(f);
3566+
f.submit();
3567+
});
3568+
await waitForPage(page, () => window.__formEcho && window.__formEcho.kind === 'form-submit');
3569+
const formSubmitForm = await page.evaluate(() => window.__formEcho);
3570+
assert.equal(formSubmitForm.body, 'alpha=one&formdata=yes');
3571+
await page.evaluate(() => {
3572+
const f = document.createElement('form');
3573+
f.method = 'GET';
3574+
f.action = '/form-echo';
3575+
for (const [name, value] of [
3576+
['kind', 'get-native'],
3577+
['alpha', 'one'],
3578+
]) {
3579+
const input = document.createElement('input');
3580+
input.name = name;
3581+
input.value = value;
3582+
f.appendChild(input);
3583+
}
3584+
const button = document.createElement('button');
3585+
button.type = 'submit';
3586+
button.name = 'submitter';
3587+
button.value = 'get-native';
3588+
f.appendChild(button);
3589+
document.body.appendChild(f);
3590+
f.requestSubmit(button);
3591+
});
3592+
await waitForPage(page, () => window.__formEcho && window.__formEcho.kind === 'get-native');
3593+
const getForm = await page.evaluate(() => window.__formEcho);
3594+
assert.equal(getForm.method, 'GET');
3595+
assert.equal(getForm.body, '');
34803596
const rawAfterSubmit = page.url();
34813597
const rawKey = new URL(rawAfterSubmit).hash
34823598
? new URLSearchParams(new URL(rawAfterSubmit).hash.slice(1)).get('k')
@@ -3514,6 +3630,18 @@ test('browser traffic uses internal SOCKS5 mode and covers proxied runtime integ
35143630
),
35153631
`target requests: ${JSON.stringify(requests)}`,
35163632
);
3633+
assert.ok(
3634+
requests.some(
3635+
(r) =>
3636+
r.url.startsWith('/form-echo?kind=script-post') &&
3637+
r.contentType.startsWith('application/x-www-form-urlencoded'),
3638+
),
3639+
`target requests: ${JSON.stringify(requests)}`,
3640+
);
3641+
assert.ok(
3642+
requests.some((r) => r.url === '/form-echo?kind=get-native&alpha=one&submitter=get-native'),
3643+
`target requests: ${JSON.stringify(requests)}`,
3644+
);
35173645
await page.click('#next');
35183646
await waitForPage(page, () => document.title === 'E2E Next');
35193647
const next = await page.evaluate(() => ({

test/js/static-policy.test.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,6 @@ test('runtime installs required escape-vector hooks', () => {
148148
for (const needle of [
149149
"document.addEventListener('click'",
150150
"root.addEventListener('click'",
151-
"document.addEventListener('submit'",
152151
'HTMLFormElement.prototype',
153152
'popstate',
154153
'ZP_RESOLVE_ENTRY',
@@ -250,8 +249,8 @@ test('runtime installs required escape-vector hooks', () => {
250249
'rewriteEventAttribute',
251250
'enforceSubtreePolicies',
252251
'installTargetServiceWorkerBlocker',
253-
'formRequestBody',
254-
'shareFragmentForKey',
252+
'shareRouteForTarget',
253+
'makeShareURL',
255254
'postMessageWrapperFor',
256255
'frameSandboxAllowsEscape',
257256
'setFrameSandboxAttribute',
@@ -260,6 +259,7 @@ test('runtime installs required escape-vector hooks', () => {
260259
"Reflect, 'getPrototypeOf'",
261260
])
262261
assert.ok(rt.includes(needle), `missing ${needle}`);
262+
assert.equal(rt.includes("document.addEventListener('submit'"), false);
263263
for (const needle of [
264264
'makeWorkerLocationFacade',
265265
"Object.defineProperty(self, 'location'",

0 commit comments

Comments
 (0)