























@@ -679,6 +679,7 @@ export async function selectOptionViaPlaywright(opts: {
679679selector?: string;
680680values: string[];
681681timeoutMs?: number;
682+ssrfPolicy?: SsrFPolicy;
682683}): Promise<void> {
683684const resolved = requireRefOrSelector(opts.ref, opts.selector);
684685if (!opts.values?.length) {
@@ -689,9 +690,19 @@ export async function selectOptionViaPlaywright(opts: {
689690const locator = resolved.ref
690691 ? refLocator(page, requireRef(resolved.ref))
691692 : page.locator(resolved.selector!);
693+const previousUrl = page.url();
692694try {
693-await locator.selectOption(opts.values, {
694-timeout: resolveInteractionTimeoutMs(opts.timeoutMs),
695+await assertInteractionNavigationCompletedSafely({
696+action: async () => {
697+await locator.selectOption(opts.values, {
698+timeout: resolveInteractionTimeoutMs(opts.timeoutMs),
699+});
700+},
701+cdpUrl: opts.cdpUrl,
702+ page,
703+ previousUrl,
704+ssrfPolicy: opts.ssrfPolicy,
705+targetId: opts.targetId,
695706});
696707} catch (err) {
697708throw toAIFriendlyError(err, label);
@@ -746,17 +757,29 @@ export async function typeViaPlaywright(opts: {
746757 : page.locator(resolved.selector!);
747758const timeout = resolveInteractionTimeoutMs(opts.timeoutMs);
748759try {
760+const previousUrl = page.url();
749761if (opts.slowly) {
750-await locator.click({ timeout });
751-await locator.type(text, { timeout, delay: 75 });
762+await assertInteractionNavigationCompletedSafely({
763+action: async () => {
764+await locator.click({ timeout });
765+await locator.type(text, { timeout, delay: 75 });
766+if (opts.submit) {
767+await locator.press("Enter", { timeout });
768+}
769+},
770+cdpUrl: opts.cdpUrl,
771+ page,
772+ previousUrl,
773+ssrfPolicy: opts.ssrfPolicy,
774+targetId: opts.targetId,
775+});
752776} else {
753-await locator.fill(text, { timeout });
754-}
755-if (opts.submit) {
756-const previousUrl = page.url();
757777await assertInteractionNavigationCompletedSafely({
758778action: async () => {
759-await locator.press("Enter", { timeout });
779+await locator.fill(text, { timeout });
780+if (opts.submit) {
781+await locator.press("Enter", { timeout });
782+}
760783},
761784cdpUrl: opts.cdpUrl,
762785 page,
@@ -775,6 +798,7 @@ export async function fillFormViaPlaywright(opts: {
775798targetId?: string;
776799fields: BrowserFormField[];
777800timeoutMs?: number;
801+ssrfPolicy?: SsrFPolicy;
778802}): Promise<void> {
779803const page = await getRestoredPageForTarget(opts);
780804const timeout = resolveInteractionTimeoutMs(opts.timeoutMs);
@@ -796,14 +820,34 @@ export async function fillFormViaPlaywright(opts: {
796820const checked =
797821rawValue === true || rawValue === 1 || rawValue === "1" || rawValue === "true";
798822try {
799-await locator.setChecked(checked, { timeout });
823+const previousUrl = page.url();
824+await assertInteractionNavigationCompletedSafely({
825+action: async () => {
826+await locator.setChecked(checked, { timeout });
827+},
828+cdpUrl: opts.cdpUrl,
829+ page,
830+ previousUrl,
831+ssrfPolicy: opts.ssrfPolicy,
832+targetId: opts.targetId,
833+});
800834} catch (err) {
801835throw toAIFriendlyError(err, ref);
802836}
803837continue;
804838}
805839try {
806-await locator.fill(value, { timeout });
840+const previousUrl = page.url();
841+await assertInteractionNavigationCompletedSafely({
842+action: async () => {
843+await locator.fill(value, { timeout });
844+},
845+cdpUrl: opts.cdpUrl,
846+ page,
847+ previousUrl,
848+ssrfPolicy: opts.ssrfPolicy,
849+targetId: opts.targetId,
850+});
807851} catch (err) {
808852throw toAIFriendlyError(err, ref);
809853}
@@ -850,9 +894,19 @@ export async function evaluateViaPlaywright(opts: {
850894}
851895852896try {
897+const previousUrl = page.url();
898+if (opts.ssrfPolicy) {
899+await assertPageNavigationCompletedSafely({
900+cdpUrl: opts.cdpUrl,
901+ page,
902+response: null,
903+ssrfPolicy: opts.ssrfPolicy,
904+targetId: opts.targetId,
905+});
906+}
907+853908if (opts.ref) {
854909const locator = refLocator(page, opts.ref);
855-const previousUrl = page.url();
856910// eslint-disable-next-line @typescript-eslint/no-implied-eval -- required for browser-context eval
857911const elementEvaluator = new Function(
858912"el",
@@ -892,7 +946,6 @@ export async function evaluateViaPlaywright(opts: {
892946return result;
893947}
894948895-const previousUrl = page.url();
896949// eslint-disable-next-line @typescript-eslint/no-implied-eval -- required for browser-context eval
897950const browserEvaluator = new Function(
898951"args",
@@ -1345,6 +1398,7 @@ async function executeSingleAction(
13451398selector: action.selector,
13461399values: action.values,
13471400timeoutMs: action.timeoutMs,
1401+ ssrfPolicy,
13481402});
13491403break;
13501404case "fill":
@@ -1353,6 +1407,7 @@ async function executeSingleAction(
13531407targetId: effectiveTargetId,
13541408fields: action.fields,
13551409timeoutMs: action.timeoutMs,
1410+ ssrfPolicy,
13561411});
13571412break;
13581413case "resize":
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。