The meta tag steps assert the invisible half of a page: the <meta> elements in <head> that drive search snippets, social sharing cards, indexing rules, and viewport behavior. Descriptions, keywords, robots directives, Open Graph (og:*) properties, and Twitter cards are exactly the things product and growth teams care about but that nobody sees during manual QA - these steps put them in the pipeline so a template change cannot silently ship a noindex or a placeholder description to production.
The core mechanism is attribute matching against a Cucumber data table. When the step runs, webship-js reads every <meta> element on the page and collects all of its attributes into a map. The data table lists attribute-name / attribute-value pairs (one per row), and the step passes when at least one meta tag matches every row - values compared exactly. That means you can pin down a tag by any combination of attributes: name + content, property + content for Open Graph, http-equiv + content, or even a lone charset row.
Because attributes are read from the live DOM, tags injected by JavaScript (client-side SEO frameworks, tag managers) are seen too - just make sure the page has finished rendering before you assert. A third step guards content hygiene: it fails if a named meta tag's content contains HTML markup, which catches CMS fields where an editor pasted rich text into a plain-text SEO field.
Quick reference
| Step | What it does |
|---|---|
Then the meta tag should exist with the following attributes: | Assert at least one <meta> tag matches every attribute row in the data table. |
Then the meta tag should not exist with the following attributes: | Assert no <meta> tag matches every attribute row in the data table. |
Then the "description" meta tag should not contain any HTML tags | Assert the named tag's content attribute contains no HTML markup. |
Steps in detail
Then the meta tag should exist with the following attributes:
Followed by a two-column data table of attribute names and expected values. The step scans all meta tags and passes if any single tag carries every listed attribute with exactly the listed value. Matching is exact and case-sensitive on values, so width=device-width, initial-scale=1 must be quoted character-for-character. Attribute names not listed in the table are ignored - you only assert what you list.
Then the meta tag should exist with the following attributes:
| name | viewport |
| content | width=device-width, initial-scale=1 |
And the meta tag should exist with the following attributes:
| property | og:title |
| content | Home |
Then the meta tag should not exist with the following attributes:
The inverse: fails if any meta tag matches all rows of the table. A tag matching only some rows does not trigger a failure - so | name | robots | plus | content | noindex | forbids exactly the combination <meta name="robots" content="noindex">, while still allowing a robots tag with a different content value. This is the go-to guard against leaking staging directives (noindex, refresh redirects, placeholder authors) into production.
Then the meta tag should not exist with the following attributes:
| name | robots |
| content | noindex |
And the meta tag should not exist with the following attributes:
| http-equiv | refresh |
| content | 5 |
Then the "description" meta tag should not contain any HTML tags
Looks up a meta tag whose name or property attribute equals the quoted argument - so it works for classic tags (description, keywords, author) and Open Graph / Twitter properties (og:title, twitter:description) alike. It first fails if the tag is missing entirely, then fails if its content value contains anything that looks like an HTML tag. The failure message includes the offending content, so a stray <p> pasted from a WYSIWYG field is spotted immediately.
Then the "description" meta tag should not contain any HTML tags
And the "og:title" meta tag should not contain any HTML tags
And the "twitter:description" meta tag should not contain any HTML tags
Complete example
Feature: SEO meta tags
Scenario: Home page ships correct meta tags
Given I am on "/index.html"
Then the meta tag should exist with the following attributes:
| name | viewport |
| content | width=device-width, initial-scale=1 |
And the meta tag should exist with the following attributes:
| charset | UTF-8 |
And the meta tag should not exist with the following attributes:
| name | robots |
| content | noindex |
And the "description" meta tag should not contain any HTML tags
Tips
- One tag per assertion: each step call describes a single meta tag. To assert several tags, repeat the step with separate tables as in the example above.
- Use
namefor standard tags,propertyfor Open Graph - mixing them up is the most common cause of a "No meta tag matching ..." failure. Inspect the page source to confirm which attribute the site uses. - For asserting the page
<title>or canonical link, use the response/element steps - this group covers<meta>elements only.