unhead icon indicating copy to clipboard operation
unhead copied to clipboard

Question: How to test meta tags with Playwright?

Open julisch94 opened this issue 2 years ago • 4 comments

Describe the feature

Hey community, this is not really a feature request. More like a documentation request, or best practice request.

Thanks for the great library! I'm loving it.

In my app I'm making use of useSeoMeta() and useHead() and I'm trying to run an e2e test using Playwright. But I have some issues.

My current testing file:

# page.spec.ts
import test, { expect } from '@playwright/test'

test('should contain the correct title', async ({ page }) => {
  await page.goto('/my-page')

  # wait for the document title to change; is there a better way?
  await page.waitForFunction(() => document.title === 'Custom Title')

  const title = await page.evaluate(() => document.title)
  expect(title).toBe('Custom Title')
})

test('should contain the correct meta tags', async ({ page }) => {
  await page.goto('/my-page')

  const ogDescription = await page.$eval('meta[property="og:description"]', el => (el as HTMLMetaElement).content)
  expect(ogDescription).toMatch(/^This is the beginning of the meta tag content./)

  const ogTitle = await page.$eval('meta[property="og:title"]', el => (el as HTMLMetaElement).content)
  expect(ogTitle).toBe('Custom Title')

  const description = await page.$eval('meta[name="description"]', el => (el as HTMLMetaElement).content)
  expect(description).toMatch(/^This is the beginning of the meta tag content./)
})

I'm noticing some flakiness in the test cases because it seems it takes some time for the meta tags to update. Plus, I've seen that $eval() is deprecated and shall be replaced with evaluate(). So I'm wondering what the best practice is to test if unhead meta tags are correctly shown.

Maybe you can point me towards some documentation on how to write tests for unhead consumers or you could potentially add some documentation about that.

Update 13-Oct-2023: page.waitForLoadState() doesn't work either

test('should contain the correct meta tags', async ({ page }) => {
  await page.goto('/my-page')

  await page.waitForLoadState()

  const ogDescription = await page.$eval('meta[property="og:description"]', el => (el as HTMLMetaElement).content)
  expect(ogDescription).toMatch(/^This is the beginning of the meta tag content./)
})

Additional information

  • [X] Would you be willing to help implement this feature?

julisch94 avatar Sep 24 '23 14:09 julisch94

I'm using await expect(page.locator('meta[property="og:description"][content="blablabla"]')).toBeAttached()

dargmuesli avatar May 19 '24 01:05 dargmuesli

If you have an SPA then you will need to wait for Unhead to render the tags. By default Unhead will debounce the modifications for 10ms, enough time to catch subsequent head writes and avoid throttling the DOM.

I don't have a non-hacky solution for this, I'd recommend just awaiting a small timeout.

harlan-zw avatar Sep 07 '24 07:09 harlan-zw