Кукловод |Подождите, пока все JavaScript выполняется - PullRequest
0 голосов
/ 26 ноября 2018

Я пытаюсь сделать скриншоты с нескольких страниц, которые должны быть полностью загружены (включая лениво загруженные изображения) для последующего сравнения.

Я нашел пример lazyimages_without_scroll_events.js , который очень помогает.

С помощью следующего кода снимки экрана выглядят нормально, но есть одна серьезная проблема.

async function takeScreenshot(browser, viewport, route) {
  return browser.newPage().then(async (page) => {
    const fileName = `${viewport.directory}/${getFilename(route)}`;

    await page.setViewport({
      width: viewport.width,
      height: 500,
    });
    await page.goto(
        `${config.server.master}${route}.html`,
        {
          waitUntil: 'networkidle0',
        }
    );
    await page.evaluate(() => {
      /* global document,requestAnimationFrame */
      let lastScrollTop = document.scrollingElement.scrollTop;

      // Scroll to bottom of page until we can't scroll anymore.
      const scroll = () => {
        document.scrollingElement.scrollTop += 100;
        if (document.scrollingElement.scrollTop !== lastScrollTop) {
          lastScrollTop = document.scrollingElement.scrollTop;
          requestAnimationFrame(scroll);
        }
      };
      scroll();
    });
    await page.waitFor(5000);
    await page.screenshot({
      path: `screenshots/master/${fileName}.png`,
      fullPage: true,
    });

    await page.close();
    console.log(`Viewport "${viewport.name}", Route "${route}"`);
  });
}

Проблема : Даже с более высокими значениями для page.waitFor() (timeout), иногда не все связанные с веб-интерфейсом JavaScripts на страницах выполнялись полностью.

Для некоторых старых страниц, где JavaScript мог изменить внешний интерфейс.Например, в одном унаследованном случае a jQuery.matchHeight.

Наилучший случай : В идеальном мире Puppeteer будет ждать, пока весь JavaScript не будет оценен и выполнен. Возможно ли что-то подобное?


EDIT
Я мог бы немного улучшить скрипт с помощью cody-g.

function jQueryMatchHeightIsProcessed() {
  return Array.from($('.match-height')).every((element) => {
    return element.style.height !== '';
  });
}

// Within takeScreenshot() after page.waitFor()
await page.waitForFunction(jQueryMatchHeightIsProcessed, {timeout: 0});

... но это далеко не идеально.Кажется, мне нужно найти похожие решения для разных сценариев веб-интерфейса, чтобы реально рассмотреть все, что происходит на целевой странице.

Основная проблема с jQuery.matchHeight в моем случае заключается в том, что он обрабатывает разные высоты в разных прогонах.Может быть вызвано ленивой загрузкой изображения.Кажется, мне нужно подождать, пока я смогу заменить его на Flexbox.(^ _ ^) °

Другие проблемы, которые необходимо исправить:

Отключение анимации:

await page.addStyleTag({
  content: `
    * {
      transition: none !important;
      animation: none !important;
    }
  `,
});

Обработка слайд-шоу:

function handleSwiperSlideshows() {
  Array.from($('.swiper-container')).forEach((element) => {
    if (typeof element.swiper !== 'undefined') {
      if (element.swiper.autoplaying) {
        element.swiper.stopAutoplay();
        element.swiper.slideTo(0);
      }
    }
  });
}

// Within takeScreenshot() after page.waitFor()
await page.evaluate(handleSwiperSlideshows);

Но все еще нетдовольно.Я думаю, что невозможно визуально проверить эти устаревшие страницы.

Ответы [ 2 ]

0 голосов
/ 26 ноября 2018
async function takeScreenshot(browser, viewport, route) {
  return browser.newPage().then(async (page) => {
    const fileName = `${viewport.directory}/${getFilename(route)}`;

    await page.setViewport({
      width: viewport.width,
      height: 500,
    });
    await page.goto(
        `${config.server.master}${route}.html`,
        {
          waitUntil: 'networkidle0',
        }
    );
    await page.evaluate(() => {
      scroll(0, 99999)
    });
    await page.waitFor(5000);
    await page.screenshot({
      path: `screenshots/master/${fileName}.png`,
      fullPage: true,
    });

    await page.close();
    console.log(`Viewport "${viewport.name}", Route "${route}"`);
  });
}
0 голосов
/ 26 ноября 2018

Следующая waitForFunction может быть полезна для вас, вы можете использовать ее для ожидания любой произвольной функции, которая оценивается как true.Если у вас есть доступ к коду страницы, вы можете установить статус окна и использовать его, чтобы уведомить кукловода, что безопасно продолжить или просто полагаться на какое-то другое состояние готовности. Примечание: эта функция является функцией опроса и переоценивает ее через некоторый интервал, который можно указать.

const watchDog = page.waitForFunction('<your function to evaluate to true>');

Например,

const watchDog = page.waitForFunction('window.status === "ready"');
await watchDog;

В вашей страницекод, вам просто нужно установить window.status на ready

Чтобы использовать несколько сторожевых таймеров в нескольких асинхронных файлах, вы можете сделать что-то вроде

index.js

...import/require file1.js;
...import/require file2.js;
...code...

file1.js:

var file1Flag=false; // global
...code...
file1Flag=true;

file2.js:

var file2Flag=false; // global
...code...
file2Flag=true;

main.js:

const watchDog = page.waitForFunction('file1Flag && file2Flag');
await watchDog;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...