Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Any way to check iframe loaded successfully?? #1361

Closed
fran0254 opened this issue Nov 11, 2017 · 10 comments
Closed

Any way to check iframe loaded successfully?? #1361

fran0254 opened this issue Nov 11, 2017 · 10 comments

Comments

@fran0254
Copy link

fran0254 commented Nov 11, 2017

yes work

await page.waitFor(2000); 
const frame = await page.frames().find(f => f.name() === 'ifrw');
const button = await frame.$('#selector');
button.click(); 

don´t work

// Was trying to select a iframe before it is actually loaded.
// Is possible check before, or wait for it to load ??
const frame = await page.frames().find(f => f.name() === 'ifrw');
const button = await frame.$('#selector');
button.click(); 
@ebidel
Copy link
Contributor

ebidel commented Nov 11, 2017

If you're using page.goto(), in that waits for the window load event to fire. So in theory, any frames on the page should also be loaded by that point in time.

If that's not working, you can use waitForSelector:

const frame = await page.frames().find(f => f.name() === 'ifrw');
await frame.waitForSelector('#selector');
const button = await frame.$('#selector');
await button.click();

Note: this will be easier with #1007, tracks waitForSelector returning Promise<ElementHandle> instead of Promise<undefined>.

@fran0254
Copy link
Author

I'm not using page.goto(), the frame is in a modal window within the same page. The way you indicated me has not worked for me

@aslushnikov
Copy link
Contributor

@fran0254 there are frame events that notify about frame structure changes:

You can wait until there's a desired frame attached with frameattached event.
Let me know if it doesn't work for you.

@fran0254
Copy link
Author

@aslushnikov Could you explain how I can check these three events that you mention to me?

attached the frame

Frame {
  _client: 
   Session {
     domain: null,
     _events: 
      { 'Page.frameAttached': [Function],
        'Page.frameNavigated': [Function],
        'Page.frameDetached': [Function],
        'Runtime.executionContextCreated': [Function],
        'Network.requestWillBeSent': [Function: bound _onRequestWillBeSent],
        'Network.requestIntercepted': [Function: bound _onRequestIntercepted],
        'Network.responseReceived': [Function: bound _onResponseReceived],
        'Network.loadingFinished': [Function: bound _onLoadingFinished],
        'Network.loadingFailed': [Function: bound _onLoadingFailed],
        'Page.loadEventFired': [Function],
        'Runtime.consoleAPICalled': [Function],
        'Page.javascriptDialogOpening': [Function],
        'Runtime.exceptionThrown': [Function],
        'Security.certificateError': [Function],
        'Inspector.targetCrashed': [Function],
        'Performance.metrics': [Function] },
     _eventsCount: 16,
     _maxListeners: undefined,
     _lastId: 142,
     _callbacks: Map {},
     _connection: 
      Connection {
        domain: null,
        _events: {},
        _eventsCount: 0,
        _maxListeners: undefined,
        _url: 'ws://127.0.0.1:45941/devtools/browser/75a70228-1c06-43fc-b1db-4bcb31ea555a',
        _lastId: 144,
        _callbacks: Map {},
        _delay: 0,
        _ws: [WebSocket],
        _sessions: [Map] },
     _targetId: '(4A708DD8E19462D630BAE640E87EFE61)',
     _sessionId: '(4A708DD8E19462D630BAE640E87EFE61):1' },
  _page: 
   Page {
     domain: null,
     _events: { dialog: [AsyncFunction] },
     _eventsCount: 1,
     _maxListeners: undefined,
     _client: 
      Session {
        domain: null,
        _events: [Object],
        _eventsCount: 16,
        _maxListeners: undefined,
        _lastId: 142,
        _callbacks: Map {},
        _connection: [Connection],
        _targetId: '(4A708DD8E19462D630BAE640E87EFE61)',
        _sessionId: '(4A708DD8E19462D630BAE640E87EFE61):1' },
     _keyboard: Keyboard { _client: [Session], _modifiers: 0, _pressedKeys: Set {} },
     _mouse: 
      Mouse {
        _client: [Session],
        _keyboard: [Keyboard],
        _x: 32.5,
        _y: 652,
        _button: 'none' },
     _touchscreen: Touchscreen { _client: [Session], _keyboard: [Keyboard] },
     _frameManager: 
      FrameManager {
        domain: null,
        _events: [Object],
        _eventsCount: 3,
        _maxListeners: undefined,
        _client: [Session],
        _page: [Circular],
        _frames: [Map],
        _contextIdToContext: [Map],
        _mainFrame: [Frame] },
     _networkManager: 
      NetworkManager {
        domain: null,
        _events: [Object],
        _eventsCount: 4,
        _maxListeners: undefined,
        _client: [Session],
        _requestIdToRequest: [Map],
        _interceptionIdToRequest: Map {},
        _extraHTTPHeaders: {},
        _offline: false,
        _credentials: null,
        _attemptedAuthentications: Set {},
        _userRequestInterceptionEnabled: false,
        _protocolRequestInterceptionEnabled: false,
        _requestHashToRequestIds: [Multimap],
        _requestHashToInterceptions: [Multimap] },
     _emulationManager: 
      EmulationManager {
        _client: [Session],
        _emulatingMobile: true,
        _injectedTouchScriptId: '1' },
     _tracing: Tracing { _client: [Session], _recording: false, _path: '' },
     _pageBindings: Map {},
     _ignoreHTTPSErrors: false,
     _screenshotTaskQueue: TaskQueue { _chain: [Promise] },
     _viewport: 
      { width: 375,
        height: 667,
        deviceScaleFactor: 2,
        isMobile: true,
        hasTouch: true,
        isLandscape: false } },
  _parentFrame: 
   Frame {
     _client: 
      Session {
        domain: null,
        _events: [Object],
        _eventsCount: 16,
        _maxListeners: undefined,
        _lastId: 142,
        _callbacks: Map {},
        _connection: [Connection],
        _targetId: '(4A708DD8E19462D630BAE640E87EFE61)',
        _sessionId: '(4A708DD8E19462D630BAE640E87EFE61):1' },
     _page: 
      Page {
        domain: null,
        _events: [Object],
        _eventsCount: 1,
        _maxListeners: undefined,
        _client: [Session],
        _keyboard: [Keyboard],
        _mouse: [Mouse],
        _touchscreen: [Touchscreen],
        _frameManager: [FrameManager],
        _networkManager: [NetworkManager],
        _emulationManager: [EmulationManager],
        _tracing: [Tracing],
        _pageBindings: Map {},
        _ignoreHTTPSErrors: false,
        _screenshotTaskQueue: [TaskQueue],
        _viewport: [Object] },
     _parentFrame: null,
     _url: 'https://www.milanuncios.com/mis-anuncios/?pagina=1201',
     _id: '(4A708DD8E19462D630BAE640E87EFE61)',
     _context: 
      ExecutionContext {
        _client: [Session],
        _contextId: 16,
        _objectHandleFactory: [Function: bound createJSHandle] },
     _waitTasks: Set {},
     _childFrames: Set { [Frame], [Frame], [Frame], [Circular] },
     _name: undefined,
     _loadingFailed: false },
  _url: 'https://www.milanuncios.com/renovar/?id=245463427',
  _id: '(6E766493375121224990C9457A8F3AF7)',
  _context: 
   ExecutionContext {
     _client: 
      Session {
        domain: null,
        _events: [Object],
        _eventsCount: 16,
        _maxListeners: undefined,
        _lastId: 142,
        _callbacks: Map {},
        _connection: [Connection],
        _targetId: '(4A708DD8E19462D630BAE640E87EFE61)',
        _sessionId: '(4A708DD8E19462D630BAE640E87EFE61):1' },
     _contextId: 55,
     _objectHandleFactory: [Function: bound createJSHandle] },
  _waitTasks: Set {},
  _childFrames: 
   Set {
     Frame {
     _client: [Session],
     _page: [Page],
     _parentFrame: [Circular],
     _url: 'https://vars.hotjar.com/rcj-99d43ead6bdf30da8ed5ffcb4f17100c.html',
     _id: '(A8BF5BD0B465B80948EF2963DD0BA529)',
     _context: [ExecutionContext],
     _waitTasks: Set {},
     _childFrames: Set {},
     _name: '_hjRemoteVarsFrame',
     _loadingFailed: false } },
  _name: 'ifrw',
  _loadingFailed: false }

