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 getFile: async ({ref}) => navSection(ref),
88 pathExists: async (ref, p) => {
89 if (ref.includes('v6') && p.includes('docs/lib/content')) {
90 return null
91 }
92 return p
93 },
94 nwo: `npm/cli`,
95 },
96 })
97
98 return {
99 testdir,
100 releases,
101 build: opts =>
102 build({
103 releases,
104 contentPath: join(testdir, 'content'),
105 navPath: join(testdir, 'nav.yml'),
106 ...opts,
107 }),
108 }
109 }
110
111 t.test('basic', async t => {
112 const {releases, build, testdir} = await mockBuild(t, {
113 testdir: {
114 'nav.yml': '- title: cli\n url: /cli',
115 },
116 })
117
118 await build()
119 t.strictSame(
120 await fs.readdir(join(testdir, 'content')),
121 releases.map(r => r.id),
122 )
123 })
124
125 t.test('prereleases', async t => {
126 const {build, releases, testdir} = await mockBuild(t, {
127 packument: {versions: ['6.14.18', '7.24.2', '8.19.3', '9.0.0-pre.2'], latest: '8.19.3'},
128 })
129
130 await build({prerelease: false})
131 const expectedReleases = releases.map(r => r.id).filter(r => r !== 'v9')
132 t.strictSame(await fs.readdir(join(testdir, 'content')), expectedReleases)
133
134 await build({prerelease: true})
135 t.strictSame(
136 await fs.readdir(join(testdir, 'content')),
137 releases.map(r => r.id),
138 )
139 })
140
141 t.test('earlier release is latest', async t => {
142 const {build} = await mockBuild(t, {
143 packument: {latest: '8.19.3'},
144 })
145
146 await build()
147 })
148
149 t.test('can skip fetching latest', async t => {
150 const {build} = await mockBuild(t)
151
152 await build({useCurrent: true})
153 })
154
155 t.test('add variant to nav', async t => {
156 const {build} = await mockBuild(t, {
157 testdir: {
158 'nav.yml': '- title: cli\n url: /cli\n variants:\n - url: /cli/v0',
159 },
160 })
161
162 await build()
163 })