diff --git a/__snapshots__/lighthouse.test.ts.js b/__snapshots__/lighthouse.test.ts.js index a498d191..58d590a7 100644 --- a/__snapshots__/lighthouse.test.ts.js +++ b/__snapshots__/lighthouse.test.ts.js @@ -87,133 +87,6 @@ const puppeteer = require('puppeteer'); // v20.7.4 or later await browser.close(); - async function waitForElement(step, frame, timeout) { - const { - count = 1, - operator = '>=', - visible = true, - properties, - attributes, - } = step; - const compFn = { - '==': (a, b) => a === b, - '>=': (a, b) => a >= b, - '<=': (a, b) => a <= b, - }[operator]; - await waitForFunction(async () => { - const elements = await querySelectorsAll(step.selectors, frame); - let result = compFn(elements.length, count); - const elementsHandle = await frame.evaluateHandle((...elements) => { - return elements; - }, ...elements); - await Promise.all(elements.map((element) => element.dispose())); - if (result && (properties || attributes)) { - result = await elementsHandle.evaluate( - (elements, properties, attributes) => { - for (const element of elements) { - if (attributes) { - for (const [name, value] of Object.entries(attributes)) { - if (element.getAttribute(name) !== value) { - return false; - } - } - } - if (properties) { - if (!isDeepMatch(properties, element)) { - return false; - } - } - } - return true; - - function isDeepMatch(a, b) { - if (a === b) { - return true; - } - if ((a && !b) || (!a && b)) { - return false; - } - if (!(a instanceof Object) || !(b instanceof Object)) { - return false; - } - for (const [key, value] of Object.entries(a)) { - if (!isDeepMatch(value, b[key])) { - return false; - } - } - return true; - } - }, - properties, - attributes - ); - } - await elementsHandle.dispose(); - return result === visible; - }, timeout); - } - - async function querySelectorsAll(selectors, frame) { - for (const selector of selectors) { - const result = await querySelectorAll(selector, frame); - if (result.length) { - return result; - } - } - return []; - } - - async function querySelectorAll(selector, frame) { - if (!Array.isArray(selector)) { - selector = [selector]; - } - if (!selector.length) { - throw new Error('Empty selector provided to querySelectorAll'); - } - let elements = []; - for (let i = 0; i < selector.length; i++) { - const part = selector[i]; - if (i === 0) { - elements = await frame.$$(part); - } else { - const tmpElements = elements; - elements = []; - for (const el of tmpElements) { - elements.push(...(await el.$$(part))); - } - } - if (elements.length === 0) { - return []; - } - if (i < selector.length - 1) { - const tmpElements = []; - for (const el of elements) { - const newEl = (await el.evaluateHandle(el => el.shadowRoot ? el.shadowRoot : el)).asElement(); - if (newEl) { - tmpElements.push(newEl); - } - } - elements = tmpElements; - } - } - return elements; - } - - async function waitForFunction(fn, timeout) { - let isActive = true; - const timeoutId = setTimeout(() => { - isActive = false; - }, timeout); - while (isActive) { - const result = await fn(); - if (result) { - clearTimeout(timeoutId); - return; - } - await new Promise(resolve => setTimeout(resolve, 100)); - } - throw new Error('Timed out'); - } })().catch(err => { console.error(err); process.exit(1); diff --git a/__snapshots__/stringify.test.ts.js b/__snapshots__/stringify.test.ts.js index c638cd67..adcb6c1a 100644 --- a/__snapshots__/stringify.test.ts.js +++ b/__snapshots__/stringify.test.ts.js @@ -14,133 +14,6 @@ const puppeteer = require('puppeteer'); // v20.7.4 or later await browser.close(); - async function waitForElement(step, frame, timeout) { - const { - count = 1, - operator = '>=', - visible = true, - properties, - attributes, - } = step; - const compFn = { - '==': (a, b) => a === b, - '>=': (a, b) => a >= b, - '<=': (a, b) => a <= b, - }[operator]; - await waitForFunction(async () => { - const elements = await querySelectorsAll(step.selectors, frame); - let result = compFn(elements.length, count); - const elementsHandle = await frame.evaluateHandle((...elements) => { - return elements; - }, ...elements); - await Promise.all(elements.map((element) => element.dispose())); - if (result && (properties || attributes)) { - result = await elementsHandle.evaluate( - (elements, properties, attributes) => { - for (const element of elements) { - if (attributes) { - for (const [name, value] of Object.entries(attributes)) { - if (element.getAttribute(name) !== value) { - return false; - } - } - } - if (properties) { - if (!isDeepMatch(properties, element)) { - return false; - } - } - } - return true; - - function isDeepMatch(a, b) { - if (a === b) { - return true; - } - if ((a && !b) || (!a && b)) { - return false; - } - if (!(a instanceof Object) || !(b instanceof Object)) { - return false; - } - for (const [key, value] of Object.entries(a)) { - if (!isDeepMatch(value, b[key])) { - return false; - } - } - return true; - } - }, - properties, - attributes - ); - } - await elementsHandle.dispose(); - return result === visible; - }, timeout); - } - - async function querySelectorsAll(selectors, frame) { - for (const selector of selectors) { - const result = await querySelectorAll(selector, frame); - if (result.length) { - return result; - } - } - return []; - } - - async function querySelectorAll(selector, frame) { - if (!Array.isArray(selector)) { - selector = [selector]; - } - if (!selector.length) { - throw new Error('Empty selector provided to querySelectorAll'); - } - let elements = []; - for (let i = 0; i < selector.length; i++) { - const part = selector[i]; - if (i === 0) { - elements = await frame.$$(part); - } else { - const tmpElements = elements; - elements = []; - for (const el of tmpElements) { - elements.push(...(await el.$$(part))); - } - } - if (elements.length === 0) { - return []; - } - if (i < selector.length - 1) { - const tmpElements = []; - for (const el of elements) { - const newEl = (await el.evaluateHandle(el => el.shadowRoot ? el.shadowRoot : el)).asElement(); - if (newEl) { - tmpElements.push(newEl); - } - } - elements = tmpElements; - } - } - return elements; - } - - async function waitForFunction(fn, timeout) { - let isActive = true; - const timeoutId = setTimeout(() => { - isActive = false; - }, timeout); - while (isActive) { - const result = await fn(); - if (result) { - clearTimeout(timeoutId); - return; - } - await new Promise(resolve => setTimeout(resolve, 100)); - } - throw new Error('Timed out'); - } })().catch(err => { console.error(err); process.exit(1); @@ -172,133 +45,6 @@ const puppeteer = require('puppeteer'); // v20.7.4 or later await browser.close(); - async function waitForElement(step, frame, timeout) { - const { - count = 1, - operator = '>=', - visible = true, - properties, - attributes, - } = step; - const compFn = { - '==': (a, b) => a === b, - '>=': (a, b) => a >= b, - '<=': (a, b) => a <= b, - }[operator]; - await waitForFunction(async () => { - const elements = await querySelectorsAll(step.selectors, frame); - let result = compFn(elements.length, count); - const elementsHandle = await frame.evaluateHandle((...elements) => { - return elements; - }, ...elements); - await Promise.all(elements.map((element) => element.dispose())); - if (result && (properties || attributes)) { - result = await elementsHandle.evaluate( - (elements, properties, attributes) => { - for (const element of elements) { - if (attributes) { - for (const [name, value] of Object.entries(attributes)) { - if (element.getAttribute(name) !== value) { - return false; - } - } - } - if (properties) { - if (!isDeepMatch(properties, element)) { - return false; - } - } - } - return true; - - function isDeepMatch(a, b) { - if (a === b) { - return true; - } - if ((a && !b) || (!a && b)) { - return false; - } - if (!(a instanceof Object) || !(b instanceof Object)) { - return false; - } - for (const [key, value] of Object.entries(a)) { - if (!isDeepMatch(value, b[key])) { - return false; - } - } - return true; - } - }, - properties, - attributes - ); - } - await elementsHandle.dispose(); - return result === visible; - }, timeout); - } - - async function querySelectorsAll(selectors, frame) { - for (const selector of selectors) { - const result = await querySelectorAll(selector, frame); - if (result.length) { - return result; - } - } - return []; - } - - async function querySelectorAll(selector, frame) { - if (!Array.isArray(selector)) { - selector = [selector]; - } - if (!selector.length) { - throw new Error('Empty selector provided to querySelectorAll'); - } - let elements = []; - for (let i = 0; i < selector.length; i++) { - const part = selector[i]; - if (i === 0) { - elements = await frame.$$(part); - } else { - const tmpElements = elements; - elements = []; - for (const el of tmpElements) { - elements.push(...(await el.$$(part))); - } - } - if (elements.length === 0) { - return []; - } - if (i < selector.length - 1) { - const tmpElements = []; - for (const el of elements) { - const newEl = (await el.evaluateHandle(el => el.shadowRoot ? el.shadowRoot : el)).asElement(); - if (newEl) { - tmpElements.push(newEl); - } - } - elements = tmpElements; - } - } - return elements; - } - - async function waitForFunction(fn, timeout) { - let isActive = true; - const timeoutId = setTimeout(() => { - isActive = false; - }, timeout); - while (isActive) { - const result = await fn(); - if (result) { - clearTimeout(timeoutId); - return; - } - await new Promise(resolve => setTimeout(resolve, 100)); - } - throw new Error('Timed out'); - } })().catch(err => { console.error(err); process.exit(1); @@ -336,133 +82,6 @@ const puppeteer = require('puppeteer'); // v20.7.4 or later await browser.close(); - async function waitForElement(step, frame, timeout) { - const { - count = 1, - operator = '>=', - visible = true, - properties, - attributes, - } = step; - const compFn = { - '==': (a, b) => a === b, - '>=': (a, b) => a >= b, - '<=': (a, b) => a <= b, - }[operator]; - await waitForFunction(async () => { - const elements = await querySelectorsAll(step.selectors, frame); - let result = compFn(elements.length, count); - const elementsHandle = await frame.evaluateHandle((...elements) => { - return elements; - }, ...elements); - await Promise.all(elements.map((element) => element.dispose())); - if (result && (properties || attributes)) { - result = await elementsHandle.evaluate( - (elements, properties, attributes) => { - for (const element of elements) { - if (attributes) { - for (const [name, value] of Object.entries(attributes)) { - if (element.getAttribute(name) !== value) { - return false; - } - } - } - if (properties) { - if (!isDeepMatch(properties, element)) { - return false; - } - } - } - return true; - - function isDeepMatch(a, b) { - if (a === b) { - return true; - } - if ((a && !b) || (!a && b)) { - return false; - } - if (!(a instanceof Object) || !(b instanceof Object)) { - return false; - } - for (const [key, value] of Object.entries(a)) { - if (!isDeepMatch(value, b[key])) { - return false; - } - } - return true; - } - }, - properties, - attributes - ); - } - await elementsHandle.dispose(); - return result === visible; - }, timeout); - } - - async function querySelectorsAll(selectors, frame) { - for (const selector of selectors) { - const result = await querySelectorAll(selector, frame); - if (result.length) { - return result; - } - } - return []; - } - - async function querySelectorAll(selector, frame) { - if (!Array.isArray(selector)) { - selector = [selector]; - } - if (!selector.length) { - throw new Error('Empty selector provided to querySelectorAll'); - } - let elements = []; - for (let i = 0; i < selector.length; i++) { - const part = selector[i]; - if (i === 0) { - elements = await frame.$$(part); - } else { - const tmpElements = elements; - elements = []; - for (const el of tmpElements) { - elements.push(...(await el.$$(part))); - } - } - if (elements.length === 0) { - return []; - } - if (i < selector.length - 1) { - const tmpElements = []; - for (const el of elements) { - const newEl = (await el.evaluateHandle(el => el.shadowRoot ? el.shadowRoot : el)).asElement(); - if (newEl) { - tmpElements.push(newEl); - } - } - elements = tmpElements; - } - } - return elements; - } - - async function waitForFunction(fn, timeout) { - let isActive = true; - const timeoutId = setTimeout(() => { - isActive = false; - }, timeout); - while (isActive) { - const result = await fn(); - if (result) { - clearTimeout(timeoutId); - return; - } - await new Promise(resolve => setTimeout(resolve, 100)); - } - throw new Error('Timed out'); - } })().catch(err => { console.error(err); process.exit(1); @@ -499,133 +118,6 @@ const puppeteer = require('puppeteer'); // v20.7.4 or later await browser.close(); - async function waitForElement(step, frame, timeout) { - const { - count = 1, - operator = '>=', - visible = true, - properties, - attributes, - } = step; - const compFn = { - '==': (a, b) => a === b, - '>=': (a, b) => a >= b, - '<=': (a, b) => a <= b, - }[operator]; - await waitForFunction(async () => { - const elements = await querySelectorsAll(step.selectors, frame); - let result = compFn(elements.length, count); - const elementsHandle = await frame.evaluateHandle((...elements) => { - return elements; - }, ...elements); - await Promise.all(elements.map((element) => element.dispose())); - if (result && (properties || attributes)) { - result = await elementsHandle.evaluate( - (elements, properties, attributes) => { - for (const element of elements) { - if (attributes) { - for (const [name, value] of Object.entries(attributes)) { - if (element.getAttribute(name) !== value) { - return false; - } - } - } - if (properties) { - if (!isDeepMatch(properties, element)) { - return false; - } - } - } - return true; - - function isDeepMatch(a, b) { - if (a === b) { - return true; - } - if ((a && !b) || (!a && b)) { - return false; - } - if (!(a instanceof Object) || !(b instanceof Object)) { - return false; - } - for (const [key, value] of Object.entries(a)) { - if (!isDeepMatch(value, b[key])) { - return false; - } - } - return true; - } - }, - properties, - attributes - ); - } - await elementsHandle.dispose(); - return result === visible; - }, timeout); - } - - async function querySelectorsAll(selectors, frame) { - for (const selector of selectors) { - const result = await querySelectorAll(selector, frame); - if (result.length) { - return result; - } - } - return []; - } - - async function querySelectorAll(selector, frame) { - if (!Array.isArray(selector)) { - selector = [selector]; - } - if (!selector.length) { - throw new Error('Empty selector provided to querySelectorAll'); - } - let elements = []; - for (let i = 0; i < selector.length; i++) { - const part = selector[i]; - if (i === 0) { - elements = await frame.$$(part); - } else { - const tmpElements = elements; - elements = []; - for (const el of tmpElements) { - elements.push(...(await el.$$(part))); - } - } - if (elements.length === 0) { - return []; - } - if (i < selector.length - 1) { - const tmpElements = []; - for (const el of elements) { - const newEl = (await el.evaluateHandle(el => el.shadowRoot ? el.shadowRoot : el)).asElement(); - if (newEl) { - tmpElements.push(newEl); - } - } - elements = tmpElements; - } - } - return elements; - } - - async function waitForFunction(fn, timeout) { - let isActive = true; - const timeoutId = setTimeout(() => { - isActive = false; - }, timeout); - while (isActive) { - const result = await fn(); - if (result) { - clearTimeout(timeoutId); - return; - } - await new Promise(resolve => setTimeout(resolve, 100)); - } - throw new Error('Timed out'); - } })().catch(err => { console.error(err); process.exit(1); @@ -664,133 +156,6 @@ const puppeteer = require('puppeteer'); // v20.7.4 or later await browser.close(); - async function waitForElement(step, frame, timeout) { - const { - count = 1, - operator = '>=', - visible = true, - properties, - attributes, - } = step; - const compFn = { - '==': (a, b) => a === b, - '>=': (a, b) => a >= b, - '<=': (a, b) => a <= b, - }[operator]; - await waitForFunction(async () => { - const elements = await querySelectorsAll(step.selectors, frame); - let result = compFn(elements.length, count); - const elementsHandle = await frame.evaluateHandle((...elements) => { - return elements; - }, ...elements); - await Promise.all(elements.map((element) => element.dispose())); - if (result && (properties || attributes)) { - result = await elementsHandle.evaluate( - (elements, properties, attributes) => { - for (const element of elements) { - if (attributes) { - for (const [name, value] of Object.entries(attributes)) { - if (element.getAttribute(name) !== value) { - return false; - } - } - } - if (properties) { - if (!isDeepMatch(properties, element)) { - return false; - } - } - } - return true; - - function isDeepMatch(a, b) { - if (a === b) { - return true; - } - if ((a && !b) || (!a && b)) { - return false; - } - if (!(a instanceof Object) || !(b instanceof Object)) { - return false; - } - for (const [key, value] of Object.entries(a)) { - if (!isDeepMatch(value, b[key])) { - return false; - } - } - return true; - } - }, - properties, - attributes - ); - } - await elementsHandle.dispose(); - return result === visible; - }, timeout); - } - - async function querySelectorsAll(selectors, frame) { - for (const selector of selectors) { - const result = await querySelectorAll(selector, frame); - if (result.length) { - return result; - } - } - return []; - } - - async function querySelectorAll(selector, frame) { - if (!Array.isArray(selector)) { - selector = [selector]; - } - if (!selector.length) { - throw new Error('Empty selector provided to querySelectorAll'); - } - let elements = []; - for (let i = 0; i < selector.length; i++) { - const part = selector[i]; - if (i === 0) { - elements = await frame.$$(part); - } else { - const tmpElements = elements; - elements = []; - for (const el of tmpElements) { - elements.push(...(await el.$$(part))); - } - } - if (elements.length === 0) { - return []; - } - if (i < selector.length - 1) { - const tmpElements = []; - for (const el of elements) { - const newEl = (await el.evaluateHandle(el => el.shadowRoot ? el.shadowRoot : el)).asElement(); - if (newEl) { - tmpElements.push(newEl); - } - } - elements = tmpElements; - } - } - return elements; - } - - async function waitForFunction(fn, timeout) { - let isActive = true; - const timeoutId = setTimeout(() => { - isActive = false; - }, timeout); - while (isActive) { - const result = await fn(); - if (result) { - clearTimeout(timeoutId); - return; - } - await new Promise(resolve => setTimeout(resolve, 100)); - } - throw new Error('Timed out'); - } })().catch(err => { console.error(err); process.exit(1); @@ -815,133 +180,6 @@ const puppeteer = require('puppeteer'); // v20.7.4 or later await browser.close(); - async function waitForElement(step, frame, timeout) { - const { - count = 1, - operator = '>=', - visible = true, - properties, - attributes, - } = step; - const compFn = { - '==': (a, b) => a === b, - '>=': (a, b) => a >= b, - '<=': (a, b) => a <= b, - }[operator]; - await waitForFunction(async () => { - const elements = await querySelectorsAll(step.selectors, frame); - let result = compFn(elements.length, count); - const elementsHandle = await frame.evaluateHandle((...elements) => { - return elements; - }, ...elements); - await Promise.all(elements.map((element) => element.dispose())); - if (result && (properties || attributes)) { - result = await elementsHandle.evaluate( - (elements, properties, attributes) => { - for (const element of elements) { - if (attributes) { - for (const [name, value] of Object.entries(attributes)) { - if (element.getAttribute(name) !== value) { - return false; - } - } - } - if (properties) { - if (!isDeepMatch(properties, element)) { - return false; - } - } - } - return true; - - function isDeepMatch(a, b) { - if (a === b) { - return true; - } - if ((a && !b) || (!a && b)) { - return false; - } - if (!(a instanceof Object) || !(b instanceof Object)) { - return false; - } - for (const [key, value] of Object.entries(a)) { - if (!isDeepMatch(value, b[key])) { - return false; - } - } - return true; - } - }, - properties, - attributes - ); - } - await elementsHandle.dispose(); - return result === visible; - }, timeout); - } - - async function querySelectorsAll(selectors, frame) { - for (const selector of selectors) { - const result = await querySelectorAll(selector, frame); - if (result.length) { - return result; - } - } - return []; - } - - async function querySelectorAll(selector, frame) { - if (!Array.isArray(selector)) { - selector = [selector]; - } - if (!selector.length) { - throw new Error('Empty selector provided to querySelectorAll'); - } - let elements = []; - for (let i = 0; i < selector.length; i++) { - const part = selector[i]; - if (i === 0) { - elements = await frame.$$(part); - } else { - const tmpElements = elements; - elements = []; - for (const el of tmpElements) { - elements.push(...(await el.$$(part))); - } - } - if (elements.length === 0) { - return []; - } - if (i < selector.length - 1) { - const tmpElements = []; - for (const el of elements) { - const newEl = (await el.evaluateHandle(el => el.shadowRoot ? el.shadowRoot : el)).asElement(); - if (newEl) { - tmpElements.push(newEl); - } - } - elements = tmpElements; - } - } - return elements; - } - - async function waitForFunction(fn, timeout) { - let isActive = true; - const timeoutId = setTimeout(() => { - isActive = false; - }, timeout); - while (isActive) { - const result = await fn(); - if (result) { - clearTimeout(timeoutId); - return; - } - await new Promise(resolve => setTimeout(resolve, 100)); - } - throw new Error('Timed out'); - } })().catch(err => { console.error(err); process.exit(1); @@ -964,135 +202,8 @@ const puppeteer = require('puppeteer'); // v20.7.4 or later await targetPage.keyboard.up('E'); } - await browser.close(); - - async function waitForElement(step, frame, timeout) { - const { - count = 1, - operator = '>=', - visible = true, - properties, - attributes, - } = step; - const compFn = { - '==': (a, b) => a === b, - '>=': (a, b) => a >= b, - '<=': (a, b) => a <= b, - }[operator]; - await waitForFunction(async () => { - const elements = await querySelectorsAll(step.selectors, frame); - let result = compFn(elements.length, count); - const elementsHandle = await frame.evaluateHandle((...elements) => { - return elements; - }, ...elements); - await Promise.all(elements.map((element) => element.dispose())); - if (result && (properties || attributes)) { - result = await elementsHandle.evaluate( - (elements, properties, attributes) => { - for (const element of elements) { - if (attributes) { - for (const [name, value] of Object.entries(attributes)) { - if (element.getAttribute(name) !== value) { - return false; - } - } - } - if (properties) { - if (!isDeepMatch(properties, element)) { - return false; - } - } - } - return true; - - function isDeepMatch(a, b) { - if (a === b) { - return true; - } - if ((a && !b) || (!a && b)) { - return false; - } - if (!(a instanceof Object) || !(b instanceof Object)) { - return false; - } - for (const [key, value] of Object.entries(a)) { - if (!isDeepMatch(value, b[key])) { - return false; - } - } - return true; - } - }, - properties, - attributes - ); - } - await elementsHandle.dispose(); - return result === visible; - }, timeout); - } - - async function querySelectorsAll(selectors, frame) { - for (const selector of selectors) { - const result = await querySelectorAll(selector, frame); - if (result.length) { - return result; - } - } - return []; - } - - async function querySelectorAll(selector, frame) { - if (!Array.isArray(selector)) { - selector = [selector]; - } - if (!selector.length) { - throw new Error('Empty selector provided to querySelectorAll'); - } - let elements = []; - for (let i = 0; i < selector.length; i++) { - const part = selector[i]; - if (i === 0) { - elements = await frame.$$(part); - } else { - const tmpElements = elements; - elements = []; - for (const el of tmpElements) { - elements.push(...(await el.$$(part))); - } - } - if (elements.length === 0) { - return []; - } - if (i < selector.length - 1) { - const tmpElements = []; - for (const el of elements) { - const newEl = (await el.evaluateHandle(el => el.shadowRoot ? el.shadowRoot : el)).asElement(); - if (newEl) { - tmpElements.push(newEl); - } - } - elements = tmpElements; - } - } - return elements; - } - - async function waitForFunction(fn, timeout) { - let isActive = true; - const timeoutId = setTimeout(() => { - isActive = false; - }, timeout); - while (isActive) { - const result = await fn(); - if (result) { - clearTimeout(timeoutId); - return; - } - await new Promise(resolve => setTimeout(resolve, 100)); - } - throw new Error('Timed out'); - } + await browser.close(); + })().catch(err => { console.error(err); process.exit(1); @@ -1125,133 +236,6 @@ const puppeteer = require('puppeteer'); // v20.7.4 or later await browser.close(); - async function waitForElement(step, frame, timeout) { - const { - count = 1, - operator = '>=', - visible = true, - properties, - attributes, - } = step; - const compFn = { - '==': (a, b) => a === b, - '>=': (a, b) => a >= b, - '<=': (a, b) => a <= b, - }[operator]; - await waitForFunction(async () => { - const elements = await querySelectorsAll(step.selectors, frame); - let result = compFn(elements.length, count); - const elementsHandle = await frame.evaluateHandle((...elements) => { - return elements; - }, ...elements); - await Promise.all(elements.map((element) => element.dispose())); - if (result && (properties || attributes)) { - result = await elementsHandle.evaluate( - (elements, properties, attributes) => { - for (const element of elements) { - if (attributes) { - for (const [name, value] of Object.entries(attributes)) { - if (element.getAttribute(name) !== value) { - return false; - } - } - } - if (properties) { - if (!isDeepMatch(properties, element)) { - return false; - } - } - } - return true; - - function isDeepMatch(a, b) { - if (a === b) { - return true; - } - if ((a && !b) || (!a && b)) { - return false; - } - if (!(a instanceof Object) || !(b instanceof Object)) { - return false; - } - for (const [key, value] of Object.entries(a)) { - if (!isDeepMatch(value, b[key])) { - return false; - } - } - return true; - } - }, - properties, - attributes - ); - } - await elementsHandle.dispose(); - return result === visible; - }, timeout); - } - - async function querySelectorsAll(selectors, frame) { - for (const selector of selectors) { - const result = await querySelectorAll(selector, frame); - if (result.length) { - return result; - } - } - return []; - } - - async function querySelectorAll(selector, frame) { - if (!Array.isArray(selector)) { - selector = [selector]; - } - if (!selector.length) { - throw new Error('Empty selector provided to querySelectorAll'); - } - let elements = []; - for (let i = 0; i < selector.length; i++) { - const part = selector[i]; - if (i === 0) { - elements = await frame.$$(part); - } else { - const tmpElements = elements; - elements = []; - for (const el of tmpElements) { - elements.push(...(await el.$$(part))); - } - } - if (elements.length === 0) { - return []; - } - if (i < selector.length - 1) { - const tmpElements = []; - for (const el of elements) { - const newEl = (await el.evaluateHandle(el => el.shadowRoot ? el.shadowRoot : el)).asElement(); - if (newEl) { - tmpElements.push(newEl); - } - } - elements = tmpElements; - } - } - return elements; - } - - async function waitForFunction(fn, timeout) { - let isActive = true; - const timeoutId = setTimeout(() => { - isActive = false; - }, timeout); - while (isActive) { - const result = await fn(); - if (result) { - clearTimeout(timeoutId); - return; - } - await new Promise(resolve => setTimeout(resolve, 100)); - } - throw new Error('Timed out'); - } })().catch(err => { console.error(err); process.exit(1); @@ -1436,133 +420,6 @@ const puppeteer = require('puppeteer'); // v20.7.4 or later await browser.close(); - async function waitForElement(step, frame, timeout) { - const { - count = 1, - operator = '>=', - visible = true, - properties, - attributes, - } = step; - const compFn = { - '==': (a, b) => a === b, - '>=': (a, b) => a >= b, - '<=': (a, b) => a <= b, - }[operator]; - await waitForFunction(async () => { - const elements = await querySelectorsAll(step.selectors, frame); - let result = compFn(elements.length, count); - const elementsHandle = await frame.evaluateHandle((...elements) => { - return elements; - }, ...elements); - await Promise.all(elements.map((element) => element.dispose())); - if (result && (properties || attributes)) { - result = await elementsHandle.evaluate( - (elements, properties, attributes) => { - for (const element of elements) { - if (attributes) { - for (const [name, value] of Object.entries(attributes)) { - if (element.getAttribute(name) !== value) { - return false; - } - } - } - if (properties) { - if (!isDeepMatch(properties, element)) { - return false; - } - } - } - return true; - - function isDeepMatch(a, b) { - if (a === b) { - return true; - } - if ((a && !b) || (!a && b)) { - return false; - } - if (!(a instanceof Object) || !(b instanceof Object)) { - return false; - } - for (const [key, value] of Object.entries(a)) { - if (!isDeepMatch(value, b[key])) { - return false; - } - } - return true; - } - }, - properties, - attributes - ); - } - await elementsHandle.dispose(); - return result === visible; - }, timeout); - } - - async function querySelectorsAll(selectors, frame) { - for (const selector of selectors) { - const result = await querySelectorAll(selector, frame); - if (result.length) { - return result; - } - } - return []; - } - - async function querySelectorAll(selector, frame) { - if (!Array.isArray(selector)) { - selector = [selector]; - } - if (!selector.length) { - throw new Error('Empty selector provided to querySelectorAll'); - } - let elements = []; - for (let i = 0; i < selector.length; i++) { - const part = selector[i]; - if (i === 0) { - elements = await frame.$$(part); - } else { - const tmpElements = elements; - elements = []; - for (const el of tmpElements) { - elements.push(...(await el.$$(part))); - } - } - if (elements.length === 0) { - return []; - } - if (i < selector.length - 1) { - const tmpElements = []; - for (const el of elements) { - const newEl = (await el.evaluateHandle(el => el.shadowRoot ? el.shadowRoot : el)).asElement(); - if (newEl) { - tmpElements.push(newEl); - } - } - elements = tmpElements; - } - } - return elements; - } - - async function waitForFunction(fn, timeout) { - let isActive = true; - const timeoutId = setTimeout(() => { - isActive = false; - }, timeout); - while (isActive) { - const result = await fn(); - if (result) { - clearTimeout(timeoutId); - return; - } - await new Promise(resolve => setTimeout(resolve, 100)); - } - throw new Error('Timed out'); - } })().catch(err => { console.error(err); process.exit(1); diff --git a/src/PuppeteerStringifyExtension.ts b/src/PuppeteerStringifyExtension.ts index a4afe874..a97f4ef1 100644 --- a/src/PuppeteerStringifyExtension.ts +++ b/src/PuppeteerStringifyExtension.ts @@ -45,6 +45,8 @@ import { import { formatJSONAsJS } from './JSONUtils.js'; export class PuppeteerStringifyExtension extends StringifyExtension { + #shouldAppendWaitForElementHelper = false; + override async beforeAllSteps(out: LineWriter, flow: UserFlow) { out.appendLine( "const puppeteer = require('puppeteer'); // v20.7.4 or later" @@ -58,14 +60,17 @@ export class PuppeteerStringifyExtension extends StringifyExtension { out.appendLine(`const timeout = ${flow.timeout || defaultTimeout};`); out.appendLine('page.setDefaultTimeout(timeout);'); out.appendLine(''); + this.#shouldAppendWaitForElementHelper = false; } override async afterAllSteps(out: LineWriter, flow: UserFlow) { out.appendLine(''); out.appendLine('await browser.close();'); out.appendLine(''); - for (const line of helpers.split('\n')) { - out.appendLine(line); + if (this.#shouldAppendWaitForElementHelper) { + for (const line of waitForElementHelper.split('\n')) { + out.appendLine(line); + } } out.endBlock().appendLine('})().catch(err => {').startBlock(); out.appendLine('console.error(err);'); @@ -332,6 +337,7 @@ export class PuppeteerStringifyExtension extends StringifyExtension { } #appendWaitForElementStep(out: LineWriter, step: WaitForElementStep): void { + this.#shouldAppendWaitForElementHelper = true; out.appendLine( `await waitForElement(${formatJSONAsJS(step, out.getIndent())}, ${ step.frame ? 'frame' : 'targetPage' @@ -342,7 +348,7 @@ export class PuppeteerStringifyExtension extends StringifyExtension { const defaultTimeout = 5000; -const helpers = `async function waitForElement(step, frame, timeout) { +const waitForElementHelper = `async function waitForElement(step, frame, timeout) { const { count = 1, operator = '>=',