Skip to content

Commit

Permalink
Fix Chrome support and add the field to send BiDi commands (#32)
Browse files Browse the repository at this point in the history
* Fix Chrome support

* Format

* Add key to the network requests.

* Add a field to send the command.

* Address review feedback
  • Loading branch information
lutien authored Aug 20, 2024
1 parent ae2514a commit 91cef26
Show file tree
Hide file tree
Showing 5 changed files with 148 additions and 70 deletions.
89 changes: 54 additions & 35 deletions src/components/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ class App extends React.Component {
browserName: null,
browserVersion: null,
browsingContexts: [],
bidiCommand: "",
bidiLog: [],
consoleInput: "",
consoleOutput: [],
Expand Down Expand Up @@ -189,8 +190,7 @@ class App extends React.Component {
...state.networkEntries,
{
contextId: data.params.context,
id:
data.params.request.request + data.params.redirectCount,
id: data.params.request.request + data.params.redirectCount,
url: data.params.request.url,
redirectCount: data.params.redirectCount,
request: data.params.request,
Expand Down Expand Up @@ -227,9 +227,13 @@ class App extends React.Component {
{}
);

// If we connected to an existing session, status `ready` will be false.
// For Firefox if we connected to an existing session, status `ready` will be false.
// Only attempt to create a new session if `ready` is true.
const canCreateNewSession = sessionStatusResponse.result.ready;
// For Chrome we can not send "session.status" command before starting the session,
// so the `result` property is going to be `undefined`.
const canCreateNewSession = sessionStatusResponse.result
? sessionStatusResponse.result.ready
: true;
// const { isConnectingToExistingSession } = this.state;
// if (!canCreateNewSession && !isConnectingToExistingSession) {
// console.log(
Expand All @@ -241,12 +245,9 @@ class App extends React.Component {

if (canCreateNewSession) {
console.log("Creating a new session");
const sessionNewResponse = await this.#client.sendCommand(
"session.new",
{
capabilities: {},
}
);
const sessionNewResponse = await this.#client.sendCommand("session.new", {
capabilities: {},
});

// Store the session id
const { capabilities, sessionId } = sessionNewResponse.result;
Expand All @@ -270,14 +271,14 @@ class App extends React.Component {
});
// Chrome doesn't support network events yet, that's why previous subscribe
// will fail, and, in this case, we will subscribe again excluding network events.
if (response.error === 'invalid argument') {
if (response.error === "invalid argument") {
this.#networkEventsSupported = false;
this.#client.sendCommand("session.subscribe", {
events: [
"browsingContext.contextCreated",
"browsingContext.domContentLoaded",
"browsingContext.load",
"log.entryAdded"
"log.entryAdded",
],
});
}
Expand Down Expand Up @@ -366,6 +367,16 @@ class App extends React.Component {
});
};

sendCommand = (e) => {
e.preventDefault();
try {
const commandObject = JSON.parse(this.state.bidiCommand);
this.#client.sendCommand(commandObject.method, commandObject.params);
} catch (error) {
console.error({ error });
}
};

