Summary - The `--exact` flag on `find role`, `find label`, and `find placeholder` was accepted by the CLI but silently dropped by the server. The Zod validation schema, TypeScript types, and action handlers all lacked the `exact` field, so it was stripped before reaching Playwright's `getByRole`, `getByLabel`, and `getByPlaceholder` calls. - Added `exact` to the schema, types, and handler for all three locators so the flag is forwarded to Playwright as intended. - Added tests confirming `exact: true` survives protocol parsing for `getbyrole`, `getbylabel`, and `getbyplaceholder`. Fixes #402
This commit is contained in:
+3
-3
@@ -887,7 +887,7 @@ async function handleGetByRole(
|
|||||||
browser: BrowserManager
|
browser: BrowserManager
|
||||||
): Promise<Response> {
|
): Promise<Response> {
|
||||||
const page = browser.getPage();
|
const page = browser.getPage();
|
||||||
const locator = page.getByRole(command.role as any, { name: command.name });
|
const locator = page.getByRole(command.role as any, { name: command.name, exact: command.exact });
|
||||||
|
|
||||||
switch (command.subaction) {
|
switch (command.subaction) {
|
||||||
case 'click':
|
case 'click':
|
||||||
@@ -927,7 +927,7 @@ async function handleGetByLabel(
|
|||||||
browser: BrowserManager
|
browser: BrowserManager
|
||||||
): Promise<Response> {
|
): Promise<Response> {
|
||||||
const page = browser.getPage();
|
const page = browser.getPage();
|
||||||
const locator = page.getByLabel(command.label);
|
const locator = page.getByLabel(command.label, { exact: command.exact });
|
||||||
|
|
||||||
switch (command.subaction) {
|
switch (command.subaction) {
|
||||||
case 'click':
|
case 'click':
|
||||||
@@ -947,7 +947,7 @@ async function handleGetByPlaceholder(
|
|||||||
browser: BrowserManager
|
browser: BrowserManager
|
||||||
): Promise<Response> {
|
): Promise<Response> {
|
||||||
const page = browser.getPage();
|
const page = browser.getPage();
|
||||||
const locator = page.getByPlaceholder(command.placeholder);
|
const locator = page.getByPlaceholder(command.placeholder, { exact: command.exact });
|
||||||
|
|
||||||
switch (command.subaction) {
|
switch (command.subaction) {
|
||||||
case 'click':
|
case 'click':
|
||||||
|
|||||||
@@ -364,6 +364,23 @@ describe('parseCommand', () => {
|
|||||||
expect(result.success).toBe(true);
|
expect(result.success).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should parse getbyrole with exact', () => {
|
||||||
|
const result = parseCommand(
|
||||||
|
cmd({
|
||||||
|
id: '1',
|
||||||
|
action: 'getbyrole',
|
||||||
|
role: 'button',
|
||||||
|
name: 'Continue',
|
||||||
|
subaction: 'click',
|
||||||
|
exact: true,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
expect(result.success).toBe(true);
|
||||||
|
if (result.success) {
|
||||||
|
expect(result.command.exact).toBe(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
it('should parse getbytext', () => {
|
it('should parse getbytext', () => {
|
||||||
const result = parseCommand(
|
const result = parseCommand(
|
||||||
cmd({
|
cmd({
|
||||||
@@ -388,6 +405,40 @@ describe('parseCommand', () => {
|
|||||||
);
|
);
|
||||||
expect(result.success).toBe(true);
|
expect(result.success).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should parse getbylabel with exact', () => {
|
||||||
|
const result = parseCommand(
|
||||||
|
cmd({
|
||||||
|
id: '1',
|
||||||
|
action: 'getbylabel',
|
||||||
|
label: 'Email',
|
||||||
|
subaction: 'fill',
|
||||||
|
value: 'test@test.com',
|
||||||
|
exact: true,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
expect(result.success).toBe(true);
|
||||||
|
if (result.success) {
|
||||||
|
expect(result.command.exact).toBe(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should parse getbyplaceholder with exact', () => {
|
||||||
|
const result = parseCommand(
|
||||||
|
cmd({
|
||||||
|
id: '1',
|
||||||
|
action: 'getbyplaceholder',
|
||||||
|
placeholder: 'Search',
|
||||||
|
subaction: 'fill',
|
||||||
|
value: 'test',
|
||||||
|
exact: true,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
expect(result.success).toBe(true);
|
||||||
|
if (result.success) {
|
||||||
|
expect(result.command.exact).toBe(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('tabs', () => {
|
describe('tabs', () => {
|
||||||
|
|||||||
@@ -126,6 +126,7 @@ const getByRoleSchema = baseCommandSchema.extend({
|
|||||||
action: z.literal('getbyrole'),
|
action: z.literal('getbyrole'),
|
||||||
role: z.string().min(1),
|
role: z.string().min(1),
|
||||||
name: z.string().optional(),
|
name: z.string().optional(),
|
||||||
|
exact: z.boolean().optional(),
|
||||||
subaction: z.enum(['click', 'fill', 'check', 'hover']),
|
subaction: z.enum(['click', 'fill', 'check', 'hover']),
|
||||||
value: z.string().optional(),
|
value: z.string().optional(),
|
||||||
});
|
});
|
||||||
@@ -140,6 +141,7 @@ const getByTextSchema = baseCommandSchema.extend({
|
|||||||
const getByLabelSchema = baseCommandSchema.extend({
|
const getByLabelSchema = baseCommandSchema.extend({
|
||||||
action: z.literal('getbylabel'),
|
action: z.literal('getbylabel'),
|
||||||
label: z.string().min(1),
|
label: z.string().min(1),
|
||||||
|
exact: z.boolean().optional(),
|
||||||
subaction: z.enum(['click', 'fill', 'check']),
|
subaction: z.enum(['click', 'fill', 'check']),
|
||||||
value: z.string().optional(),
|
value: z.string().optional(),
|
||||||
});
|
});
|
||||||
@@ -147,6 +149,7 @@ const getByLabelSchema = baseCommandSchema.extend({
|
|||||||
const getByPlaceholderSchema = baseCommandSchema.extend({
|
const getByPlaceholderSchema = baseCommandSchema.extend({
|
||||||
action: z.literal('getbyplaceholder'),
|
action: z.literal('getbyplaceholder'),
|
||||||
placeholder: z.string().min(1),
|
placeholder: z.string().min(1),
|
||||||
|
exact: z.boolean().optional(),
|
||||||
subaction: z.enum(['click', 'fill']),
|
subaction: z.enum(['click', 'fill']),
|
||||||
value: z.string().optional(),
|
value: z.string().optional(),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -108,6 +108,7 @@ export interface GetByRoleCommand extends BaseCommand {
|
|||||||
action: 'getbyrole';
|
action: 'getbyrole';
|
||||||
role: string;
|
role: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
|
exact?: boolean;
|
||||||
subaction: 'click' | 'fill' | 'check' | 'hover';
|
subaction: 'click' | 'fill' | 'check' | 'hover';
|
||||||
value?: string;
|
value?: string;
|
||||||
}
|
}
|
||||||
@@ -122,6 +123,7 @@ export interface GetByTextCommand extends BaseCommand {
|
|||||||
export interface GetByLabelCommand extends BaseCommand {
|
export interface GetByLabelCommand extends BaseCommand {
|
||||||
action: 'getbylabel';
|
action: 'getbylabel';
|
||||||
label: string;
|
label: string;
|
||||||
|
exact?: boolean;
|
||||||
subaction: 'click' | 'fill' | 'check';
|
subaction: 'click' | 'fill' | 'check';
|
||||||
value?: string;
|
value?: string;
|
||||||
}
|
}
|
||||||
@@ -129,6 +131,7 @@ export interface GetByLabelCommand extends BaseCommand {
|
|||||||
export interface GetByPlaceholderCommand extends BaseCommand {
|
export interface GetByPlaceholderCommand extends BaseCommand {
|
||||||
action: 'getbyplaceholder';
|
action: 'getbyplaceholder';
|
||||||
placeholder: string;
|
placeholder: string;
|
||||||
|
exact?: boolean;
|
||||||
subaction: 'click' | 'fill';
|
subaction: 'click' | 'fill';
|
||||||
value?: string;
|
value?: string;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user