this repo has no description
at main 235 lines 6.9 kB view raw
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})