mirror of
https://github.com/Kong/insomnia.git
synced 2026-11-05 20:43:52 -05:00
refactor: update E2E test configurations and improve field handling in auth and sync pages
This commit is contained in:
5 files changed
+56
-23
No files matched your search
@@ -102,8 +102,8 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
# To scale up, add indices here and bump shardTotal to match.
|
||||
shardIndex: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
|
||||
shardTotal: [16]
|
||||
shardIndex: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]
|
||||
shardTotal: [24]
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5
|
||||
|
||||
@@ -244,23 +244,26 @@ export class AuthTabComponent extends TabPanelPage {
|
||||
reapply: () => this.setCodeMirrorValue(editor, value),
|
||||
};
|
||||
await edit.reapply!();
|
||||
await this.waitForAuthFieldsPersisted([edit]);
|
||||
// Verify every field written so far, not just this one: its save can
|
||||
// overwrite an earlier field from a stale copy of the auth config.
|
||||
await this.waitForAuthFieldsPersisted([...edits, edit]);
|
||||
edits.push(edit);
|
||||
}
|
||||
if (fields.signatureMethod) {
|
||||
const signatureMethod = fields.signatureMethod;
|
||||
const selectMethod = () =>
|
||||
this.page
|
||||
const selectMethod = async () => {
|
||||
await this.page
|
||||
.locator(this.TABPANEL)
|
||||
.locator("#Signature-Method")
|
||||
.selectOption(signatureMethod);
|
||||
};
|
||||
await selectMethod();
|
||||
const edit: AuthFieldEdit = {
|
||||
field: "signatureMethod",
|
||||
value: signatureMethod,
|
||||
reapply: selectMethod,
|
||||
};
|
||||
await this.waitForAuthFieldsPersisted([edit]);
|
||||
await this.waitForAuthFieldsPersisted([...edits, edit]);
|
||||
edits.push(edit);
|
||||
}
|
||||
// A later field's debounced save can overwrite an earlier one from a
|
||||
|
||||
@@ -317,11 +317,13 @@ export class CloudSyncPage extends BasePage {
|
||||
* @param branch - The local branch to delete
|
||||
*/
|
||||
async deleteLocalBranch(branch: string): Promise<void> {
|
||||
await this.branchesDialog
|
||||
const row = this.branchesDialog
|
||||
.getByLabel("Branches list", { exact: true })
|
||||
.getByLabel(branch, { exact: true })
|
||||
.getByRole("button", { name: "Delete" })
|
||||
.dblclick();
|
||||
.getByLabel(branch, { exact: true });
|
||||
await row.getByRole("button", { name: "Delete" }).click();
|
||||
// A dblclick can fire its 2nd click before React re-renders the
|
||||
// button into its "Confirm" state, so wait for it explicitly.
|
||||
await row.getByRole("button", { name: "Confirm" }).click();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -347,11 +349,13 @@ export class CloudSyncPage extends BasePage {
|
||||
* @param branch - The local branch to merge in
|
||||
*/
|
||||
async mergeBranch(branch: string): Promise<void> {
|
||||
await this.branchesDialog
|
||||
const row = this.branchesDialog
|
||||
.getByLabel("Branches list", { exact: true })
|
||||
.getByLabel(branch, { exact: true })
|
||||
.getByRole("button", { name: "Merge" })
|
||||
.dblclick();
|
||||
.getByLabel(branch, { exact: true });
|
||||
await row.getByRole("button", { name: "Merge" }).click();
|
||||
// A dblclick can fire its 2nd click before React re-renders the
|
||||
// button into its "Confirm" state, so wait for it explicitly.
|
||||
await row.getByRole("button", { name: "Confirm" }).click();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -38,15 +38,25 @@ export class McpClientPage extends RequestPage {
|
||||
*/
|
||||
async getTools(): Promise<string[]> {
|
||||
// The sidebar is populated asynchronously once the server answers
|
||||
// tools/list, so wait for the first row before reading the list.
|
||||
await expect(this.page.locator(this.TOOL_ROW).first()).toBeVisible({
|
||||
timeout: DEFAULT_TIMEOUT,
|
||||
});
|
||||
return this.page
|
||||
.locator(this.TOOL_ROW)
|
||||
.evaluateAll((rows) =>
|
||||
rows.map((row) => row.getAttribute("aria-label") ?? ""),
|
||||
);
|
||||
// tools/list, and it can re-render (briefly empty) while it settles,
|
||||
// so poll until a non-empty list of names has been read.
|
||||
let tools: string[] = [];
|
||||
await expect
|
||||
.poll(
|
||||
async () => {
|
||||
tools = (
|
||||
await this.page
|
||||
.locator(this.TOOL_ROW)
|
||||
.evaluateAll((rows) =>
|
||||
rows.map((row) => row.getAttribute("aria-label") ?? ""),
|
||||
)
|
||||
).filter(Boolean);
|
||||
return tools.length;
|
||||
},
|
||||
{ timeout: DEFAULT_TIMEOUT },
|
||||
)
|
||||
.toBeGreaterThan(0);
|
||||
return tools;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import { expect } from "@playwright/test";
|
||||
|
||||
import { DEFAULT_TIMEOUT } from "../misc/constants";
|
||||
import type { RequestHeader,SocketIOMessage } from "../models/socket-io-request";
|
||||
import { RequestPage } from "./request.page";
|
||||
|
||||
@@ -5,6 +8,19 @@ export class SocketIORequestPage extends RequestPage {
|
||||
protected readonly urlBarId = "websocket-url-bar";
|
||||
protected readonly persistedDbFile = "insomnia.SocketIORequest.db";
|
||||
|
||||
/**
|
||||
* Clicks Connect and waits for the button to flip to "Disconnect", so a
|
||||
* following send doesn't race the handshake and get dropped.
|
||||
*/
|
||||
async connect(): Promise<void> {
|
||||
await super.connect();
|
||||
await expect(
|
||||
this.page
|
||||
.locator(this.PANE)
|
||||
.getByRole("button", { name: "Disconnect", exact: true }),
|
||||
).toBeVisible({ timeout: DEFAULT_TIMEOUT });
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the full Socket.IO request state from the UI (url, headers, and
|
||||
* the composed message).
|
||||
|
||||
Reference in new issue
Block a user