/**
 * `toHaveValidAMPForUser` matcher.
 *
 * Site Kit by Google, Copyright 2021 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * External dependencies
 */
import jsdom from 'jsdom';
const { JSDOM } = jsdom;

/**
 * WordPress dependencies
 */
import { createURL } from '@wordpress/e2e-test-utils';

/**
 * Internal dependencies
 */
import { fetchPageContent } from '../utils';

/**
 * Determines if the path has valid AMP for users.
 *
 * @since 1.10.0
 *
 * @param {(string|Object)} path The string URI or page object.
 * @return {Object} Matcher results.
 */
export async function toHaveValidAMPForUser( path ) {
	let pass, message;
	const urlToFetch =
		'object' === typeof path ? path.url() : createURL( path );

	const cookies = await page.cookies();

	// Make sure we have a login cookie
	if (
		false ===
		cookies.some( ( { name } ) => name.match( /^wordpress_logged_in/ ) )
	) {
		throw new Error(
			'toHaveValidAMPForUser failed. User is not logged in.'
		);
	}

	const html = await fetchPageContent( urlToFetch );
	const jsDoc = new JSDOM( html ).window.document;
	try {
		const iconElement = jsDoc.querySelector(
			'#amp-admin-bar-item-status-icon'
		);
		// AMP v2 uses an amp-icon class, as well as additional classes for validity.
		if ( iconElement.classList.contains( 'amp-icon' ) ) {
			expect( iconElement.classList.contains( 'amp-valid' ) ).toBe(
				true
			);
		} else {
			// AMP v1
			expect( iconElement.textContent ).toMatch( '✅' );
		}
		pass = true;
		message = () => 'Expected logged-in user not to have valid AMP';
	} catch ( error ) {
		pass = false;
		message = () => 'Expected logged-in user to have valid AMP';
	}
	return { pass, message };
}

@@ -693,51 +693,49 @@
 ort 
-jsdom from 'jsdom';%0Aconst %7B JSDOM %7D = jsdom
+ampHTMLValidator from 'amphtml-validator'
 ;%0A%0A/
@@ -1143,110 +1143,8 @@
 ) %7B%0A
-%09let pass, message;%0A%09const urlToFetch =%0A%09%09'object' === typeof path ? path.url() : createURL( path );%0A%0A
 %09con
@@ -1407,507 +1407,377 @@
 nst 
-html = await fetchPageContent( urlToFetch );%0A%09const jsDoc = new JSDOM( html ).window.document;%0A%09try %7B%0A%09%09const iconElement = jsDoc.querySelector(%0A%09%09%09'#amp-admin-bar-item-status-icon'%0A%09%09);%0A%09%09// AMP v2 uses an amp-icon class, as well as additional classes for 
+urlToFetch =%0A%09%09'object' === typeof path ? path.url() : createURL( path );%0A%0A%09const html = await fetchPageContent( urlToFetch );%0A%09const validator = await ampHTMLValidator.getInstance();%0A%0A%09const %7B status, errors %7D = validator.
 valid
-ity.%0A%09%09if ( iconElement.classList.contains( 'amp-icon' ) ) %7B%0A%09%09%09expect( iconElement.classList.contains( 'amp-valid' ) ).toBe(%0A%09%09%09%09true%0A%09%09%09);%0A%09%09%7D else %7B%0A%09%09%09// AMP v1%0A%09%09%09expect( iconElement.textContent ).toMatch( '%E2%9C%85' );%0A%09%09%7D%0A
+ateString( html );%0A%0A%09if (%0A%09%09'PASS' === status %7C%7C%0A%09%09! errors.some( ( %7B code %7D ) =%3E code !== 'DEV_MODE_ONLY' )%0A%09) %7B%0A%09%09return %7B%0A%09
 %09%09pass
- =
+:
  true
-;%0A
+,%0A%09
 %09%09me
@@ -1773,34 +1773,33 @@
 true,%0A%09%09%09message
- =
+:
  () =%3E 'Expected
@@ -1840,28 +1840,26 @@
 AMP'
-;%0A%09%7D catch ( error )
+,%0A%09%09%7D;%0A%09%7D%0A%0A%09return
  %7B%0A%09
@@ -1867,17 +1867,16 @@
 pass
- =
+:
  false
-;
+,
 %0A%09%09m
@@ -1881,18 +1881,17 @@
 %09message
- =
+:
  () =%3E '
@@ -1936,37 +1936,11 @@
 AMP'
-;%0A%09%7D%0A%09return %7B pass, message 
+,%0A%09
 %7D;%0A%7D

Fix AMP related E2E failure on 4.9 by using official AMP Validator.