chore: add a11y to bidi over bidi+ (#10338)

This commit is contained in:
Alex Rudenko 2023-06-07 13:54:09 +02:00 committed by GitHub
parent b8782fd7a2
commit edb03d695b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 73 additions and 19 deletions

View File

@ -18,8 +18,6 @@ import {Protocol} from 'devtools-protocol';
import {ElementHandle} from '../api/ElementHandle.js'; import {ElementHandle} from '../api/ElementHandle.js';
import {CDPSession} from './Connection.js';
/** /**
* Represents a Node and the properties of it that are relevant to Accessibility. * Represents a Node and the properties of it that are relevant to Accessibility.
* @public * @public
@ -109,6 +107,11 @@ export interface SnapshotOptions {
root?: ElementHandle<Node>; root?: ElementHandle<Node>;
} }
interface DataProvider {
getFullAXTree(): Promise<Protocol.Accessibility.GetFullAXTreeResponse>;
describeNode(id: string): Promise<Protocol.DOM.DescribeNodeResponse>;
}
/** /**
* The Accessibility class provides methods for inspecting the browser's * The Accessibility class provides methods for inspecting the browser's
* accessibility tree. The accessibility tree is used by assistive technology * accessibility tree. The accessibility tree is used by assistive technology
@ -132,13 +135,13 @@ export interface SnapshotOptions {
* @public * @public
*/ */
export class Accessibility { export class Accessibility {
#client: CDPSession; #dataProvider: DataProvider;
/** /**
* @internal * @internal
*/ */
constructor(client: CDPSession) { constructor(dataProvider: DataProvider) {
this.#client = client; this.#dataProvider = dataProvider;
} }
/** /**
@ -184,12 +187,10 @@ export class Accessibility {
options: SnapshotOptions = {} options: SnapshotOptions = {}
): Promise<SerializedAXNode | null> { ): Promise<SerializedAXNode | null> {
const {interestingOnly = true, root = null} = options; const {interestingOnly = true, root = null} = options;
const {nodes} = await this.#client.send('Accessibility.getFullAXTree'); const {nodes} = await this.#dataProvider.getFullAXTree();
let backendNodeId: number | undefined; let backendNodeId: number | undefined;
if (root) { if (root && root.id) {
const {node} = await this.#client.send('DOM.describeNode', { const {node} = await this.#dataProvider.describeNode(root.id);
objectId: root.id,
});
backendNodeId = node.backendNodeId; backendNodeId = node.backendNodeId;
} }
const defaultRoot = AXNode.createTree(nodes); const defaultRoot = AXNode.createTree(nodes);

View File

@ -167,7 +167,16 @@ export class CDPPage extends Page {
this.#keyboard = new Keyboard(client); this.#keyboard = new Keyboard(client);
this.#mouse = new Mouse(client, this.#keyboard); this.#mouse = new Mouse(client, this.#keyboard);
this.#touchscreen = new Touchscreen(client, this.#keyboard); this.#touchscreen = new Touchscreen(client, this.#keyboard);
this.#accessibility = new Accessibility(client); this.#accessibility = new Accessibility({
describeNode(id: string) {
return client.send('DOM.describeNode', {
objectId: id,
});
},
getFullAXTree() {
return client.send('Accessibility.getFullAXTree');
},
});
this.#frameManager = new FrameManager( this.#frameManager = new FrameManager(
client, client,
this, this,

View File

@ -281,20 +281,20 @@ export class BrowsingContext extends EventEmitter {
return await this.evaluate(getPageContent); return await this.evaluate(getPageContent);
} }
async sendCDPCommand( async sendCDPCommand<T extends keyof ProtocolMapping.Commands>(
method: keyof ProtocolMapping.Commands, method: T,
params: object = {} params: ProtocolMapping.Commands[T]['paramsType'][0] = {}
): Promise<unknown> { ): Promise<ProtocolMapping.Commands[T]['returnType']> {
const session = await this.connection.send('cdp.getSession', { const session = await this.connection.send('cdp.getSession', {
context: this.#id, context: this.#id,
}); });
// TODO: remove any once chromium-bidi types are updated. const sessionId = session.result.cdpSession;
const sessionId = (session.result as any).cdpSession; const result = await this.connection.send('cdp.sendCommand', {
return await this.connection.send('cdp.sendCommand', {
cdpMethod: method, cdpMethod: method,
cdpParams: params, cdpParams: params,
cdpSession: sessionId, cdpSession: sessionId,
}); });
return result.result;
} }
dispose(): void { dispose(): void {

View File

@ -26,6 +26,7 @@ import {
} from '../../api/Page.js'; } from '../../api/Page.js';
import {assert} from '../../util/assert.js'; import {assert} from '../../util/assert.js';
import {Deferred} from '../../util/Deferred.js'; import {Deferred} from '../../util/Deferred.js';
import {Accessibility} from '../Accessibility.js';
import {ConsoleMessage, ConsoleMessageLocation} from '../ConsoleMessage.js'; import {ConsoleMessage, ConsoleMessageLocation} from '../ConsoleMessage.js';
import {TargetCloseError} from '../Errors.js'; import {TargetCloseError} from '../Errors.js';
import {Handler} from '../EventEmitter.js'; import {Handler} from '../EventEmitter.js';
@ -58,6 +59,7 @@ import {BidiSerializer} from './Serializer.js';
* @internal * @internal
*/ */
export class Page extends PageBase { export class Page extends PageBase {
#accessibility: Accessibility;
#timeoutSettings = new TimeoutSettings(); #timeoutSettings = new TimeoutSettings();
#browserContext: BrowserContext; #browserContext: BrowserContext;
#connection: Connection; #connection: Connection;
@ -135,6 +137,24 @@ export class Page extends PageBase {
for (const [event, subscriber] of this.#networkManagerEvents) { for (const [event, subscriber] of this.#networkManagerEvents) {
this.#networkManager.on(event, subscriber); this.#networkManager.on(event, subscriber);
} }
// TODO: https://github.com/w3c/webdriver-bidi/issues/443
this.#accessibility = new Accessibility({
describeNode: (id: string) => {
return this.mainFrame().context().sendCDPCommand('DOM.describeNode', {
objectId: id,
});
},
getFullAXTree: () => {
return this.mainFrame()
.context()
.sendCDPCommand('Accessibility.getFullAXTree');
},
});
}
override get accessibility(): Accessibility {
return this.#accessibility;
} }
override browser(): Browser { override browser(): Browser {
@ -374,7 +394,7 @@ export class Page extends PageBase {
const width = viewport.width; const width = viewport.width;
const height = viewport.height; const height = viewport.height;
const deviceScaleFactor = 1; const deviceScaleFactor = 1;
const screenOrientation = {angle: 0, type: 'portraitPrimary'}; const screenOrientation = {angle: 0, type: 'portraitPrimary' as const};
await this.mainFrame() await this.mainFrame()
.context() .context()

View File

@ -209,6 +209,12 @@
"parameters": ["cdp", "firefox"], "parameters": ["cdp", "firefox"],
"expectations": ["SKIP", "TIMEOUT"] "expectations": ["SKIP", "TIMEOUT"]
}, },
{
"testIdPattern": "[accessibility.spec] *",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["chrome", "webDriverBiDi"],
"expectations": ["PASS"]
},
{ {
"testIdPattern": "[ariaqueryhandler.spec] *", "testIdPattern": "[ariaqueryhandler.spec] *",
"platforms": ["darwin", "linux", "win32"], "platforms": ["darwin", "linux", "win32"],
@ -2363,6 +2369,24 @@
"parameters": ["cdp", "firefox"], "parameters": ["cdp", "firefox"],
"expectations": ["SKIP"] "expectations": ["SKIP"]
}, },
{
"testIdPattern": "[accessibility.spec] Accessibility get snapshots while the tree is re-calculated",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["chrome", "webDriverBiDi"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[accessibility.spec] Accessibility should report uninteresting nodes",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["chrome", "webDriverBiDi"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[accessibility.spec] Accessibility should work",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["chrome", "webDriverBiDi"],
"expectations": ["FAIL"]
},
{ {
"testIdPattern": "[CDPSession.spec] Target.createCDPSession should send events", "testIdPattern": "[CDPSession.spec] Target.createCDPSession should send events",
"platforms": ["win32"], "platforms": ["win32"],