Skip to content

Commit c8f5ae4

Browse files
authored
feat: Introduce webext run --devtools to open DevTools for the installed add-on right away. (#2488)
1 parent fcbdd1a commit c8f5ae4

File tree

9 files changed

+81
-8
lines changed

9 files changed

+81
-8
lines changed

src/cmd/run.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ const log = createLogger(import.meta.url);
2828
export type CmdRunParams = {|
2929
artifactsDir: string,
3030
browserConsole: boolean,
31+
devtools: boolean,
3132
pref?: FirefoxPreferences,
3233
firefox: string,
3334
firefoxProfile?: string,
@@ -75,6 +76,7 @@ export default async function run(
7576
{
7677
artifactsDir,
7778
browserConsole = false,
79+
devtools = false,
7880
pref,
7981
firefox,
8082
firefoxProfile,
@@ -174,6 +176,7 @@ export default async function run(
174176
profilePath: firefoxProfile,
175177
customPrefs,
176178
browserConsole,
179+
devtools,
177180
preInstall,
178181

179182
// Firefox runner injected dependencies.

src/extension-runners/firefox-desktop.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import type {FirefoxInfo} from '../firefox/index'; // eslint-disable-line import
3333
type FirefoxDesktopSpecificRunnerParams = {|
3434
customPrefs?: FirefoxPreferences,
3535
browserConsole: boolean,
36+
devtools: boolean,
3637
firefoxBinary: string,
3738
preInstall: boolean,
3839

@@ -212,6 +213,7 @@ export class FirefoxDesktopExtensionRunner {
212213
async startFirefoxInstance() {
213214
const {
214215
browserConsole,
216+
devtools,
215217
extensions,
216218
firefoxBinary,
217219
preInstall,
@@ -241,6 +243,7 @@ export class FirefoxDesktopExtensionRunner {
241243
firefoxBinary,
242244
binaryArgs,
243245
extensions,
246+
devtools,
244247
});
245248

246249
this.runningInfo.firefox.on('close', () => {
@@ -262,7 +265,7 @@ export class FirefoxDesktopExtensionRunner {
262265
for (const extension of extensions) {
263266
try {
264267
const addonId = await (
265-
remoteFirefox.installTemporaryAddon(extension.sourceDir)
268+
remoteFirefox.installTemporaryAddon(extension.sourceDir, devtools)
266269
.then((installResult: FirefoxRDPResponseAddon) => {
267270
return installResult.addon.id;
268271
})

src/firefox/index.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ export type FirefoxRunOptions = {
9090
binaryArgs?: Array<string>,
9191
args?: Array<any>,
9292
extensions: Array<Extension>,
93+
devtools: boolean,
9394
};
9495

9596
/*
@@ -103,6 +104,7 @@ export async function run(
103104
firefoxBinary,
104105
binaryArgs,
105106
extensions,
107+
devtools,
106108
}: FirefoxRunOptions = {}
107109
): Promise<FirefoxInfo> {
108110

@@ -164,9 +166,13 @@ export async function run(
164166
throw error;
165167
});
166168

167-
log.info(
168-
'Use --verbose or open Tools > Web Developer > Browser Console ' +
169-
'to see logging');
169+
if (!devtools) {
170+
log.info('Use --verbose or --devtools to see logging');
171+
}
172+
if (devtools) {
173+
log.info('More info about WebExtensions debugging:');
174+
log.info('https://extensionworkshop.com/documentation/develop/debugging/');
175+
}
170176

171177
firefox.stderr.on('data', (data) => {
172178
log.debug(`Firefox stderr: ${data.toString().trim()}`);

src/firefox/remote.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,8 @@ export class RemoteFirefox {
131131
}
132132

133133
async installTemporaryAddon(
134-
addonPath: string
134+
addonPath: string,
135+
openDevTools?: boolean
135136
): Promise<FirefoxRDPResponseAddon> {
136137
const addonsActor = await this.getAddonsActor();
137138

@@ -140,6 +141,7 @@ export class RemoteFirefox {
140141
to: addonsActor,
141142
type: 'installTemporaryAddon',
142143
addonPath,
144+
openDevTools,
143145
});
144146
log.debug(`installTemporaryAddon: ${JSON.stringify(response)}`);
145147
log.info(`Installed ${addonPath} as a temporary add-on`);

src/program.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,12 @@ Example: $0 --help run.
707707
demandOption: false,
708708
type: 'array',
709709
},
710+
'devtools': {
711+
describe: 'Open the DevTools for the installed add-on ' +
712+
'(Firefox 106 and later)',
713+
demandOption: false,
714+
type: 'boolean',
715+
},
710716
'browser-console': {
711717
alias: ['bc'],
712718
describe: 'Open the DevTools Browser Console.',

tests/functional/fake-firefox-binary.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const REQUEST_INSTALL_ADDON = {
99
to: 'fakeAddonsActor',
1010
type: 'installTemporaryAddon',
1111
addonPath: process.env.addonPath,
12+
openDevTools: false, // Introduced in Firefox 106 (Bug 1787409 / Bug 1789245)
1213
};
1314
const REPLY_INSTALL_ADDON = {
1415
from: 'fakeAddonsActor',

tests/unit/test-firefox/test.firefox.js

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ import {fs} from 'mz';
1111
import * as firefox from '../../../src/firefox/index.js';
1212
import {onlyInstancesOf, UsageError, WebExtError} from '../../../src/errors.js';
1313
import {withTempDir} from '../../../src/util/temp-dir.js';
14+
import {
15+
consoleStream, // instance is imported to inspect logged messages
16+
} from '../../../src/util/logger.js';
1417
import {
1518
basicManifest,
1619
fixturePath,
@@ -240,6 +243,41 @@ describe('firefox', () => {
240243
});
241244
});
242245

246+
it('logs link to debugging docs', async () => {
247+
const runner = createFakeFxRunner();
248+
consoleStream.flushCapturedLogs();
249+
consoleStream.startCapturing();
250+
251+
const expectedMessage = 'More info about WebExtensions debugging:';
252+
const expectedURLToDocs =
253+
'https://extensionworkshop.com/documentation/develop/debugging/';
254+
await runFirefox({fxRunner: runner, devtools: false});
255+
assert.notOk(consoleStream.capturedMessages.find(
256+
(msg) => msg.includes(expectedMessage)
257+
));
258+
assert.notOk(consoleStream.capturedMessages.find(
259+
(msg) => msg.includes(expectedURLToDocs)
260+
));
261+
262+
consoleStream.flushCapturedLogs();
263+
264+
await runFirefox({fxRunner: runner, devtools: true});
265+
const foundMessage = consoleStream.capturedMessages.find(
266+
(msg) => msg.includes(expectedMessage)
267+
);
268+
const foundDocURL = consoleStream.capturedMessages.find(
269+
(msg) => msg.includes(expectedURLToDocs)
270+
);
271+
272+
// Expect the logs to be found.
273+
assert.ok(foundMessage);
274+
assert.ok(foundDocURL);
275+
276+
// Expected to be emitted as info level logs.
277+
assert.ok(foundMessage?.includes('[info]'));
278+
assert.ok(foundDocURL?.includes('[info]'));
279+
});
280+
243281
});
244282

245283
describe('copyProfile', () => {
@@ -1003,7 +1041,6 @@ describe('firefox', () => {
10031041
sinon.assert.calledOnce(fakeAsyncFsStat);
10041042
}
10051043
));
1006-
10071044
});
10081045

10091046
});

tests/unit/test-firefox/test.remote.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -297,11 +297,11 @@ describe('firefox.remote', () => {
297297
const addonsActor = 'addons1.actor.conn';
298298
const addonPath = '/path/to/addon';
299299

300-
client.request.withArgs({
300+
client.request.withArgs(sinon.match({
301301
type: 'installTemporaryAddon',
302302
to: addonsActor,
303303
addonPath,
304-
}).resolves({
304+
})).resolves({
305305
addon: {id: 'abc123@temporary-addon'},
306306
});
307307

tests/unit/test.program.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,21 @@ describe('program.main', () => {
552552
});
553553
});
554554

555+
it('opens devtools when --devtools is specified', () => {
556+
const fakeCommands = fake(commands, {
557+
run: () => Promise.resolve(),
558+
});
559+
return execProgram(
560+
['run', '--devtools'],
561+
{commands: fakeCommands})
562+
.then(() => {
563+
sinon.assert.calledWithMatch(
564+
fakeCommands.run,
565+
{devtools: true}
566+
);
567+
});
568+
});
569+
555570
async function testWatchFileOption(watchFile) {
556571
const fakeCommands = fake(commands, {
557572
run: () => Promise.resolve(),

0 commit comments

Comments
 (0)