Skip to content

Commit

Permalink
Fix scan command error handling
Browse files Browse the repository at this point in the history
fix: attempting to fix #695
  • Loading branch information
meza committed Dec 16, 2024
1 parent 9695ab9 commit 04126d3
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 2 deletions.
88 changes: 88 additions & 0 deletions src/actions/scan.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -387,4 +387,92 @@ describe('The Scan action', () => {
}
});
});

it<LocalTestContext>('handles errors gracefully and continues scanning other mods', async ({ options, logger }) => {
const name1 = chance.word();
const name2 = chance.word();
const randomResult1 = generateScanResult({ name: name1 }).generated;
const randomResult2 = generateScanResult({ name: name2 }).generated;

vi.mocked(scanLib).mockResolvedValueOnce([randomResult1, randomResult2]);
vi.mocked(shouldAddScanResults).mockResolvedValueOnce(false);

await scan(options, logger);

const logMessages = vi.mocked(logger.log).mock.calls;

expect(logMessages[0][0]).toContain(name1);
expect(logMessages[0][0]).toContain('Found unmanaged mod: ');
expect(logMessages[1][0]).toContain(name2);
expect(logMessages[1][0]).toContain('Found unmanaged mod: ');
});

it<LocalTestContext>('updates the configuration and lock files correctly for all found mods', async (context) => {
const preexistingMod = generateModConfig().generated;
const preexistingInstall = generateModInstall({
type: preexistingMod.type,
id: preexistingMod.id,
name: preexistingMod.name
}).generated;

context.randomConfiguration.mods.push(preexistingMod);
context.randomInstallations.push(preexistingInstall);

const details1 = randomModDetails();
const randomResult1 = generateScanResult(details1).generated;
const details2 = randomModDetails();
const randomResult2 = generateScanResult(details2).generated;

vi.mocked(scanLib).mockResolvedValueOnce([randomResult1, randomResult2]);
vi.mocked(shouldAddScanResults).mockResolvedValueOnce(true);

await scan(context.options, context.logger);

expect(vi.mocked(writeConfigFile)).toHaveBeenCalledOnce();
expect(vi.mocked(writeLockFile)).toHaveBeenCalledOnce();

const writtenConfig = vi.mocked(writeConfigFile).mock.calls[0][0];
const writtenLock = vi.mocked(writeLockFile).mock.calls[0][0];

expect(writtenConfig.mods).toContainEqual(preexistingMod);
expect(writtenConfig.mods).toContainEqual({
name: details1.name,
id: details1.modId,
type: details1.platform
});
expect(writtenConfig.mods).toContainEqual({
name: details2.name,
id: details2.modId,
type: details2.platform
});

expect(writtenLock).toContainEqual(preexistingInstall);
expect(writtenLock).toContainEqual({
downloadUrl: randomResult1.localDetails[0].mod.downloadUrl,
fileName: randomResult1.localDetails[0].mod.fileName,
hash: randomResult1.localDetails[0].mod.hash,
id: details1.modId,
name: details1.name,
releasedOn: randomResult1.localDetails[0].mod.releaseDate,
type: details1.platform
});
expect(writtenLock).toContainEqual({
downloadUrl: randomResult2.localDetails[0].mod.downloadUrl,
fileName: randomResult2.localDetails[0].mod.fileName,
hash: randomResult2.localDetails[0].mod.hash,
id: details2.modId,
name: details2.name,
releasedOn: randomResult2.localDetails[0].mod.releaseDate,
type: details2.platform
});
});

it<LocalTestContext>('logs detailed error messages for debugging purposes', async ({ options, logger }) => {
const error = new Error('Test error');
vi.mocked(scanLib).mockRejectedValueOnce(error);

await expect(scan(options, logger)).rejects.toThrow('process.exit');

expect(logger.error).toHaveBeenCalledWith(error.message, 2);
});
});
44 changes: 43 additions & 1 deletion src/lib/scan.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { fileIsManaged } from './configurationHelper.js';
import { getModFiles } from './fileHelper.js';
import { getHash } from './hash.js';
import { ModInstall, ModsJson, Platform } from './modlist.types.js';
import { scan } from './scan.js';
import { scan, scanFiles } from './scan.js';

vi.mock('./fileHelper.js');
vi.mock('./hash.js');
Expand Down Expand Up @@ -329,4 +329,46 @@ describe('The scan library', () => {
});
});
});

describe('scanFiles function', () => {
it('handles errors gracefully and skips problematic mods', async () => {
const files = [chance.word()];
const installations: ModInstall[] = [];
const prefer = Platform.MODRINTH;
const configuration = generateModsJson().generated;

vi.mocked(getHash).mockRejectedValueOnce(new Error('Test error'));

const result = await scanFiles(files, installations, prefer, configuration);

expect(result).toEqual([]);
});

it('logs detailed error messages for debugging purposes', async () => {
const files = [chance.word()];
const installations: ModInstall[] = [];
const prefer = Platform.MODRINTH;
const configuration = generateModsJson().generated;

const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});

vi.mocked(getHash).mockRejectedValueOnce(new Error('Test error'));

await scanFiles(files, installations, prefer, configuration);

expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining('Error fetching mod details'));
consoleErrorSpy.mockRestore();
});

it('returns an empty array when there are no files in the mods folder or all files are managed', async () => {
const files: string[] = [];
const installations: ModInstall[] = [];
const prefer = Platform.MODRINTH;
const configuration = generateModsJson().generated;

const result = await scanFiles(files, installations, prefer, configuration);

expect(result).toEqual([]);
});
});
});
5 changes: 4 additions & 1 deletion src/lib/scan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,10 @@ export const scanFiles = async (
} catch (error) {
if (!(error instanceof CurseforgeDownloadUrlError || error instanceof NoRemoteFileFound)) {
// Edge case for a freak Curseforge bug and the no remote file
throw error;
console.error(`Error fetching mod details for ${lookupResult.hits[i].modId} on ${lookupResult.hits[i].platform}: ${error.message}`);
continue; // Skip problematic mods
}
console.error(`Error fetching mod details for ${lookupResult.hits[i].modId} on ${lookupResult.hits[i].platform}: ${error.message}`);
}
}

Expand All @@ -102,6 +104,7 @@ export const scanFiles = async (
const result: ScanResults[] = [];
normalizedResults.forEach((normalizeResult) => {
if (normalizeResult.status === 'rejected') {
console.error(`Error normalizing results: ${normalizeResult.reason}`);
return;
}

Expand Down

0 comments on commit 04126d3

Please sign in to comment.