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 let shaCounter = 0
70 const build = t.mockRequire('../lib/build', {
71 pacote: {
72 ...pacote,
73 packument: async () => {
74 return {
75 'dist-tags': {
76 latest: packument.latest,
77 },
78 versions: packument.versions.reduce((acc, v) => {
79 acc[v] = null
80 return acc
81 }, {}),
82 }
83 },
84 },
85 '@prettier/sync': {format: s => s},
86 '../lib/gh.js': {
87 getCurrentSha: async () => {
88 shaCounter = shaCounter + 1
89 return 'abc' + shaCounter
90 },
91 getFile: async ({ref}) => navSection(ref),
92 pathExists: async (ref, p) => {
93 if (ref.includes('v6') && p.includes('docs/lib/content')) {
94 return null
95 }
96 return p
97 },
98 nwo: `npm/cli`,
99 },
100 })
101
102 return {
103 testdir,
104 releases,
105 build: opts =>
106 build({
107 releases,
108 contentPath: join(testdir, 'content'),
109 navPath: join(testdir, 'nav.yml'),
110 ...opts,
111 }),
112 }
113 }
114
115 t.test('basic', async t => {
116 const {releases, build, testdir} = await mockBuild(t, {
117 testdir: {
118 'nav.yml': '- title: cli\n url: /cli',
119 },
120 })
121
122 await build()
123 t.strictSame(
124 await fs.readdir(join(testdir, 'content')),
125 releases.map(r => r.id),
126 )
127 })
128
129 t.test('prereleases', async t => {
130 const {build, releases, testdir} = await mockBuild(t, {
131 packument: {versions: ['6.14.18', '7.24.2', '8.19.3', '9.0.0-pre.2'], latest: '8.19.3'},
132 })
133
134 await build({prerelease: false})
135 const expectedReleases = releases.map(r => r.id).filter(r => r !== 'v9')
136 t.strictSame(await fs.readdir(join(testdir, 'content')), expectedReleases)
137
138 await build({prerelease: true})
139 t.strictSame(
140 await fs.readdir(join(testdir, 'content')),
141 releases.map(r => r.id),
142 )
143 })
144
145 t.test('earlier release is latest', async t => {
146 const {build} = await mockBuild(t, {
147 packument: {latest: '8.19.3'},
148 })
149
150 await build()
151 })
152
153 t.test('can skip fetching latest', async t => {
154 const {build} = await mockBuild(t)
155
156 await build({useCurrent: true})
157 })
158
159 t.test('add variant to nav', async t => {
160 const {build} = await mockBuild(t, {
161 testdir: {
162 'nav.yml': '- title: cli\n url: /cli\n variants:\n - url: /cli/v0',
163 },
164 })
165
166 await build()
167 })