Skip to content
Open
9 changes: 9 additions & 0 deletions __tests__/cache.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ describe('dependency cache', () => {
let spyWarning: jest.SpyInstance<void, Parameters<typeof core.warning>>;
let spyDebug: jest.SpyInstance<void, Parameters<typeof core.debug>>;
let spySaveState: jest.SpyInstance<void, Parameters<typeof core.saveState>>;
let spyCoreError: jest.SpyInstance;

beforeEach(() => {
workspace = mkdtempSync(join(tmpdir(), 'setup-java-cache-'));
Expand Down Expand Up @@ -51,13 +52,21 @@ describe('dependency cache', () => {

spySaveState = jest.spyOn(core, 'saveState');
spySaveState.mockImplementation(() => null);

// Mock core.error to suppress error logs
spyCoreError = jest.spyOn(core, 'error');
spyCoreError.mockImplementation(() => {});
});

afterEach(() => {
process.chdir(ORIGINAL_CWD);
process.env['GITHUB_WORKSPACE'] = ORIGINAL_GITHUB_WORKSPACE;
process.env['RUNNER_OS'] = ORIGINAL_RUNNER_OS;
resetState();

jest.resetAllMocks();
jest.clearAllMocks();
jest.restoreAllMocks();
});

describe('restore', () => {
Expand Down
13 changes: 13 additions & 0 deletions __tests__/cleanup-java.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,32 @@ describe('cleanup', () => {
Parameters<typeof cache.saveCache>
>;
let spyJobStatusSuccess: jest.SpyInstance;
let spyCoreError: jest.SpyInstance;

beforeEach(() => {
spyWarning = jest.spyOn(core, 'warning');
spyWarning.mockImplementation(() => null);

spyInfo = jest.spyOn(core, 'info');
spyInfo.mockImplementation(() => null);

spyCacheSave = jest.spyOn(cache, 'saveCache');

spyJobStatusSuccess = jest.spyOn(util, 'isJobStatusSuccess');
spyJobStatusSuccess.mockReturnValue(true);

// Mock core.error to suppress error logs
spyCoreError = jest.spyOn(core, 'error');
spyCoreError.mockImplementation(() => {});

createStateForSuccessfulRestore();
});

afterEach(() => {
resetState();
jest.resetAllMocks();
jest.clearAllMocks();
jest.restoreAllMocks();
});

it('does not fail nor warn even when the save process throws a ReserveCacheError', async () => {
Expand Down
6 changes: 6 additions & 0 deletions __tests__/distributors/adopt-installer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ import {JavaInstallerOptions} from '../../src/distributions/base-models';
import os from 'os';

import manifestData from '../data/adopt.json';
import * as core from '@actions/core';

describe('getAvailableVersions', () => {
let spyHttpClient: jest.SpyInstance;
let spyCoreError: jest.SpyInstance;

beforeEach(() => {
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
Expand All @@ -20,6 +22,10 @@ describe('getAvailableVersions', () => {
headers: {},
result: []
});

// Mock core.error to suppress error logs
spyCoreError = jest.spyOn(core, 'error');
spyCoreError.mockImplementation(() => {});
});

afterEach(() => {
Expand Down
121 changes: 107 additions & 14 deletions __tests__/distributors/base-installer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class EmptyJavaBase extends JavaBase {
): Promise<JavaDownloadRelease> {
const availableVersion = '11.0.9';
if (!semver.satisfies(availableVersion, range)) {
throw new Error('Available version not found');
throw this.createVersionNotFoundError(range, [availableVersion]);
}

return {
Expand Down Expand Up @@ -248,6 +248,7 @@ describe('setupJava', () => {
let spyCoreExportVariable: jest.SpyInstance;
let spyCoreAddPath: jest.SpyInstance;
let spyCoreSetOutput: jest.SpyInstance;
let spyCoreError: jest.SpyInstance;

beforeEach(() => {
spyGetToolcachePath = jest.spyOn(util, 'getToolcachePath');
Expand Down Expand Up @@ -287,6 +288,10 @@ describe('setupJava', () => {
spyCoreSetOutput = jest.spyOn(core, 'setOutput');
spyCoreSetOutput.mockImplementation(() => undefined);

// Mock core.error to suppress error logs
spyCoreError = jest.spyOn(core, 'error');
spyCoreError.mockImplementation(() => undefined);

jest.spyOn(os, 'arch').mockReturnValue('x86' as ReturnType<typeof os.arch>);
});

Expand Down Expand Up @@ -530,19 +535,16 @@ describe('setupJava', () => {
checkLatest: false
}
]
])(
'should throw an error for Available version not found for %s',
async input => {
mockJavaBase = new EmptyJavaBase(input);
await expect(mockJavaBase.setupJava()).rejects.toThrow(
'Available version not found'
);
expect(spyTcFindAllVersions).toHaveBeenCalled();
expect(spyCoreAddPath).not.toHaveBeenCalled();
expect(spyCoreExportVariable).not.toHaveBeenCalled();
expect(spyCoreSetOutput).not.toHaveBeenCalled();
}
);
])('should throw an error for version not found for %s', async input => {
mockJavaBase = new EmptyJavaBase(input);
await expect(mockJavaBase.setupJava()).rejects.toThrow(
`Could not find satisfied version for SemVer '${input.version}'`
);
expect(spyTcFindAllVersions).toHaveBeenCalled();
expect(spyCoreAddPath).not.toHaveBeenCalled();
expect(spyCoreExportVariable).not.toHaveBeenCalled();
expect(spyCoreSetOutput).not.toHaveBeenCalled();
});
});

describe('normalizeVersion', () => {
Expand Down Expand Up @@ -570,6 +572,97 @@ describe('normalizeVersion', () => {
});
});

describe('createVersionNotFoundError', () => {
it('should include all required fields in error message without available versions', () => {
const mockJavaBase = new EmptyJavaBase({
version: '17.0.5',
architecture: 'x64',
packageType: 'jdk',
checkLatest: false
});

const error = (mockJavaBase as any).createVersionNotFoundError('17.0.5');

expect(error.message).toContain(
"Could not find satisfied version for SemVer '17.0.5'"
);
expect(error.message).toContain('Distribution: Empty');
expect(error.message).toContain('Package type: jdk');
expect(error.message).toContain('Architecture: x64');
});

it('should include available versions when provided', () => {
const mockJavaBase = new EmptyJavaBase({
version: '17.0.5',
architecture: 'x64',
packageType: 'jdk',
checkLatest: false
});

const availableVersions = ['11.0.1', '11.0.2', '17.0.1', '17.0.2'];
const error = (mockJavaBase as any).createVersionNotFoundError(
'17.0.5',
availableVersions
);

expect(error.message).toContain(
"Could not find satisfied version for SemVer '17.0.5'"
);
expect(error.message).toContain('Distribution: Empty');
expect(error.message).toContain('Package type: jdk');
expect(error.message).toContain('Architecture: x64');
expect(error.message).toContain(
'Available versions: 11.0.1, 11.0.2, 17.0.1, 17.0.2'
);
});

it('should truncate available versions when there are many', () => {
const mockJavaBase = new EmptyJavaBase({
version: '17.0.5',
architecture: 'x64',
packageType: 'jdk',
checkLatest: false
});

// Create 60 versions to test truncation
const availableVersions = Array.from({length: 60}, (_, i) => `11.0.${i}`);
const error = (mockJavaBase as any).createVersionNotFoundError(
'17.0.5',
availableVersions
);

expect(error.message).toContain('Available versions:');
expect(error.message).toContain('...');
expect(error.message).toContain('(showing first 50 of 60 versions');
});

it('should include additional context when provided', () => {
const mockJavaBase = new EmptyJavaBase({
version: '17.0.5',
architecture: 'x64',
packageType: 'jdk',
checkLatest: false
});

const availableVersions = ['11.0.1', '11.0.2'];
const additionalContext = 'Platform: linux';
const error = (mockJavaBase as any).createVersionNotFoundError(
'17.0.5',
availableVersions,
additionalContext
);

expect(error.message).toContain(
"Could not find satisfied version for SemVer '17.0.5'"
);
expect(error.message).toContain('Distribution: Empty');
expect(error.message).toContain('Package type: jdk');
expect(error.message).toContain('Architecture: x64');
expect(error.message).toContain('Platform: linux');
expect(error.message).toContain('Available versions: 11.0.1, 11.0.2');
});
});

describe('getToolcacheVersionName', () => {
const DummyJavaBase = JavaBase as any;

Expand Down
7 changes: 6 additions & 1 deletion __tests__/distributors/corretto-installer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ import {JavaInstallerOptions} from '../../src/distributions/base-models';
import {CorrettoDistribution} from '../../src/distributions/corretto/installer';
import * as util from '../../src/util';
import os from 'os';
import {isGeneratorFunction} from 'util/types';
import * as core from '@actions/core';

import manifestData from '../data/corretto.json';

describe('getAvailableVersions', () => {
let spyHttpClient: jest.SpyInstance;
let spyGetDownloadArchiveExtension: jest.SpyInstance;
let spyCoreError: jest.SpyInstance;

beforeEach(() => {
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
Expand All @@ -23,6 +24,10 @@ describe('getAvailableVersions', () => {
util,
'getDownloadArchiveExtension'
);

// Mock core.error to suppress error logs
spyCoreError = jest.spyOn(core, 'error');
spyCoreError.mockImplementation(() => {});
});

afterEach(() => {
Expand Down
8 changes: 7 additions & 1 deletion __tests__/distributors/dragonwell-installer.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import {HttpClient} from '@actions/http-client';
import {DragonwellDistribution} from '../../src/distributions/dragonwell/installer';
import * as utils from '../../src/util';
import * as core from '@actions/core';

import manifestData from '../data/dragonwell.json';

describe('getAvailableVersions', () => {
let spyHttpClient: jest.SpyInstance;
let spyUtilGetDownloadArchiveExtension: jest.SpyInstance;
let spyCoreError: jest.SpyInstance;

beforeEach(() => {
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
Expand All @@ -21,6 +23,10 @@ describe('getAvailableVersions', () => {
'getDownloadArchiveExtension'
);
spyUtilGetDownloadArchiveExtension.mockReturnValue('tar.gz');

// Mock core.error to suppress error logs
spyCoreError = jest.spyOn(core, 'error');
spyCoreError.mockImplementation(() => {});
});

afterEach(() => {
Expand Down Expand Up @@ -232,7 +238,7 @@ describe('getAvailableVersions', () => {
await expect(
distribution['findPackageForDownload'](jdkVersion)
).rejects.toThrow(
`Couldn't find any satisfied version for the specified java-version: "${jdkVersion}" and architecture: "${arch}".`
`Could not find satisfied version for SemVer '${jdkVersion}'`
);
}
);
Expand Down
28 changes: 18 additions & 10 deletions __tests__/distributors/graalvm-installer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ beforeAll(() => {
describe('GraalVMDistribution', () => {
let distribution: GraalVMDistribution;
let mockHttpClient: jest.Mocked<http.HttpClient>;
let spyCoreError: jest.SpyInstance;

const defaultOptions: JavaInstallerOptions = {
version: '17',
Expand All @@ -59,6 +60,10 @@ describe('GraalVMDistribution', () => {
(distribution as any).http = mockHttpClient;

(util.getDownloadArchiveExtension as jest.Mock).mockReturnValue('tar.gz');

// Mock core.error to suppress error logs
spyCoreError = jest.spyOn(core, 'error');
spyCoreError.mockImplementation(() => {});
});

afterAll(() => {
Expand Down Expand Up @@ -348,11 +353,17 @@ describe('GraalVMDistribution', () => {
} as http.HttpClientResponse;
mockHttpClient.head.mockResolvedValue(mockResponse);

// Verify the error is thrown with the expected message
await expect(
(distribution as any).findPackageForDownload('17.0.99')
).rejects.toThrow(
'Could not find GraalVM for SemVer 17.0.99. Please check if this version is available at https://download.oracle.com/graalvm'
"Could not find satisfied version for SemVer '17.0.99'"
);

// Verify the hint about checking the base URL is included
await expect(
(distribution as any).findPackageForDownload('17.0.99')
).rejects.toThrow('https://download.oracle.com/graalvm');
});

it('should throw error for unauthorized access (401)', async () => {
Expand Down Expand Up @@ -496,12 +507,11 @@ describe('GraalVMDistribution', () => {

await expect(
(distribution as any).findPackageForDownload('23')
).rejects.toThrow("Unable to find latest version for '23-ea'");

// Verify error logging
expect(core.error).toHaveBeenCalledWith(
'Available versions: 23-ea-20240716'
).rejects.toThrow(
"Could not find satisfied version for SemVer '23-ea'"
);

// Verify error logging - removed as we now use the helper method which doesn't call core.error
});

it('should throw error when no matching file for architecture in EA build', async () => {
Expand Down Expand Up @@ -708,11 +718,9 @@ describe('GraalVMDistribution', () => {

await expect(
(distribution as any).findEABuildDownloadUrl('23-ea')
).rejects.toThrow("Unable to find latest version for '23-ea'");
).rejects.toThrow("Could not find satisfied version for SemVer '23-ea'");

expect(core.error).toHaveBeenCalledWith(
'Available versions: 23-ea-20240716, 23-ea-20240709'
);
// Verify error logging - removed as we now use the helper method which doesn't call core.error
});

it('should throw error when no matching file for architecture', async () => {
Expand Down
6 changes: 6 additions & 0 deletions __tests__/distributors/jetbrains-installer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import {JetBrainsDistribution} from '../../src/distributions/jetbrains/installer

import manifestData from '../data/jetbrains.json';
import os from 'os';
import * as core from '@actions/core';

describe('getAvailableVersions', () => {
let spyHttpClient: jest.SpyInstance;
let spyCoreError: jest.SpyInstance;

beforeEach(() => {
spyHttpClient = jest.spyOn(HttpClient.prototype, 'getJson');
Expand All @@ -15,6 +17,10 @@ describe('getAvailableVersions', () => {
headers: {},
result: []
});

// Mock core.error to suppress error logs
spyCoreError = jest.spyOn(core, 'error');
spyCoreError.mockImplementation(() => {});
});

afterEach(() => {
Expand Down
Loading
Loading