-
Notifications
You must be signed in to change notification settings - Fork 354
Add tests for launching/attaching to chrome #831
Conversation
test/int/adapter.test.ts
Outdated
const DEBUGGER_LINE = 2; | ||
|
||
server = createServer({ root: testProjectRoot }); | ||
server.listen(7890); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code is similar to line 118 and to the should stop on debugger statement in http://localhost test
Is there any way we can avoid duplicating it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed. We set this up in the setup()
for this suite now
test/int/adapter.test.ts
Outdated
|
||
console.log('killing all instances of chrome'); | ||
// force kill chrome here, as it will be left open by the debug adapter (same behavior as v1) | ||
const killCmd = (process.platform === 'win32') ? 'taskkill /F /IM chrome.exe /T' : 'killall chrome'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code is similar to the code in testSetup.tearDown. Would it be possible to unify it?
Is this behavior undesirable? If so, we should add a TODO to fix it after we release v2.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It can make troubleshooting easier. If you start Chrome, fail to attach, then kill Chrome, sometimes people might think that Chrome never actually started.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I definitely think we need to look at changing the behavior for V2 after we get the initial release out, because what essentially happens here is that the debugger attaches properly but expects to find an "about:blank" page, which we launch to when we launch chrome. If a user already has an instance of chrome running with the debug flag, it won't have that about:blank page, and the debugger bails, even if it might have been able to recover.
For now I'll create a "kill all instance of chrome" function that will get rid of the duplicated code.
|
||
const DATA_ROOT = testSetup.DATA_ROOT; | ||
|
||
suite('Chrome Debug Adapter etc', function () { | ||
suite('Chrome Debug Adapter etc', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mocha suggests using normal functions instead of arrow functions, so we can access the this pointer if needed: https://mochajs.org/#arrow-functions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can still do this with arrow functions: https://stackoverflow.com/questions/15971167/how-to-increase-timeout-for-a-single-test-case-in-mocha. I would vote for using arrow functions here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, the reason I changed this to an arrow function was mainly just because of our lint rules that will flag any regular function
declarations, and were red-lining the entire test in the editor. The other option is just to add tslint exceptions for all the tests, but that's also kind of annoying. There's a big long discussion about arrow functions vs normal here. There's been some chatter about redesigns in mocha to better support arrow functions, but so far it doesn't seem to have gone anywhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW, Jasmine also recommends function
over ()=>{}
https://stackoverflow.com/questions/38915090/are-arrow-functions-recommended-in-jasmine-test-cases.
Personally, I'd prefer to use arrow functions almost everywhere since it makes javascript behave more like C#, Java, and others in regards to this
, and of course I'm more familiar with those languages, but it seems like the JS community (at least right now) still relies pretty heavily on the current this
behavior.
So I can go either way on this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's use the arrow function then. If we ever need to do something which the only way to do it is to get the this pointer, then we can change that particular call to use a function instead.
test/int/adapter.test.ts
Outdated
|
||
server = createServer({ root: testProjectRoot }); | ||
server.listen(7890); | ||
const browser = await puppeteer.launch(<puppeteer.LaunchOptions>{ headless: false, args: ['http://localhost:7890', '--remote-debugging-port=7777'] }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this cast needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not needed for anything except intellisense. For whatever reason, VS Code doesn't provide intellisense on anonymous objects, even when the type of the argument is known for that function unless you provide a type assertion. We can remove it if you'd prefer, I typically just toss them on there when I need to check what the possible values can be.
**EDIT: figured out the problem on my end with the intellisense, turns out it was an extension (TypeScript Importer) causing the problems just for me.
@@ -30,7 +30,8 @@ class NotYetLaunched implements IChromeLauncherLifetimeState { | |||
} | |||
|
|||
public stop(): Promise<void> { | |||
throw new Error(`Can't stop the chrome process because it hasn't been launched yet`); | |||
// no-op here because in the case that we attach to an existing instance the launcher will still be in this state | |||
return new Promise(a => a()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Promise.resolve()
test/int/adapter.test.ts
Outdated
|
||
console.log('killing all instances of chrome'); | ||
// force kill chrome here, as it will be left open by the debug adapter (same behavior as v1) | ||
const killCmd = (process.platform === 'win32') ? 'taskkill /F /IM chrome.exe /T' : 'killall chrome'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It can make troubleshooting easier. If you start Chrome, fail to attach, then kill Chrome, sometimes people might think that Chrome never actually started.
try { | ||
await Promise.all([ | ||
dc.configurationSequence(), | ||
dc.launch({ url: 'http://localhost:7890', timeout: 2000, webRoot: testProjectRoot }), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd specify the port here as an explicit parameter, to make it clearer that we are going to be using the same port...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
dc.launch({ url: 'http://localhost:7890', timeout: 2000, webRoot: testProjectRoot }), | ||
]); | ||
} catch (err) { | ||
expect(err.message).to.satisfy( (x: string) => x.startsWith('Cannot connect to runtime process, timeout after 2000 ms')); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will this test fail if dc.launch somehow succeeds?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. Right now since we're just baselining V1 behavior, we are expecting this to throw an exception. Once we decide it's an appropriate time to fix this, then we can change the test accordingly. I'll add a note in the test that explains this so that it's clear what we're expecting from the test
test/int/adapter.test.ts
Outdated
dc.assertStoppedLocation('debugger_statement', { path: breakFile, line: DEBUGGER_LINE } ) | ||
]); | ||
|
||
await browser.close(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be a good idea to put the .close() in a finally block, so we'll close the browser even if the test fails...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good suggestion. I added a finally block for both tests that close with puppeteer.
test/testUtils.ts
Outdated
* Kills all running instances of chrome on the test host | ||
*/ | ||
export function killAllChrome() { | ||
const killCmd = (process.platform === 'win32') ? 'taskkill /F /IM chrome.exe /T' : 'killall chrome'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will this kill all the chrome.exe instances on my desktop every time I run the tests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. Unless there's an easy way to get the PID of the instance that the debug adapter launched so we can just close that specific instance, I don't see another option other than just force killing all chrome instances here. Let me know if you know of a better way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tested on my PC and "wmic process where ExecutablePath='path goes here\chrome-win\chrome.exe' delete" can kill only the chrome.exe instances at a specific path
-Make debugging port explicit in tests -Put puppeteer browser.close() in finally blocks -Add context around the "should throw error when launching if chrome debug port is in use" test.
command. The kill command (or taskkill) will return with non-zero codes if the process is already dead. In which case, we don't care (we do the same thing elsewhere)
Adding tests for launching chrome (relies on microsoft/vscode-chrome-debug-core#438)