setActiveTab = (tab) => {
this.setState({
activeTab: tab,
Expand Down Expand Up @@ -449,6 +460,7 @@ class App extends React.Component {
render() {
const {
activeTab,
bidiCommand,
bidiLog,
browserName,
browserVersion,
Expand All @@ -465,29 +477,29 @@ class App extends React.Component {
pageTimings,
} = this.state;

const tabs = [{
id: "console",
icon: consoleIcon,
title: "Console",
content: (
<Console
consoleOutput={consoleOutput}
consoleInput={consoleInput}
isClientReady={isClientReady}
onSubmit={this.onConsoleSubmit}
onChange={this.onInputChange}
evaluationBrowsingContextId={evaluationBrowsingContextId}
filteringBrowsingContextId={filteringBrowsingContextId}
browsingContexts={browsingContexts}
setEvaluationBrowsingContext={
this.setEvaluationBrowsingContext
}
/>
),
}];
const tabs = [
{
id: "console",
icon: consoleIcon,
title: "Console",
content: (
<Console
consoleOutput={consoleOutput}
consoleInput={consoleInput}
isClientReady={isClientReady}
onSubmit={this.onConsoleSubmit}
onChange={this.onInputChange}
evaluationBrowsingContextId={evaluationBrowsingContextId}
filteringBrowsingContextId={filteringBrowsingContextId}
browsingContexts={browsingContexts}
setEvaluationBrowsingContext={this.setEvaluationBrowsingContext}
/>
),
},
];

// Add network tab only if network events are supported.
if(this.#networkEventsSupported) {
if (this.#networkEventsSupported) {
tabs.push({
id: "network",
icon: networkIcon,
Expand All @@ -509,8 +521,15 @@ class App extends React.Component {
tabs.push({
id: "bidi-log",
icon: bidiLogIcon,
title: "BiDi log",
content: <BiDiLog log={bidiLog} />,
title: "BiDi interface",
content: (
<BiDiLog
log={bidiLog}
bidiCommand={bidiCommand}
onBidiCommandChange={this.onInputChange}
sendCommand={this.sendCommand}
/>
),
});

return (
Expand Down
27 changes: 27 additions & 0 deletions src/components/BiDiCommandInput.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
.BiDiCommandInput {
display: grid;
height: 45px;
align-content: center;
grid-template-columns: auto 80px;
column-gap: 20px;
overflow: hidden;
margin-inline: 20px;
border-bottom: 1px solid #eee;
}

.BiDiCommandInput__input {
border: 0;
font-size: 14px;
margin-left: 2px;
}

.BiDiCommandInput__form {
display: contents;
}

.BiDiCommandInput__button {
border: 0;
text-align: left;
height: 24px;
font-size: 14px;
}
23 changes: 23 additions & 0 deletions src/components/BiDiCommandInput.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from "react";

import "./BiDiCommandInput.css";

const BiDiCommandInput = ({ onInputChange, onSubmit, value }) => {
return (
<li className="BiDiCommandInput">
<form className="BiDiCommandInput__form" onSubmit={onSubmit}>
<input
className="BiDiCommandInput__input"
id="bidiCommand"
name="bidiCommand"
onChange={onInputChange}
placeholder="Write a BiDi command here to send it to the browser"
value={value}
/>
<button className="entry__type BiDiCommandInput__button">Send</button>
</form>
</li>
);
};

export default BiDiCommandInput;
12 changes: 9 additions & 3 deletions src/components/BiDiLog.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
import React from "react";
import BiDiLogEntry from "./BiDiLogEntry";
import BiDiCommandInput from "./BiDiCommandInput";

import "./BiDiLog.css";

const BiDiLog = ({ log }) => {
const BiDiLog = ({ bidiCommand, log, onBidiCommandChange, sendCommand }) => {
return (
<div className="bidi-log">
<ul className="bidi-log__list">
{log.map((entry) => (
<BiDiLogEntry entry={entry} key={entry.message}/>
<BiDiCommandInput
onInputChange={onBidiCommandChange}
onSubmit={sendCommand}
value={bidiCommand}
/>
{log.toReversed().map((entry, index) => (
<BiDiLogEntry entry={entry} key={entry.message + index} />
))}
</ul>
</div>
Expand Down
67 changes: 35 additions & 32 deletions src/components/Network.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,25 @@ const Network = ({
networkEntries,
pageTimings,
}) => {

if (!isClientReady) {
return null;
}

const entries = networkEntries.filter(({ contextId }) =>
!filteringBrowsingContextId || (filteringBrowsingContextId === contextId));
const entries = networkEntries.filter(
({ contextId }) =>
!filteringBrowsingContextId || filteringBrowsingContextId === contextId
);

const timings = pageTimings.filter(({ contextId }) =>
!filteringBrowsingContextId || (filteringBrowsingContextId === contextId));
const timings = pageTimings.filter(
({ contextId }) =>
!filteringBrowsingContextId || filteringBrowsingContextId === contextId
);

const events = harEvents.filter((event) =>
!filteringBrowsingContextId || (filteringBrowsingContextId === event.params.context));
const events = harEvents.filter(
(event) =>
!filteringBrowsingContextId ||
filteringBrowsingContextId === event.params.context
);

return (
<div className="network-app">
Expand All @@ -38,34 +44,31 @@ const Network = ({
<span className="network-column network-column-protocol ellipsis-text">
Protocol
</span>
<span className="network-column network-column-url">
URL
</span>
<span className="network-column network-column-url">URL</span>
</div>
</div>
<div className="network-entries">
{entries.map(
({
isFirstRequest,
request,
response,
url,
}) =>
<div className={`network-row ${isFirstRequest ? 'network-first-request' : ''}`}>
<span className="network-column network-column-status">
{response?.status}
</span>
<span className="network-column network-column-status">
{request.method}
</span>
<span className="network-column network-column-status">
{response?.protocol}
</span>
<span className="network-column network-column-status ellipsis-text">
{request.url}
</span>
</div>
)}
{entries.map(({ isFirstRequest, request, response, redirectCount }) => (
<div
className={`network-row ${
isFirstRequest ? "network-first-request" : ""
}`}
key={request.request + redirectCount}
>
<span className="network-column network-column-status">
{response?.status}
</span>
<span className="network-column network-column-status">
{request.method}
</span>
<span className="network-column network-column-status">
{response?.protocol}
</span>
<span className="network-column network-column-status ellipsis-text">
{request.url}
</span>
</div>
))}
</div>
<NetworkFooter
browserName={browserName}
Expand Down

0 comments on commit 91cef26

Please sign in to comment.