this repo has no description
1import assert from 'node:assert/strict'
2import { access, mkdir, rm, writeFile } from 'node:fs/promises'
3import { join } from 'node:path'
4import { describe, test } from 'node:test'
5import { installRelease } from '../src/index.js'
6import { getPlatformInfo } from '../src/platform.js'
7
8describe('Error Handling', () => {
9 test('installRelease throws error for invalid repo', async (t) => {
10 t.mock.method(global, 'fetch', async () => {
11 return {
12 ok: false,
13 status: 404,
14 statusText: 'Not Found',
15 } as Response
16 })
17
18 await assert.rejects(
19 async () => await installRelease('invalid/repo', 'v1.0.0'),
20 /Release v1.0.0 not found for repository invalid\/repo/,
21 )
22 })
23
24 test('installRelease throws error for invalid version', async (t) => {
25 t.mock.method(global, 'fetch', async () => {
26 return {
27 ok: false,
28 status: 404,
29 statusText: 'Not Found',
30 } as Response
31 })
32
33 await assert.rejects(
34 async () => await installRelease('getzola/zola', 'v999.999.999'),
35 /Release v999.999.999 not found for repository getzola\/zola/,
36 )
37 })
38
39 test('installRelease throws error when no matching asset found', async (t) => {
40 // Mock a successful release response but with assets that don't match
41 const mockReleaseData = {
42 tag_name: 'v0.20.0',
43 assets: [
44 {
45 name: 'zola-v0.20.0-x86_64-unknown-linux-gnu.tar.gz',
46 browser_download_url: 'https://example.com/download',
47 size: 15728640,
48 },
49 ],
50 }
51
52 t.mock.method(global, 'fetch', async () => {
53 return {
54 ok: true,
55 json: async () => mockReleaseData,
56 } as Response
57 })
58
59 // Test with a platform map that points to a non-existent asset
60 // The current platform will use the custom mapping and fail to find the asset
61 const currentPlatform = getPlatformInfo()
62
63 await assert.rejects(
64 async () =>
65 await installRelease('getzola/zola', 'v0.20.0', {
66 platformMap: {
67 [currentPlatform.combined]: 'nonexistent-asset.tar.gz',
68 },
69 }),
70 /Release asset nonexistent-asset.tar.gz not found in release/,
71 )
72 })
73
74 test('installRelease handles malformed repo name', async (t) => {
75 t.mock.method(global, 'fetch', async () => {
76 return {
77 ok: false,
78 status: 404,
79 statusText: 'Not Found',
80 } as Response
81 })
82
83 await assert.rejects(
84 async () => await installRelease('malformed-repo-name', 'v1.0.0'),
85 /Release v1.0.0 not found for repository malformed-repo-name/,
86 )
87 })
88
89 test('installRelease validates custom platform mapping', async (t) => {
90 // Mock a successful release response but with assets that don't match
91 const mockReleaseData = {
92 tag_name: 'v0.20.0',
93 assets: [
94 {
95 name: 'zola-v0.20.0-x86_64-unknown-linux-gnu.tar.gz',
96 browser_download_url: 'https://example.com/download',
97 size: 15728640,
98 },
99 ],
100 }
101
102 t.mock.method(global, 'fetch', async () => {
103 return {
104 ok: true,
105 json: async () => mockReleaseData,
106 } as Response
107 })
108
109 const currentPlatform = getPlatformInfo()
110
111 await assert.rejects(
112 async () =>
113 await installRelease('getzola/zola', 'v0.20.0', {
114 platformMap: {
115 [currentPlatform.combined]: 'nonexistent-file.tar.gz',
116 },
117 }),
118 /Release asset nonexistent-file.tar.gz not found in release/,
119 )
120 })
121
122 test('installRelease throws error when binary exists without force flag', async (t) => {
123 // Mock a successful release response
124 const mockReleaseData = {
125 tag_name: 'v0.20.0',
126 assets: [
127 {
128 name: 'test-app-v0.20.0-x86_64-apple-darwin.tar.gz',
129 browser_download_url: 'https://example.com/download',
130 size: 15728640,
131 },
132 ],
133 }
134
135 t.mock.method(global, 'fetch', async () => {
136 return {
137 ok: true,
138 json: async () => mockReleaseData,
139 } as Response
140 })
141
142 // Get current platform for accurate testing
143 const currentPlatform = getPlatformInfo()
144
145 // Create a test directory with an existing binary
146 const testDir = './test-force-flag'
147 const binaryPath = `${testDir}/app`
148
149 await mkdir(testDir, { recursive: true })
150 await writeFile(binaryPath, 'existing binary')
151
152 try {
153 await assert.rejects(
154 async () =>
155 await installRelease('test/app', 'v0.20.0', {
156 outputDir: testDir,
157 platformMap: {
158 [currentPlatform.combined]: 'test-app-v0.20.0-x86_64-apple-darwin.tar.gz',
159 },
160 }),
161 /Binary .* already exists. Use --force to overwrite./,
162 )
163 } finally {
164 // Clean up
165 await rm(testDir, { recursive: true }).catch(() => {})
166 }
167 })
168
169 test('installRelease cleans up archive after extraction failure', async (t) => {
170 // Mock a successful release response
171 const mockReleaseData = {
172 tag_name: 'v0.20.0',
173 assets: [
174 {
175 name: 'test-app-v0.20.0-x86_64-apple-darwin.tar.gz',
176 browser_download_url: 'https://example.com/download',
177 size: 15728640,
178 },
179 ],
180 }
181
182 let downloadCallCount = 0
183 t.mock.method(global, 'fetch', async (url: string) => {
184 if (url.includes('api.github.com')) {
185 return {
186 ok: true,
187 json: async () => mockReleaseData,
188 } as Response
189 }
190
191 // Mock download that succeeds but creates invalid archive
192 downloadCallCount++
193 return {
194 ok: true,
195 body: new ReadableStream({
196 start(controller) {
197 // Create content that will fail extraction (invalid gzip)
198 controller.enqueue(new Uint8Array([0x00, 0x01, 0x02, 0x03]))
199 controller.close()
200 },
201 }),
202 } as Response
203 })
204
205 const currentPlatform = getPlatformInfo()
206 const testDir = './test-cleanup-after-failure'
207
208 try {
209 await assert.rejects(
210 async () =>
211 await installRelease('test/app', 'v0.20.0', {
212 outputDir: testDir,
213 platformMap: {
214 [currentPlatform.combined]: 'test-app-v0.20.0-x86_64-apple-darwin.tar.gz',
215 },
216 }),
217 // Should fail during extraction but still clean up
218 )
219
220 // Verify download was called
221 assert.equal(downloadCallCount, 1)
222
223 // Verify archive was cleaned up (temp file shouldn't exist)
224 const tempPath = join(testDir, 'test-app-v0.20.0-x86_64-apple-darwin.tar.gz')
225
226 await assert.rejects(
227 async () => await access(tempPath),
228 // File should not exist (cleaned up)
229 )
230 } finally {
231 // Clean up test directory
232 await rm(testDir, { recursive: true }).catch(() => {})
233 }
234 })
235})