1 const t = require('tap')
2 const {resolve, join, posix} = require('path')
3 const fs = require('fs/promises')
4 const pacote = require('pacote')
5 const yaml = require('yaml')
6 const semver = require('semver')
7
8 const navPath = resolve(__dirname, '..', '..', 'content', 'nav.yml')
9
10 const getReleases = () => [
11 {
12 id: 'v6',
13 branch: 'release/v6',
14 },
15 {
16 id: 'v7',
17 branch: 'release/v7',
18 },
19 {
20 id: 'v8',
21 branch: 'release/v8',
22 },
23 {
24 id: 'v9',
25 branch: 'latest',
26 },
27 ]
28
29 const mockBuild = async (t, {releases = getReleases(), packument = {}, testdir: testdirOpts} = {}) => {
30 const rawNav = await fs.readFile(navPath, 'utf-8')
31 const nav = yaml.parse(rawNav)
32
33 const testdir = t.testdir({
34 'nav.yml': rawNav,
35 content: {},
36 ...testdirOpts,
37 })
38
39 if (!packument.versions) {
40 packument.versions = releases.map(r => {
41 // real tarball requests are made for these verions
42 // so by default they all need to exist
43 switch (r.id.slice(1)) {
44 case '6':
45 return '6.14.18'
46 case '7':
47 return '7.24.2'
48 case '8':
49 return '8.19.3'
50 case '9':
51 return '9.0.0'
52 default:
53 throw new Error(`Unknown packument version: ${JSON.stringify(r)}`)
54 }
55 })
56 }
57
58 if (!packument.latest) {
59 packument.latest = packument.versions[packument.versions.length - 1]
60 }
61
62 const navSection = ref => {
63 const id = ref === 'latest' ? `v${semver.major(packument.latest)}` : posix.basename(ref)
64 const {variants} = nav.find(c => c.url === '/cli')
65 const {children} = variants.find(v => posix.basename(v.url) === id)
66 return yaml.stringify(children).replace(new RegExp(`/cli/${id}/`, 'g'), '/')
67 }
68
69 const build = t.mockRequire('../lib/build', {
70 pacote: {
71 ...pacote,
72 packument: async () => {
73 return {
74 'dist-tags': {
75 latest: packument.latest,
76 },
77 versions: packument.versions.reduce((acc, v) => {
78 acc[v] = null
79 return acc
80 }, {}),
81 }
82 },
83 },
84 '@prettier/sync': {format: s => s},
85 '../lib/gh.js': {
86 getFile: async ({ref}) => navSection(ref),
87 pathExists: async (ref, p) => {
88 if (ref.includes('v6') && p.includes('docs/lib/content')) {
89 return null
90 }
91 return p
92 },
93 nwo: `npm/cli`,
94 },
95 })
96
97 return {
98 testdir,
99 releases,
100 build: opts =>
101 build({
102 releases,
103 contentPath: join(testdir, 'content'),
104 navPath: join(testdir, 'nav.yml'),
105 ...opts,
106 }),
107 }
108 }
109
110 t.test('basic', async t => {
111 const {releases, build, testdir} = await mockBuild(t, {
112 testdir: {
113 'nav.yml': '- title: cli\n url: /cli',
114 },
115 })
116
117 await build()
118 t.strictSame(
119 await fs.readdir(join(testdir, 'content')),
120 releases.map(r => r.id),
121 )
122 })
123
124 t.test('prereleases', async t => {
125 const {build, releases, testdir} = await mockBuild(t, {
126 packument: {versions: ['6.14.18', '7.24.2', '8.19.3', '9.0.0-pre.2'], latest: '8.19.3'},
127 })
128
129 await build({prerelease: false})
130 const expectedReleases = releases.map(r => r.id).filter(r => r !== 'v9')
131 t.strictSame(await fs.readdir(join(testdir, 'content')), expectedReleases)
132
133 await build({prerelease: true})
134 t.strictSame(
135 await fs.readdir(join(testdir, 'content')),
136 releases.map(r => r.id),
137 )
138 })
139
140 t.test('earlier release is latest', async t => {
141 const {build} = await mockBuild(t, {
142 packument: {latest: '8.19.3'},
143 })
144
145 await build()
146 })
147
148 t.test('can skip fetching latest', async t => {
149 const {build} = await mockBuild(t)
150
151 await build({useCurrent: true})
152 })
153
154 t.test('add variant to nav', async t => {
155 const {build} = await mockBuild(t, {
156 testdir: {
157 'nav.yml': '- title: cli\n url: /cli\n variants:\n - url: /cli/v0',
158 },
159 })
160
161 await build()
162 })