Formatting

This commit is contained in:
Matthew Leibowitz
2025-05-26 03:46:39 +02:00
parent 3e924fe06b
commit eb37c9a493
5 changed files with 98 additions and 88 deletions
+41 -27
View File
@@ -30,10 +30,14 @@ jest.unstable_mockModule('@azure-rest/ai-inference', () => ({
// Default to throwing errors to catch unexpected calls // Default to throwing errors to catch unexpected calls
const mockExistsSync = jest.fn().mockImplementation(() => { const mockExistsSync = jest.fn().mockImplementation(() => {
throw new Error('Unexpected call to existsSync - test should override this implementation') throw new Error(
'Unexpected call to existsSync - test should override this implementation'
)
}) })
const mockReadFileSync = jest.fn().mockImplementation(() => { const mockReadFileSync = jest.fn().mockImplementation(() => {
throw new Error('Unexpected call to readFileSync - test should override this implementation') throw new Error(
'Unexpected call to readFileSync - test should override this implementation'
)
}) })
/** /**
@@ -41,9 +45,12 @@ const mockReadFileSync = jest.fn().mockImplementation(() => {
* @param fileContents - Object mapping file paths to their contents * @param fileContents - Object mapping file paths to their contents
* @param nonExistentFiles - Array of file paths that should be treated as non-existent * @param nonExistentFiles - Array of file paths that should be treated as non-existent
*/ */
function mockFileContent(fileContents: Record<string, string> = {}, nonExistentFiles: string[] = []): void { function mockFileContent(
fileContents: Record<string, string> = {},
nonExistentFiles: string[] = []
): void {
// Mock existsSync to return true for files that exist, false for those that don't // Mock existsSync to return true for files that exist, false for those that don't
mockExistsSync.mockImplementation(function(this: any, path: any): boolean { mockExistsSync.mockImplementation(function (this: any, path: any): boolean {
if (nonExistentFiles.includes(path)) { if (nonExistentFiles.includes(path)) {
return false return false
} }
@@ -51,7 +58,11 @@ function mockFileContent(fileContents: Record<string, string> = {}, nonExistentF
}) })
// Mock readFileSync to return the content for known files // Mock readFileSync to return the content for known files
mockReadFileSync.mockImplementation(function(this: any, path: any, encoding: any): string { mockReadFileSync.mockImplementation(function (
this: any,
path: any,
encoding: any
): string {
if (encoding === 'utf-8' && path in fileContents) { if (encoding === 'utf-8' && path in fileContents) {
return fileContents[path] return fileContents[path]
} }
@@ -66,11 +77,11 @@ function mockFileContent(fileContents: Record<string, string> = {}, nonExistentF
function mockInputs(inputs: Record<string, string> = {}): void { function mockInputs(inputs: Record<string, string> = {}): void {
// Default values that are applied unless overridden // Default values that are applied unless overridden
const defaultInputs: Record<string, string> = { const defaultInputs: Record<string, string> = {
'token': 'fake-token' token: 'fake-token'
} }
// Combine defaults with user-provided inputs // Combine defaults with user-provided inputs
const allInputs: Record<string, string> = {...defaultInputs, ...inputs} const allInputs: Record<string, string> = { ...defaultInputs, ...inputs }
core.getInput.mockImplementation((name: string) => { core.getInput.mockImplementation((name: string) => {
return allInputs[name] || '' return allInputs[name] || ''
@@ -81,11 +92,7 @@ function mockInputs(inputs: Record<string, string> = {}): void {
* Helper function to verify common response assertions * Helper function to verify common response assertions
*/ */
function verifyStandardResponse(): void { function verifyStandardResponse(): void {
expect(core.setOutput).toHaveBeenNthCalledWith( expect(core.setOutput).toHaveBeenNthCalledWith(1, 'response', 'Hello, user!')
1,
'response',
'Hello, user!'
)
expect(core.setOutput).toHaveBeenNthCalledWith( expect(core.setOutput).toHaveBeenNthCalledWith(
2, 2,
'response-file', 'response-file',
@@ -107,13 +114,13 @@ const { run } = await import('../src/main.js')
describe('main.ts', () => { describe('main.ts', () => {
// Reset all mocks before each test // Reset all mocks before each test
beforeEach(() => { beforeEach(() => {
jest.clearAllMocks(); jest.clearAllMocks()
}); })
it('Sets the response output', async () => { it('Sets the response output', async () => {
// Set the action's inputs as return values from core.getInput(). // Set the action's inputs as return values from core.getInput().
mockInputs({ mockInputs({
'prompt': 'Hello, AI!', prompt: 'Hello, AI!',
'system-prompt': 'You are a test assistant.' 'system-prompt': 'You are a test assistant.'
}) })
@@ -125,14 +132,17 @@ describe('main.ts', () => {
it('Sets a failed status when no prompt is set', async () => { it('Sets a failed status when no prompt is set', async () => {
// Clear the getInput mock and simulate no prompt or prompt-file input // Clear the getInput mock and simulate no prompt or prompt-file input
mockInputs({ mockInputs({
'prompt': '', prompt: '',
'prompt-file': '' 'prompt-file': ''
}) })
await run() await run()
// Verify that the action was marked as failed. // Verify that the action was marked as failed.
expect(core.setFailed).toHaveBeenNthCalledWith(1, 'Neither prompt-file nor prompt was set') expect(core.setFailed).toHaveBeenNthCalledWith(
1,
'Neither prompt-file nor prompt was set'
)
}) })
it('uses prompt-file', async () => { it('uses prompt-file', async () => {
@@ -188,7 +198,7 @@ describe('main.ts', () => {
// Set up input mocks // Set up input mocks
mockInputs({ mockInputs({
'prompt': promptString, prompt: promptString,
'prompt-file': promptFile, 'prompt-file': promptFile,
'system-prompt': 'You are a test assistant.' 'system-prompt': 'You are a test assistant.'
}) })
@@ -206,7 +216,7 @@ describe('main.ts', () => {
role: 'system', role: 'system',
content: expect.any(String) content: expect.any(String)
}, },
{ role: 'user', content: promptFileContent } // Should use the file content, not the string input { role: 'user', content: promptFileContent } // Should use the file content, not the string input
], ],
max_tokens: expect.any(Number), max_tokens: expect.any(Number),
model: expect.any(String) model: expect.any(String)
@@ -218,7 +228,8 @@ describe('main.ts', () => {
it('uses system-prompt-file', async () => { it('uses system-prompt-file', async () => {
const systemPromptFile = 'system-prompt.txt' const systemPromptFile = 'system-prompt.txt'
const systemPromptContent = 'You are a specialized system assistant for testing' const systemPromptContent =
'You are a specialized system assistant for testing'
// Set up mock to return specific content for the system prompt file // Set up mock to return specific content for the system prompt file
mockFileContent({ mockFileContent({
@@ -227,7 +238,7 @@ describe('main.ts', () => {
// Set up input mocks // Set up input mocks
mockInputs({ mockInputs({
'prompt': 'Hello, AI!', prompt: 'Hello, AI!',
'system-prompt-file': systemPromptFile 'system-prompt-file': systemPromptFile
}) })
@@ -246,7 +257,7 @@ describe('main.ts', () => {
// Set up input mocks // Set up input mocks
mockInputs({ mockInputs({
'prompt': 'Hello, AI!', prompt: 'Hello, AI!',
'system-prompt-file': systemPromptFile 'system-prompt-file': systemPromptFile
}) })
@@ -260,8 +271,10 @@ describe('main.ts', () => {
it('prefers system-prompt-file over system-prompt when both are provided', async () => { it('prefers system-prompt-file over system-prompt when both are provided', async () => {
const systemPromptFile = 'system-prompt.txt' const systemPromptFile = 'system-prompt.txt'
const systemPromptFileContent = 'You are a specialized system assistant from file' const systemPromptFileContent =
const systemPromptString = 'You are a basic system assistant from input parameter' 'You are a specialized system assistant from file'
const systemPromptString =
'You are a basic system assistant from input parameter'
// Set up mock to return specific content for the system prompt file // Set up mock to return specific content for the system prompt file
mockFileContent({ mockFileContent({
@@ -270,7 +283,7 @@ describe('main.ts', () => {
// Set up input mocks // Set up input mocks
mockInputs({ mockInputs({
'prompt': 'Hello, AI!', prompt: 'Hello, AI!',
'system-prompt-file': systemPromptFile, 'system-prompt-file': systemPromptFile,
'system-prompt': systemPromptString 'system-prompt': systemPromptString
}) })
@@ -302,7 +315,8 @@ describe('main.ts', () => {
const promptFile = 'prompt.txt' const promptFile = 'prompt.txt'
const promptContent = 'This is a prompt from a file' const promptContent = 'This is a prompt from a file'
const systemPromptFile = 'system-prompt.txt' const systemPromptFile = 'system-prompt.txt'
const systemPromptContent = 'You are a specialized system assistant from file' const systemPromptContent =
'You are a specialized system assistant from file'
// Set up mock to return specific content for both files // Set up mock to return specific content for both files
mockFileContent({ mockFileContent({
@@ -345,7 +359,7 @@ describe('main.ts', () => {
const customMaxTokens = 500 const customMaxTokens = 500
mockInputs({ mockInputs({
'prompt': 'Hello, AI!', prompt: 'Hello, AI!',
'system-prompt': 'You are a test assistant.', 'system-prompt': 'You are a test assistant.',
'max-tokens': customMaxTokens.toString() 'max-tokens': customMaxTokens.toString()
}) })
Generated Vendored
+30 -31
View File
@@ -33552,6 +33552,32 @@ function getPathFromMapKey(mapKey) {
} }
const RESPONSE_FILE = 'modelResponse.txt'; const RESPONSE_FILE = 'modelResponse.txt';
/**
* Helper function to load content from a file or use fallback input
* @param filePathInput - Input name for the file path
* @param contentInput - Input name for the direct content
* @param defaultValue - Default value to use if neither file nor content is provided
* @returns The loaded content
*/
function loadContentFromFileOrInput(filePathInput, contentInput, defaultValue) {
const filePath = coreExports.getInput(filePathInput);
const contentString = coreExports.getInput(contentInput);
if (filePath !== undefined && filePath !== '') {
if (!fs.existsSync(filePath)) {
throw new Error(`File for ${filePathInput} was not found: ${filePath}`);
}
return fs.readFileSync(filePath, 'utf-8');
}
else if (contentString !== undefined && contentString !== '') {
return contentString;
}
else if (defaultValue !== undefined) {
return defaultValue;
}
else {
throw new Error(`Neither ${filePathInput} nor ${contentInput} was set`);
}
}
/** /**
* The main function for the action. * The main function for the action.
* *
@@ -33559,37 +33585,10 @@ const RESPONSE_FILE = 'modelResponse.txt';
*/ */
async function run() { async function run() {
try { try {
const promptFile = coreExports.getInput('prompt-file'); // Load prompt content - required
const promptString = coreExports.getInput('prompt'); const prompt = loadContentFromFileOrInput('prompt-file', 'prompt');
let prompt; // Load system prompt with default value
if (promptFile !== undefined && promptFile !== '') { const systemPrompt = loadContentFromFileOrInput('system-prompt-file', 'system-prompt', 'You are a helpful assistant');
if (!fs.existsSync(promptFile)) {
throw new Error(`Prompt file not found: ${promptFile}`);
}
prompt = fs.readFileSync(promptFile, 'utf-8');
}
else if (promptString !== undefined && promptString !== '') {
prompt = promptString;
}
else {
throw new Error('prompt is not set');
}
const systemPromptFile = coreExports.getInput('system-prompt-file');
const systemPromptString = coreExports.getInput('system-prompt');
let systemPrompt;
if (systemPromptFile !== undefined && systemPromptFile !== '') {
if (!fs.existsSync(systemPromptFile)) {
throw new Error(`System prompt file not found: ${systemPromptFile}`);
}
systemPrompt = fs.readFileSync(systemPromptFile, 'utf-8');
}
else if (systemPromptString !== undefined && systemPromptString !== '') {
systemPrompt = systemPromptString;
}
else {
// Use default system prompt
systemPrompt = 'You are a helpful assistant';
}
const modelName = coreExports.getInput('model'); const modelName = coreExports.getInput('model');
const maxTokens = parseInt(coreExports.getInput('max-tokens'), 10); const maxTokens = parseInt(coreExports.getInput('max-tokens'), 10);
const token = coreExports.getInput('token') || process.env['GITHUB_TOKEN']; const token = coreExports.getInput('token') || process.env['GITHUB_TOKEN'];
Generated Vendored
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -32,7 +32,7 @@
"local-action": "npx @github/local-action . src/main.ts .env", "local-action": "npx @github/local-action . src/main.ts .env",
"package": "npx rollup --config rollup.config.ts --configPlugin @rollup/plugin-typescript", "package": "npx rollup --config rollup.config.ts --configPlugin @rollup/plugin-typescript",
"package:watch": "npm run package -- --watch", "package:watch": "npm run package -- --watch",
"test": "NODE_OPTIONS=--experimental-vm-modules NODE_NO_WARNINGS=1 npx jest", "test": "npx cross-env NODE_OPTIONS=--experimental-vm-modules NODE_NO_WARNINGS=1 npx jest",
"all": "npm run format:write && npm run lint && npm run test && npm run coverage && npm run package" "all": "npm run format:write && npm run lint && npm run test && npm run coverage && npm run package"
}, },
"license": "MIT", "license": "MIT",
+1 -4
View File
@@ -44,10 +44,7 @@ function loadContentFromFileOrInput(
export async function run(): Promise<void> { export async function run(): Promise<void> {
try { try {
// Load prompt content - required // Load prompt content - required
const prompt = loadContentFromFileOrInput( const prompt = loadContentFromFileOrInput('prompt-file', 'prompt')
'prompt-file',
'prompt'
)
// Load system prompt with default value // Load system prompt with default value
const systemPrompt = loadContentFromFileOrInput( const systemPrompt = loadContentFromFileOrInput(