Include canonical <link> for user review pages (#13127)

* Include canonical <link> for user review pages

Also add rel=nofollow to links to it filtering user reviews by score
as it's useless for search engines to visit, it's the same content but
filtered.
This commit is contained in:
Mathieu Pillard 2024-07-25 13:03:01 +02:00 коммит произвёл GitHub
Родитель c5c73838af
Коммит 7b9f6fe7f4
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
4 изменённых файлов: 56 добавлений и 0 удалений

Просмотреть файл

@ -151,6 +151,7 @@ export class RatingsByStarBase extends React.Component<InternalProps> {
<Link
className="RatingsByStar-row"
key={star}
rel="nofollow"
title={getLinkTitles(star, starCount) || ''}
to={reviewListURL({
addonSlug: addon.slug,

Просмотреть файл

@ -11,6 +11,7 @@ import { DEFAULT_API_PAGE_SIZE } from 'amo/api';
import AddonReviewCard from 'amo/components/AddonReviewCard';
import AddonSummaryCard from 'amo/components/AddonSummaryCard';
import FeaturedAddonReview from 'amo/components/FeaturedAddonReview';
import HeadLinks from 'amo/components/HeadLinks';
import Page from 'amo/components/Page';
import { fetchReviewPermissions, fetchReviews } from 'amo/actions/reviews';
import { setViewContext } from 'amo/actions/viewContext';
@ -332,6 +333,7 @@ export class AddonReviewListBase extends React.Component<InternalProps> {
{reviewId && <meta name="robots" content="noindex, follow" />}
</Helmet>
)}
{addon && !reviewId && <HeadLinks />}
{errorHandler.renderErrorIfPresent()}

Просмотреть файл

@ -78,6 +78,7 @@ describe(__filename, () => {
'href',
`/en-US/android${reviewListURL({ addonSlug: addon.slug, score })}`,
);
expect(link).toHaveAttribute('rel', 'nofollow');
expect(within(link).getByText(count)).toBeInTheDocument();
}

Просмотреть файл

@ -1,3 +1,4 @@
import config from 'config';
import { waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
@ -17,6 +18,7 @@ import {
CLIENT_APP_FIREFOX,
SET_VIEW_CONTEXT,
} from 'amo/constants';
import { hrefLangs } from 'amo/languages';
import { fetchAddon, loadAddon } from 'amo/reducers/addons';
import {
changeLocation,
@ -700,6 +702,56 @@ describe(__filename, () => {
expect(getElements('meta[name="robots"]')).toHaveLength(0);
});
it('renders a canonical link for the list page with alternates', async () => {
renderWithAddonAndReviews();
const getExpectedURL = (locale, app) => {
return `${config.get(
'baseURL',
)}/${locale}/${app}/addon/${defaultSlug}/reviews/`;
};
await waitFor(() =>
expect(getElement('link[rel="canonical"]')).toHaveAttribute(
'href',
getExpectedURL('en-US', 'firefox'),
),
);
await waitFor(() =>
expect(getElement('link[rel="alternate"]')).toBeInTheDocument(),
);
expect(getElements('link[rel="alternate"]')).toHaveLength(
hrefLangs.length,
);
const hrefLangsMap = config.get('hrefLangsMap');
hrefLangs.forEach((hrefLang) => {
const locale = hrefLangsMap[hrefLang] || hrefLang;
expect(
getElement(`link[rel="alternate"][hreflang="${hrefLang}"]`),
).toHaveAttribute('href', getExpectedURL(locale, 'firefox'));
});
});
it('renders a canonical with no query string', async () => {
renderWithAddonAndReviews({ score: 5 });
const getExpectedURL = (locale, app) => {
return `${config.get(
'baseURL',
)}/${locale}/${app}/addon/${defaultSlug}/reviews/`;
};
await waitFor(() =>
expect(getElement('link[rel="canonical"]')).toHaveAttribute(
'href',
getExpectedURL('en-US', 'firefox'),
),
);
});
it('renders a robots meta tag when there is a featured review', async () => {
const reviews = [
{ ...fakeReview, id: 1, score: 1 },