ค้นหาเว็บไซต์

ReferenceError: document ไม่ได้ถูกกำหนด ข้อผิดพลาด Typescript ใน Playwright


ความคิดคือฉันกำลังพยายามดึงหัวข้อ HTML ทั้งหมด (h1 h2 h3 h4 h5 h6) และทดสอบว่าพวกมันเรียงตามลำดับที่เป็นมิตรกับ SEO หรือไม่ ถ้าฉันพยายามรันมัน ฉันจะได้ข้อผิดพลาด ReferenceError: document is not defined ใน Typescript บน Playwright

async assertHeadingsOrder2() {
  // eslint-disable-next-line @typescript-eslint/require-await
  await test.step('Test html header structure for catalog page', async () => {
    // Get all the heading tags (h1, h2, h3, h4, h5, h6) in the document
    const headingTags = document.querySelectorAll('h1, h2, h3, h4, h5, h6');

    // Define a function to test the hierarchy
    function testHeadingHierarchy() {
      const hierarchy = [];

      headingTags.forEach(heading => {
        const tagName = heading.tagName.toLowerCase(); // Get the tag name (e.g., "h1", "h2")
        const level = parseInt(tagName.charAt(1), 10); // Extract the numeric level from the tag name

        // Check if the hierarchy is valid
        if (level > hierarchy.length + 1) {
          console.error(`Invalid hierarchy: ${tagName} is not in the correct order.`);
        }

        // Update the hierarchy array with the current level
        hierarchy[level - 1] = tagName;
      });

      console.log('Heading hierarchy is valid:', hierarchy.join(' > '));
    }

    // Call the function to test the hierarchy
    testHeadingHierarchy();
  });
}

คำตอบ #1

Playwright จะไม่ทำให้ document ใช้งานได้โดยอัตโนมัติใน Node แต่จะให้คุณใช้วัตถุ browser และ page ที่มี API ที่ครอบคลุมสำหรับจัดการเว็บไซต์

คุณสามารถใช้ page.evaluate() เพื่อรันโค้ดในเบราว์เซอร์และเข้าถึง document แต่โดยปกติแล้ว คุณจะเลือกองค์ประกอบด้วย API สำหรับตัวระบุตำแหน่ง (locators) บนวัตถุ page

ตัวเลือก CSS ของคุณควรเป็น "h1, h2, h3, h4, h5, h6" แทนที่จะเป็น "h1 h2 h3 h4 h5 h6" แบบแรกใช้เครื่องหมายจุลภาคสำหรับตรรกะ "หรือ" ขณะที่แบบหลังจะเลือก <h6> ที่ซ้อนอยู่ภายในหัวข้ออื่นทั้งหมด

นี่คือตัวอย่าง:

import {expect, test} from "@playwright/test"; // ^1.39.0

const failMsg = (prev, curr) =>
  `h${curr} was more than one level deeper than previous header h${prev}`;

test("detects a skipped heading", async ({page}) => {
  test.fail(); // expect this test to fail
  const html = `<!DOCTYPE html><html><body>
  <h1>1</h1>
  <h2>2</h2>
  <h4>4</h4>
  </body></html>`;
  await page.setContent(html); // replace with page.goto("<Your URL>"); when you're working with a real site
  const headers = await page
    .locator("h1, h2, h3, h4, h5, h6")
    .evaluateAll(els => els.map(el => +el.tagName.slice(1)));

  for (let i = 1; i < headers.length; i++) {
    expect(
      headers[i] - headers[i-1],
      failMsg(headers[i-1], headers[i])
    ).toBeLessThan(2);
  }
});

test("handles a valid structure", async ({page}) => {
  const html = `<!DOCTYPE html><html><body>
  <h1>1</h1>
  <h2>2</h2>
  <h3>3</h3>
  <h4>4</h4>
  <h4>4</h4>
  <h2>2</h2> <!-- it's OK to skip back, just not forward -->
  <h3>3</h3>
  </body></html>`;
  await page.setContent(html);
  const headers = await page
    .locator("h1, h2, h3, h4, h5, h6")
    .evaluateAll(els => els.map(el => +el.tagName.slice(1)));

  for (let i = 1; i < headers.length; i++) {
    expect(
      headers[i] - headers[i-1],
      failMsg(headers[i-1], headers[i])
    ).toBeLessThan(2);
  }
});

test("handles a valid structure on a real site", async ({page}) => {
  await page.goto("https://playwright.dev/docs/test-assertions");
  const headers = await page
    .locator("h1, h2, h3, h4, h5, h6")
    .evaluateAll(els => els.map(el => +el.tagName.slice(1)));

  for (let i = 1; i < headers.length; i++) {
    expect(
      headers[i] - headers[i-1],
      failMsg(headers[i-1], headers[i])
    ).toBeLessThan(2);
  }
});

สำหรับการทดสอบจริงของคุณ คุณน่าจะใช้ page.goto() แทน page.setContent ซึ่งในที่นี้ใช้เพื่อช่วยแสดงตรรกะของการอ้างอิงได้อย่างง่ายๆ

คุณอาจต้องการใช้ตัวแมตช์แบบกำหนดเองเพื่อช่วยสรุปข้อความเทมเพลตข้อผิดพลาดที่ยาวและลูปที่ชัดเจน และ/หรือเขียนฟังก์ชันช่วยเหลือเพื่อดึงหัวข้อ

นอกจากนี้ ข้อสันนิษฐานนี้ไม่ได้รออัตโนมัติ แต่ฉันสมมติว่าหัวข้อคงโอเคที่จะดึงมากหรือน้อยได้ในครั้งเดียว หากสมมติฐานนั้นไม่เป็นความจริง ลองใช้ poll หรือ toPass