Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

SSL browser-runtime.ts   Interaktion und
Portierbarkeitunbekannt

 
type QaBrowserGateway = {
  call: (
    method: string,
    params: Record<string, unknown>,
    opts?: { timeoutMs?: number },
  ) => Promise<unknown>;
};

type QaBrowserEnv = {
  gateway: QaBrowserGateway;
};

type QaBrowserRequestParams = {
  method: "GET" | "POST" | "DELETE";
  path: string;
  query?: Record<string, string | number | boolean | undefined>;
  body?: unknown;
  timeoutMs?: number;
};

type QaBrowserOpenTabParams = {
  url: string;
  profile?: string;
  timeoutMs?: number;
};

type QaBrowserSnapshotParams = {
  profile?: string;
  targetId?: string;
  format?: "ai" | "aria";
  limit?: number;
  interactive?: boolean;
  compact?: boolean;
  depth?: number;
  selector?: string;
  frame?: string;
  labels?: boolean;
  mode?: "efficient";
  maxChars?: number;
  timeoutMs?: number;
};

type QaBrowserActRequest = {
  kind: string;
  targetId?: string;
  ref?: string;
  doubleClick?: boolean;
  button?: string;
  modifiers?: string[];
  text?: string;
  submit?: boolean;
  slowly?: boolean;
  key?: string;
  delayMs?: number;
  startRef?: string;
  endRef?: string;
  values?: string[];
  fields?: Array<Record<string, unknown>>;
  width?: number;
  height?: number;
  timeMs?: number;
  selector?: string;
  url?: string;
  loadState?: string;
  textGone?: string;
  timeoutMs?: number;
  fn?: string;
};

type QaBrowserActParams = {
  profile?: string;
  request: QaBrowserActRequest;
  timeoutMs?: number;
};

type QaBrowserStatus = {
  enabled?: boolean;
  running?: boolean;
  cdpReady?: boolean;
};

type QaBrowserReadyParams = {
  profile?: string;
  timeoutMs?: number;
  intervalMs?: number;
};

function normalizeBrowserQuery(
  query: QaBrowserRequestParams["query"],
): Record<string, string> | undefined {
  if (!query) {
    return undefined;
  }
  const normalized = Object.fromEntries(
    Object.entries(query)
      .filter(([, value]) => value !== undefined)
      .map(([key, value]) => [key, String(value)]),
  );
  return Object.keys(normalized).length > 0 ? normalized : undefined;
}

function resolveBrowserTimeoutMs(timeoutMs: number | undefined, fallbackMs: number) {
  if (typeof timeoutMs !== "number" || !Number.isFinite(timeoutMs)) {
    return fallbackMs;
  }
  return Math.max(1, Math.floor(timeoutMs));
}

export async function callQaBrowserRequest<T = unknown>(
  env: QaBrowserEnv,
  params: QaBrowserRequestParams,
): Promise<T> {
  const timeoutMs = resolveBrowserTimeoutMs(params.timeoutMs, 20_000);
  const payload = await env.gateway.call(
    "browser.request",
    {
      method: params.method,
      path: params.path,
      query: normalizeBrowserQuery(params.query),
      body: params.body,
      timeoutMs,
    },
    { timeoutMs },
  );
  return payload as T;
}

export async function qaBrowserOpenTab<T = unknown>(
  env: QaBrowserEnv,
  params: QaBrowserOpenTabParams,
): Promise<T> {
  return await callQaBrowserRequest<T>(env, {
    method: "POST",
    path: "/tabs/open",
    query: params.profile ? { profile: params.profile } : undefined,
    body: { url: params.url },
    timeoutMs: resolveBrowserTimeoutMs(params.timeoutMs, 20_000),
  });
}

export async function qaBrowserSnapshot<T = unknown>(
  env: QaBrowserEnv,
  params: QaBrowserSnapshotParams = {},
): Promise<T> {
  return await callQaBrowserRequest<T>(env, {
    method: "GET",
    path: "/snapshot",
    query: {
      profile: params.profile,
      targetId: params.targetId,
      format: params.format ?? "ai",
      limit: params.limit,
      interactive: params.interactive,
      compact: params.compact,
      depth: params.depth,
      selector: params.selector,
      frame: params.frame,
      labels: params.labels,
      mode: params.mode,
      maxChars: params.maxChars,
    },
    timeoutMs: resolveBrowserTimeoutMs(params.timeoutMs, 20_000),
  });
}

export async function qaBrowserAct<T = unknown>(
  env: QaBrowserEnv,
  params: QaBrowserActParams,
): Promise<T> {
  return await callQaBrowserRequest<T>(env, {
    method: "POST",
    path: "/act",
    query: params.profile ? { profile: params.profile } : undefined,
    body: params.request,
    timeoutMs: resolveBrowserTimeoutMs(params.timeoutMs, 20_000),
  });
}

function isQaBrowserReady(status: QaBrowserStatus | null | undefined) {
  return status?.enabled === true && status?.running === true && status?.cdpReady === true;
}

function sleep(ms: number) {
  return new Promise<void>((resolve) => setTimeout(resolve, ms));
}

export async function waitForQaBrowserReady<T extends QaBrowserStatus = QaBrowserStatus>(
  env: QaBrowserEnv,
  params: QaBrowserReadyParams = {},
): Promise<T> {
  const timeoutMs = resolveBrowserTimeoutMs(params.timeoutMs, 20_000);
  const intervalMs = resolveBrowserTimeoutMs(params.intervalMs, 250);
  const startedAt = Date.now();
  let lastStatus: QaBrowserStatus | null = null;
  while (Date.now() - startedAt < timeoutMs) {
    lastStatus = await callQaBrowserRequest<QaBrowserStatus>(env, {
      method: "GET",
      path: "/",
      query: params.profile ? { profile: params.profile } : undefined,
      timeoutMs: Math.min(timeoutMs, 5_000),
    });
    if (isQaBrowserReady(lastStatus)) {
      return lastStatus as T;
    }
    await sleep(intervalMs);
  }
  throw new Error(
    `browser control not ready after ${timeoutMs}ms${
      lastStatus ? ` (${JSON.stringify(lastStatus)})` : ""
    }`,
  );
}

Messung V0.5 in Prozent
C=100 H=97 G=98

[Verzeichnis aufwärts0.13unsichere VerbindungÜbersetzung europäischer Sprachen durch Browser2026-06-10]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik