|
9 | 9 | createLiquidContext, |
10 | 10 | extractLinksWithLiquid, |
11 | 11 | } from '../lib/extract-links' |
12 | | -import { latestStable } from '@/versions/lib/enterprise-server-releases' |
| 12 | +import { latest, latestStable } from '@/versions/lib/enterprise-server-releases' |
13 | 13 | import { getFeaturesByVersion } from '@/versions/middleware/features' |
14 | 14 | import type { Page } from '@/types' |
15 | 15 |
|
@@ -533,6 +533,7 @@ describe('normalizeLinkPath', () => { |
533 | 533 |
|
534 | 534 | describe('checkInternalLink', () => { |
535 | 535 | const pageMap = { |
| 536 | + '/en': {} as unknown as Page, |
536 | 537 | '/en/actions/getting-started': {} as unknown as Page, |
537 | 538 | '/en/repositories/overview': {} as unknown as Page, |
538 | 539 | '/actions/guides': {} as unknown as Page, |
@@ -797,6 +798,67 @@ describe('checkInternalLink', () => { |
797 | 798 | expect(result.isRedirect).toBe(true) |
798 | 799 | expect(result.redirectTarget).toBe('/') |
799 | 800 | }) |
| 801 | + |
| 802 | + test.each([ |
| 803 | + '/admin/does-not-exist', |
| 804 | + '/admin/guides/does-not-exist', |
| 805 | + '/desktop/guides/does-not-exist', |
| 806 | + '/free-pro-team@latest/does-not-exist', |
| 807 | + '/enterprise-server/does-not-exist', |
| 808 | + '/enterprise/user/does-not-exist', |
| 809 | + ])('reports %s as broken when the redirect resolver target is missing', (href) => { |
| 810 | + const result = checkInternalLink(href, pageMap, redirects) |
| 811 | + expect(result.exists).toBe(false) |
| 812 | + expect(result.isRedirect).toBe(false) |
| 813 | + }) |
| 814 | + |
| 815 | + test('resolves an /admin/guides link through a versioned redirect to a real page', () => { |
| 816 | + const result = checkInternalLink( |
| 817 | + '/admin/guides/old-guide', |
| 818 | + { [`/en/enterprise-server@${latest}/admin/new-guide`]: {} as unknown as Page }, |
| 819 | + { |
| 820 | + [`/enterprise-server@${latest}/admin/old-guide`]: `/enterprise-server@${latest}/admin/new-guide`, |
| 821 | + }, |
| 822 | + ) |
| 823 | + expect(result.exists).toBe(true) |
| 824 | + expect(result.isRedirect).toBe(true) |
| 825 | + expect(result.redirectTarget).toBe(`/enterprise-server@${latest}/admin/new-guide`) |
| 826 | + }) |
| 827 | + |
| 828 | + test('ignores .md when checking a fallback redirect target', () => { |
| 829 | + const result = checkInternalLink( |
| 830 | + '/free-pro-team@latest/actions/getting-started.md', |
| 831 | + pageMap, |
| 832 | + redirects, |
| 833 | + ) |
| 834 | + expect(result.exists).toBe(true) |
| 835 | + expect(result.isRedirect).toBe(true) |
| 836 | + expect(result.redirectTarget).toBe('/actions/getting-started.md') |
| 837 | + }) |
| 838 | + |
| 839 | + test('applies the GraphQL category rewrite before checking a fallback redirect target', () => { |
| 840 | + const result = checkInternalLink( |
| 841 | + '/free-pro-team@latest/v4/scalar/boolean', |
| 842 | + { '/en/graphql/reference/other': {} as unknown as Page }, |
| 843 | + { '/v4/scalar/boolean': '/graphql/reference/scalars#boolean' }, |
| 844 | + ) |
| 845 | + expect(result.exists).toBe(true) |
| 846 | + expect(result.isRedirect).toBe(true) |
| 847 | + expect(result.redirectTarget).toBe('/graphql/reference/other#scalar-boolean') |
| 848 | + }) |
| 849 | + |
| 850 | + test('resolves fallback redirects in the checked language', () => { |
| 851 | + const result = checkInternalLink( |
| 852 | + '/free-pro-team@latest', |
| 853 | + { '/ja': {} as unknown as Page }, |
| 854 | + {}, |
| 855 | + undefined, |
| 856 | + 'ja', |
| 857 | + ) |
| 858 | + expect(result.exists).toBe(true) |
| 859 | + expect(result.isRedirect).toBe(true) |
| 860 | + expect(result.redirectTarget).toBe('/') |
| 861 | + }) |
800 | 862 | }) |
801 | 863 |
|
802 | 864 | describe('resolveInternalLinkKey', () => { |
|
0 commit comments