Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const VersionDropdown: FC = () => {
);

if (
release?.status === 'LTS' &&
(release?.status === 'LTS' || release?.status === 'EOL') &&
(pathname.includes('current') || pathname.includes('alpha'))
) {
redirect({ href: '/download', locale });
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import assert from 'node:assert/strict';
import { beforeEach, describe, it, mock } from 'node:test';

import { render } from '@testing-library/react';

import {
ReleaseContext,
ReleasesContext,
} from '#site/providers/releaseProvider';

const redirect = mock.fn();
const setVersion = mock.fn();
const Select = mock.fn(() => null);
let pathname;

mock.module('@node-core/ui-components/Common/Select/NoScriptSelect', {
defaultExport: Select,
});

mock.module('#site/navigation.mjs', {
namedExports: {
redirect,
usePathname: () => pathname,
},
});

const { default: VersionDropdown } = await import('../VersionDropdown');

const statuses = [
{
status: 'EOL',
path: '/download',
badgeKind: 'warning',
versions: ['v18.0.0', 'v16.0.0'],
},
{
status: 'Current',
path: '/download/current',
badgeKind: 'default',
versions: ['v25.0.0', 'v25.1.0'],
},
{
status: 'LTS',
path: '/download',
badgeKind: 'info',
versions: ['v24.0.0', 'v22.0.0'],
},
{
status: 'Alpha',
path: '/download/alpha',
badgeKind: 'default',
versions: ['v26.0.0-alpha.1', 'v26.0.0-alpha.2'],
},
];

const releases = statuses.flatMap(({ status, versions }) =>
versions.map(versionWithPrefix => ({ versionWithPrefix, status }))
);

const renderDropdown = (release = releases[0]) => {
render(
<ReleasesContext value={{ releases, snippets: [] }}>
<ReleaseContext value={{ release, setVersion }}>
<VersionDropdown />
</ReleaseContext>
</ReleasesContext>
);

return Select.mock.calls.at(-1).arguments[0];
};

describe('VersionDropdown', () => {
beforeEach(() => {
pathname = '/download';
redirect.mock.resetCalls();
setVersion.mock.resetCalls();
Select.mock.resetCalls();
});

for (const { status, path, badgeKind, versions } of statuses) {
describe(status, () => {
const release = releases.find(candidate => candidate.status === status);

beforeEach(() => {
pathname = path;
});

it('uses the active release as the default selection', () => {
const { defaultValue, ariaLabel } = renderDropdown(release);

assert.equal(defaultValue, release.versionWithPrefix);
assert.equal(ariaLabel, 'layouts.download.dropdown.version');
});

it(`provides the ${status} badge for each version`, () => {
const { values } = renderDropdown(release);

assert.equal(values.length, releases.length);
for (const version of versions) {
assert.deepEqual(
values.find(({ value }) => value === version),
{
value: version,
label: version,
badge: { label: status, kind: badgeKind },
}
);
}
});

for (const target of statuses) {
const description =
target.status === status ? `another ${status}` : target.status;

it(`switches to ${description}`, () => {
const { onChange } = renderDropdown(release);
const version = target.versions.find(
candidate => candidate !== release.versionWithPrefix
);

onChange(version);

if (target.path !== path) {
assert.equal(redirect.mock.callCount(), 1);
assert.deepEqual(redirect.mock.calls[0].arguments, [
{ href: target.path, locale: 'en' },
]);
assert.equal(setVersion.mock.callCount(), 0);
} else {
assert.equal(redirect.mock.callCount(), 0);
assert.equal(setVersion.mock.callCount(), 1);
assert.deepEqual(setVersion.mock.calls[0].arguments, [version]);
}
});
}
});
}
});
1 change: 1 addition & 0 deletions apps/site/tests/setup.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import '../../../tests/setup.mjs';
mock.module('next-intl', {
namedExports: {
useTranslations: () => key => key,
useLocale: () => 'en',

useFormatter: () => {
const formatWith = format => new Intl.DateTimeFormat('en-US', format);
Expand Down
Loading