@aslushnikov
Copy link
Contributor

@fran0254 sure.

So you had the following that works and want to get rid of timeout:

await page.waitFor(2000);  // <-- we want to get rid of this timeout!
const frame = page.frames().find(f => f.name() === 'ifrw'); // nit: no need to await
const button = await frame.$('#selector');
button.click(); 

For this, you can come up with a helper function waitForFrame:

function waitForFrame(page) {
  let fulfill;
  const promise = new Promise(x => fulfill = x);
  checkFrame();
  return promise;

  function checkFrame() {
    const frame = page.frames().find(f => f.name() === 'ifrw');
    if (frame)
      fulfill(frame);
    else
      page.once('frameattached', checkFrame);
  }
}

and use it later like this:

// 1. waiting for frame with name 'ifrw' to get attached
const frame = await waitForFrame(page); 
// 2. waiting for the frame to contain the necessary selector
await frame.waitForSelector('#selector');
const button = await frame.$('#selector');
button.click(); 

Note the step (2): iframe will be attached first and then navigated to its url, so we want to make sure the button exists before clicking.

@ebidel
Copy link
Contributor

ebidel commented Nov 12, 2017

@aslushnikov The original posts mentioned knowing when a "frame is loaded". Is frameattached or framenavigated guaranteed to happen after window.onload? And where does that fall in relation to the other waitUntil timings?

@fran0254
Copy link
Author

works perfect for me. Thank you

@stackflows
Copy link

Actually, I do not think that this solves the issue at hand: It should be possible to "waitUntil" a frame is loaded without watching for events. This would be a great addition to the functionality of the frame class and in consequence also for page.

@jcppython
Copy link

How to get the status of the iframe, as response.status using page.goto?

@aslushnikov
Copy link
Contributor

@jcppython you can track all requests using 'request' event, and then pick the suitable response:

const requestPerFrame = new Map();
const page = await browser.newPage();
page.on('request', request => {
  if (request.isNavigationRequest())
    requestPerFrame.set(request.frame(), request);
});
await page.goto('https://example.com');
const someFrame = page.frames()[1];
const frameNavigationResponse = requestPerFrame.get(someFrame).response();

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

No branches or pull requests

5 participants