import { jest, describe, it, expect, beforeEach, afterEach, beforeAll, afterAll } from '@jest/globals'; import {fileURLToPath} from 'url'; import * as io from '@actions/io'; import * as fs from 'fs'; import * as path from 'path'; import os from 'os'; // Mock @actions/core before importing source modules that depend on it jest.unstable_mockModule('@actions/core', () => ({ info: jest.fn(), warning: jest.fn(), debug: jest.fn(), error: jest.fn(), notice: jest.fn(), setFailed: jest.fn(), setOutput: jest.fn(), getInput: jest.fn(), getBooleanInput: jest.fn(), getMultilineInput: jest.fn(), addPath: jest.fn(), exportVariable: jest.fn(), saveState: jest.fn(), getState: jest.fn(), setSecret: jest.fn(), isDebug: jest.fn(() => false), startGroup: jest.fn(), endGroup: jest.fn(), group: jest.fn((_name: string, fn: () => Promise) => fn()), toPlatformPath: jest.fn((p: string) => p), toWin32Path: jest.fn((p: string) => p), toPosixPath: jest.fn((p: string) => p) })); // Dynamic imports after mocking const core = await import('@actions/core'); const auth = await import('../src/auth.js'); const {M2_DIR, MVN_SETTINGS_FILE} = await import('../src/constants.js'); const __dirname = path.dirname(fileURLToPath(import.meta.url)); const m2Dir = path.join(__dirname, M2_DIR); const settingsFile = path.join(m2Dir, MVN_SETTINGS_FILE); describe('auth tests', () => { let spyOSHomedir: any; let spyInfo: any; beforeEach(async () => { await io.rmRF(m2Dir); spyOSHomedir = jest.spyOn(os, 'homedir'); spyOSHomedir.mockReturnValue(__dirname); spyInfo = core.info as jest.Mock; spyInfo.mockImplementation(() => null); }, 300000); afterAll(async () => { try { await io.rmRF(m2Dir); } catch { console.log('Failed to remove test directories'); } jest.resetAllMocks(); jest.clearAllMocks(); jest.restoreAllMocks(); }, 100000); it('creates settings.xml in alternate locations', async () => { const id = 'packages'; const username = 'UNAMI'; const password = 'TOLKIEN'; const altHome = path.join(__dirname, 'runner', 'settings'); const altSettingsFile = path.join(altHome, MVN_SETTINGS_FILE); await io.rmRF(altHome); // ensure it doesn't already exist await auth.createAuthenticationSettings( id, username, password, altHome, true ); expect(fs.existsSync(m2Dir)).toBe(false); expect(fs.existsSync(settingsFile)).toBe(false); expect(fs.existsSync(altHome)).toBe(true); expect(fs.existsSync(altSettingsFile)).toBe(true); expect(fs.readFileSync(altSettingsFile, 'utf-8')).toEqual( auth.generate(id, username, password) ); await io.rmRF(altHome); }, 100000); it('creates settings.xml with minimal configuration', async () => { const id = 'packages'; const username = 'UNAME'; const password = 'TOKEN'; await auth.createAuthenticationSettings( id, username, password, m2Dir, true ); expect(fs.existsSync(m2Dir)).toBe(true); expect(fs.existsSync(settingsFile)).toBe(true); expect(fs.readFileSync(settingsFile, 'utf-8')).toEqual( auth.generate(id, username, password) ); }, 100000); it('creates settings.xml with additional configuration', async () => { const id = 'packages'; const username = 'UNAME'; const password = 'TOKEN'; const gpgPassphrase = 'GPG'; await auth.createAuthenticationSettings( id, username, password, m2Dir, true, gpgPassphrase ); expect(fs.existsSync(m2Dir)).toBe(true); expect(fs.existsSync(settingsFile)).toBe(true); expect(fs.readFileSync(settingsFile, 'utf-8')).toEqual( auth.generate(id, username, password, gpgPassphrase) ); }, 100000); it('overwrites existing settings.xml files', async () => { const id = 'packages'; const username = 'USERNAME'; const password = 'PASSWORD'; fs.mkdirSync(m2Dir, {recursive: true}); fs.writeFileSync(settingsFile, 'FAKE FILE'); expect(fs.existsSync(m2Dir)).toBe(true); expect(fs.existsSync(settingsFile)).toBe(true); await auth.createAuthenticationSettings( id, username, password, m2Dir, true ); expect(fs.existsSync(m2Dir)).toBe(true); expect(fs.existsSync(settingsFile)).toBe(true); expect(fs.readFileSync(settingsFile, 'utf-8')).toEqual( auth.generate(id, username, password) ); }, 100000); it('does not overwrite existing settings.xml files', async () => { const id = 'packages'; const username = 'USERNAME'; const password = 'PASSWORD'; fs.mkdirSync(m2Dir, {recursive: true}); fs.writeFileSync(settingsFile, 'FAKE FILE'); expect(fs.existsSync(m2Dir)).toBe(true); expect(fs.existsSync(settingsFile)).toBe(true); await auth.createAuthenticationSettings( id, username, password, m2Dir, false ); expect(fs.existsSync(m2Dir)).toBe(true); expect(fs.existsSync(settingsFile)).toBe(true); expect(fs.readFileSync(settingsFile, 'utf-8')).toEqual('FAKE FILE'); }, 100000); it('generates valid settings.xml with minimal configuration', () => { const id = 'packages'; const username = 'USER'; const password = '&<>"\'\'"><&'; const expectedSettings = ` false ${id} \${env.${username}} \${env.&<>"''"><&} `; expect(auth.generate(id, username, password)).toEqual(expectedSettings); }); it('generates valid settings.xml with additional configuration', () => { const id = 'packages'; const username = 'USER'; const password = '&<>"\'\'"><&'; const gpgPassphrase = 'PASSPHRASE'; const expectedSettings = ` false ${id} \${env.${username}} \${env.&<>"''"><&} gpg.passphrase \${env.${gpgPassphrase}} `; expect(auth.generate(id, username, password, gpgPassphrase)).toEqual( expectedSettings ); }); });