Skip to content

Conversation

@pavelfeldman
Copy link
Member

No description provided.

Deletes the downloaded file.

#### download.error()
- returns: <[Promise]<null|[string]>>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What kind of errors are returned here? When should I use this string?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WebKit will report network error here. If you did not pass acceptDownloads, you get canceled error as well.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this match the response.failure() api? It is equivalent right?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not equivalent, but it is similar, so i can rename.

const page = await context.newPage();
page._ownedContext = context;
return page;
export abstract class BrowserBase extends EventEmitter implements Browser {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Browser already extends EventEmitter

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My understanding is that Browser is an interface, so it can't extend class


async _initialize() {
const promises: Promise<any>[] = [
this._browser._session.send('Browser.setDownloadBehavior', {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't contextId be passed too?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes :)

import { Readable } from 'stream';

export class Download {
private _downloadsPath: string;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: readonly?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't do it systematically :/

import { helper } from '../helper';
import * as fs from 'fs';
import * as os from 'os';
import * as path from 'path';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: run 'Organize imports'?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure


export class InterceptingTransport implements ConnectionTransport {
private readonly _delegate: ConnectionTransport;
private _interceptor: (message: ProtocolRequest) => ProtocolRequest;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: readonly too?

this._page._frameManager.frameLifecycleEvent(frameId, event);
}

private _onDownloadCreated() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

revert?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

expect(fs.existsSync(path1)).toBeFalsy();
expect(fs.existsSync(path2)).toBeFalsy();
});
it.fail(true)('should delete downloads on browser gone', async ({ server, defaultBrowserOptions }) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unskip now that Joel has a fix?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As soon as it lands

}

_didCloseInternal() {
async _didCloseInternal(omitDeleteDownloads = false) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was hard for me to follow. Can we leave it as _didCloseInternal(), and add async deleteDownloads(). Is it important that the close event fires before the downloads have been deleted?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My worry is that it is easy to forget to call deleteDownloads. As of now, they know they need to call _didCloseInternal. Or what do you mean?

[/object/g, 'Object'],
[/Promise\<T\>/, 'Promise<Object>']
[/Promise\<T\>/, 'Promise<Object>'],
[/Readable/, 'stream.Readable']
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we leave this as Readable, it shouldn't need any special casing or overrides.

src/download.ts Outdated
return fileName;
}

async error(): Promise<string | null> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May be waitForFinished() ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ugly?

state._stderr.on('line', dumperr);
if (dumpProtocolOnFailure)
state.browser._setDebugFunction(data => test.output.push(`\x1b[32m[pw:protocol]\x1b[0m ${data}`));
debug('pw:protocol').output = data => test.output.push(`\x1b[32m[pw:protocol]\x1b[0m ${data}`);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in my console: debug('str') !== debug('str')
How does this work?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question.

#### event: 'download'
- <[Download]>

Emitted when attachment is downloaded. User can access basic file operations on downloaded content via the passed [Download] instance. Browser context must be created with the `acceptDownloads` set to `true` when user needs access to the downloaded content. If `acceptDownloads` is not set or set to `false`, download events are emitted, but the actual download is not performed and user has no access to the downloaded files.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

super nit: we don't usually mention "user" in the docs.

async path(): Promise<string | null> {
if (!this._acceptDownloads)
throw new Error('Pass { acceptDownloads: true } when you are creating your browser context.');
const fileName = path.join(this._downloadsPath, this._uuid);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a way to retrieve suggested file name, extension, mime type or url? I imagine that would be very handy, e.g. to assert that my "Download" button tries to download the "screenshot-{current-time}.png" file.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that'd be super handy. Follow up?

async delete(): Promise<void> {
if (!this._acceptDownloads || this._deleted)
return;
const fileName = await this.path();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should check _deleted after this await to avoid a race.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

src/download.ts Outdated
return;
const fileName = await this.path();
this._deleted = true;
if (fileName && await util.promisify(fs.exists)(fileName))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Asynchronous exists check is racy. Better to always call unlink and catch ENOENT error.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

await browser.close();
expect(fs.existsSync(path1)).toBeFalsy();
expect(fs.existsSync(path2)).toBeFalsy();
console.log(path.join(path1, '..'));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stray log

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

expect(fs.existsSync(path.join(path1, '..'))).toBeFalsy();
});
it('make coverage happy', async({page}) => {
// Otherwise FF gets mad.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a list of not covered methods in playwright.spec.js.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

state._stderr.off('line', dumperr);
if (dumpProtocolOnFailure)
state.browser._setDebugFunction(() => void 0);
debug('pw:protocol').output = data => console.log;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what this meant to be, but looks suspicious :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

}
}

export class InterceptingTransport implements ConnectionTransport {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is this one used?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nowhere just yet, but looks generally useful?

@pavelfeldman pavelfeldman merged commit 75571e8 into microsoft:master Apr 3, 2020
@pavelfeldman pavelfeldman deleted the fe_download branch April 17, 2020 21:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants