Проверка метаданных страницы
В предыдущем уроке сохранённая статья получила правильный адрес, статус и текст. Но документ может одновременно сообщать браузеру неверное название, указывать canonical другой страницы или содержать правило индексации, перенесённое из неподходящей среды. Эти свойства не видны в основном тексте и требуют отдельного наблюдения.
В этом уроке проверим метаданные каталога и учебной статьи. Исходники находятся в lesson-21/start и expected архива продолжения. Это отдельная лаборатория на loopback, а не производственная версия ProfessorWeb. Она получает noindex, follow и локальные canonical. Тесты, запросы и оценка индексации сейчас не выполнялись.
Название страницы и её заголовок
title находится в head и обозначает документ для вкладки браузера. H1 относится к содержимому. Они могут различаться осмысленно: у каталога title равен «Учебный каталог», а H1 — «Каталог курсов». У сохранённой статьи оба называют «Основы HTML». Проверять их как одно поле было бы ошибкой, потому что пользователь встречает их в разных местах.
Матрица задаёт две страницы и ожидаемые значения:
const paths = [
{ path: '/', title: 'Учебный каталог', heading: 'Каталог курсов' },
{ path: '/my/html/html5/level1/1_1.php',
title: 'Основы HTML', heading: 'Основы HTML' }
];
Полный сценарий для каждой строки сначала проверяет 200 без автоматического редиректа. Затем открывает страницу, использует toHaveTitle() и находит H1 по роли, уровню и точному имени. Такая проверка заметит общую ошибку шаблона, при которой все страницы получают название главной, даже если текст статьи остаётся на месте.
В настоящем ProfessorWeb названия могут включать имя сайта. Тогда матрица должна описывать принятый формат, а не автоматически требовать равенства H1 и title. Полезно проверять предмет страницы и единственность основного заголовка отдельно от брендового суффикса. Текущий пример намеренно оставляет короткие названия, чтобы объяснить разные свойства документа.
Canonical выбранной среды
Для двух проверяемых страниц зададим ровно один link rel="canonical". Его href — абсолютный локальный адрес с тем же pathname. Каталог указывает на корень лаборатории, сохранённая статья — на свой .php путь. Ошибка 404 не получает canonical статьи и не выдаётся за существующий материал.
const canonical = page.locator('head link[rel="canonical"]');
await expect(canonical).toHaveCount(1);
await expect(canonical).toHaveAttribute(
'href', `http://127.0.0.1:4407${entry.path}`
);
Сначала проверяем число элементов. Если общий шаблон и шаблон статьи добавят разные canonical одновременно, наличие одного правильного href не спасёт договорённость. Точное сравнение проверяет схему, host, порт и путь. Для производственной среды эти значения будут другими; порт локальной лаборатории нельзя переносить в метаданные публичного сайта.
Canonical не изменяет адрес браузера и не является редиректом. Он сообщает предпочтительный адрес среди связанных документов. Как поисковая система выбирает каноническую страницу, описано в Google Search Central. Сценарий здесь проверяет отправленный сигнал, а не решение поисковой системы и не будущую позицию в выдаче.
Мы не заставляем Playwright переходить по canonical. Это важно для локальной работы: проверка метаданных не должна неожиданно открыть production или вызвать внешние запросы. Само наличие абсолютного href не означает необходимость посещения указанного адреса. В этой лаборатории он даже остаётся внутри loopback, но принцип пригодится и для staging.
Robots в HTML и HTTP
Локальная лаборатория получает meta robots noindex, follow. Сервер также отправляет X-Robots-Tag для HTML. В сценарии проверяются оба уровня: HTTP-заголовок читается из ответа API, meta — из открытого документа.
expect(response.headers()['x-robots-tag']).toBe('noindex, follow');
const robots = page.locator('head meta[name="robots"]');
await expect(robots).toHaveCount(1);
await expect(robots).toHaveAttribute('content', 'noindex, follow');
Здесь ожидается конкретная строка, потому что мы сами задали её в ограниченном сервере. Общий анализ чужого сайта потребовал бы разбирать регистр, запятые, несколько директив и правила конкретных роботов. Нельзя считать любую другую запись неправильной только из-за порядка слов. Наш сценарий проверяет договорённый вывод собственных исходников.
noindex относится к индексации, а не к авторизации. Страница остаётся доступна человеку, который может обратиться к серверу. Loopback ограничивает доступ сетевым интерфейсом; правило роботов выражает другую задачу. Полноценное закрытие приватной среды не достигается одной метатеговой строкой. В данном примере настоящих секретов и приватного контента нет.
Смысл meta robots и X-Robots-Tag, а также необходимость доступности правила для обходчика разобраны в документации Google. Мы не используем noindex как замену canonical. Лаборатория закрыта от индексации потому, что это учебная локальная среда; canonical лишь описывает выбранный адрес её документа.
Ошибки переноса конфигурации
Представим, что при будущей публикации production получит метаданные локальной среды. Статьи откроются, а noindex начнёт противоречить задаче появления материалов в поиске. Обратная ошибка — публичная тестовая копия получает настройки индексации рабочего сайта. Поэтому среда должна входить в исходные условия сценария, а ожидаемые правила нельзя задавать одним общим значением для всех адресов.
В настоящем ProfessorWeb редакционный preview уже отличается от производственной сборки. Защищённые прежние материалы нельзя превращать в черновики или закрывать noindex в рабочей версии. Наш Node-сервер демонстрирует локальную проверку и не редактирует эти настройки. Чтобы применить матрицу к ProfessorWeb, нужно читать его фактические шаблоны и правила выбранной сборки.
Обратите внимание и на HTTP-коды. Правильный canonical не делает 404 существующей статьёй, а title ошибки не исправляет ответ 200 для отсутствующего пути. Поэтому мы опираемся на предыдущую проверку статуса. Метаданные дополняют договорённость маршрута, а не заменяют её.
Что можно утверждать после будущего сценария
Ожидаемый результат — обе выбранные HTML-страницы сообщают правильное название, имеют единственный локальный canonical и согласованные правила robots. Это ограниченная матрица, а не аудит всех вспомогательных маршрутов. Сервер отправляет noindex и для остальных учебных HTML, но сценарий подробно сопоставляет значения только у двух страниц.
Даже после исполнения такой результат не подтвердит индексацию в Google или Яндексе. Для этого нужны доступный поисковому роботу рабочий сайт, состояние обхода и инструменты вебмастера. Сейчас мы подготовили наблюдения над локальным документом; решений поисковых систем и изменения трафика нет.
В качестве изменения для самостоятельного разбора добавьте вторую canonical-ссылку с неправильным путём. Подумайте, какое утверждение остановится первым и почему. Затем верните единственное согласованное значение. Этот опыт помогает понять, зачем проверять структуру метаданных до оценки их отдельных полей. Выполнять его сейчас не требуется: примеры остаются исходниками для чтения.