From 9a869e9c495594ef543eb00e3fc11b1696ccc56c Mon Sep 17 00:00:00 2001 From: Ryan Ghadimi <114221941+GhadimiR@users.noreply.github.com> Date: Wed, 19 Mar 2025 11:21:30 +0000 Subject: [PATCH] Lint --- __tests__/download.test.ts | 339 ++++++++++++++++++------------------- 1 file changed, 164 insertions(+), 175 deletions(-) diff --git a/__tests__/download.test.ts b/__tests__/download.test.ts index 581824b..1b74d70 100644 --- a/__tests__/download.test.ts +++ b/__tests__/download.test.ts @@ -1,19 +1,8 @@ import * as core from '@actions/core' -import * as github from '@actions/github' -import * as os from 'os' import artifact, {ArtifactNotFoundError} from '@actions/artifact' import {run} from '../src/download-artifact' import {Inputs} from '../src/constants' -const fixtures = { - artifactName: 'artifact-name', - rootDirectory: '/some/artifact/path', - filesToUpload: [ - '/some/artifact/path/file1.txt', - '/some/artifact/path/file2.txt' - ] -} - jest.mock('@actions/github', () => ({ context: { repo: { @@ -27,7 +16,7 @@ jest.mock('@actions/github', () => ({ jest.mock('@actions/core') -/* eslint-disable no-unused-vars */ +/* eslint-disable no-unused-vars */ /* eslint-disable @typescript-eslint/no-explicit-any */ const mockInputs = (overrides?: Partial<{[K in Inputs]?: any}>) => { const inputs = { [Inputs.Name]: 'artifact-name', @@ -50,177 +39,177 @@ const mockInputs = (overrides?: Partial<{[K in Inputs]?: any}>) => { } describe('download', () => { - beforeEach(async () => { - mockInputs() - jest.clearAllMocks() - - // Mock artifact client methods - jest.spyOn(artifact, 'listArtifacts').mockImplementation(() => - Promise.resolve({ artifacts: [] }) - ) - jest.spyOn(artifact, 'getArtifact').mockImplementation((name) => { - throw new ArtifactNotFoundError(`Artifact '${name}' not found`) + beforeEach(async () => { + mockInputs() + jest.clearAllMocks() + + // Mock artifact client methods + jest + .spyOn(artifact, 'listArtifacts') + .mockImplementation(() => Promise.resolve({artifacts: []})) + jest.spyOn(artifact, 'getArtifact').mockImplementation(name => { + throw new ArtifactNotFoundError(`Artifact '${name}' not found`) + }) + jest + .spyOn(artifact, 'downloadArtifact') + .mockImplementation(() => Promise.resolve({digestMismatch: false})) + }) + + test('downloads a single artifact by name', async () => { + const mockArtifact = { + id: 123, + name: 'artifact-name', + size: 1024, + digest: 'abc123' + } + + jest + .spyOn(artifact, 'getArtifact') + .mockImplementation(() => Promise.resolve({artifact: mockArtifact})) + + await run() + + expect(artifact.downloadArtifact).toHaveBeenCalledWith( + mockArtifact.id, + expect.objectContaining({ + expectedHash: mockArtifact.digest }) - jest.spyOn(artifact, 'downloadArtifact').mockImplementation(() => - Promise.resolve({ digestMismatch: false }) - ) + ) + expect(core.info).toHaveBeenCalledWith('Total of 1 artifact(s) downloaded') + }) + + test('downloads multiple artifacts when no name or pattern provided', async () => { + jest.clearAllMocks() + mockInputs({ + [Inputs.Name]: '', + [Inputs.Pattern]: '' }) - test('downloads a single artifact by name', async () => { - const mockArtifact = { - id: 123, - name: 'artifact-name', - size: 1024, - digest: 'abc123' - } - - jest.spyOn(artifact, 'getArtifact').mockImplementation(() => - Promise.resolve({ artifact: mockArtifact }) - ) - - await run() - - expect(artifact.downloadArtifact).toHaveBeenCalledWith( - mockArtifact.id, - expect.objectContaining({ - expectedHash: mockArtifact.digest - }) - ) - expect(core.info).toHaveBeenCalledWith('Total of 1 artifact(s) downloaded') + const mockArtifacts = [ + {id: 123, name: 'artifact1', size: 1024, digest: 'abc123'}, + {id: 456, name: 'artifact2', size: 2048, digest: 'def456'} + ] + + // Set up artifact mock after clearing mocks + jest + .spyOn(artifact, 'listArtifacts') + .mockImplementation(() => Promise.resolve({artifacts: mockArtifacts})) + + // Reset downloadArtifact mock as well + jest + .spyOn(artifact, 'downloadArtifact') + .mockImplementation(() => Promise.resolve({digestMismatch: false})) + + await run() + + expect(core.info).toHaveBeenCalledWith( + 'No input name or pattern filtered specified, downloading all artifacts' + ) + + expect(core.info).toHaveBeenCalledWith('Total of 2 artifact(s) downloaded') + expect(artifact.downloadArtifact).toHaveBeenCalledTimes(2) + }) + + test('sets download path output even when no artifacts are found', async () => { + mockInputs({[Inputs.Name]: ''}) + + await run() + + expect(core.setOutput).toHaveBeenCalledWith( + 'download-path', + expect.any(String) + ) + + expect(core.info).toHaveBeenCalledWith( + 'Download artifact has finished successfully' + ) + + expect(core.info).toHaveBeenCalledWith('Total of 0 artifact(s) downloaded') + }) + + test('filters artifacts by pattern', async () => { + const mockArtifacts = [ + {id: 123, name: 'test-artifact', size: 1024, digest: 'abc123'}, + {id: 456, name: 'prod-artifact', size: 2048, digest: 'def456'} + ] + + jest + .spyOn(artifact, 'listArtifacts') + .mockImplementation(() => Promise.resolve({artifacts: mockArtifacts})) + + mockInputs({ + [Inputs.Name]: '', + [Inputs.Pattern]: 'test-*' }) - test('downloads multiple artifacts when no name or pattern provided', async () => { - jest.clearAllMocks() - mockInputs({ - [Inputs.Name]: '', - [Inputs.Pattern]: '' + await run() + + expect(artifact.downloadArtifact).toHaveBeenCalledTimes(1) + expect(artifact.downloadArtifact).toHaveBeenCalledWith( + 123, + expect.anything() + ) + }) + + test('uses token and repository information when provided', async () => { + const token = 'ghp_testtoken123' + + mockInputs({ + [Inputs.Name]: '', + [Inputs.GitHubToken]: token, + [Inputs.Repository]: 'myorg/myrepo', + [Inputs.RunID]: '789' + }) + + jest + .spyOn(artifact, 'listArtifacts') + .mockImplementation(() => Promise.resolve({artifacts: []})) + + await run() + + expect(artifact.listArtifacts).toHaveBeenCalledWith( + expect.objectContaining({ + findBy: { + token, + workflowRunId: 789, + repositoryName: 'myrepo', + repositoryOwner: 'myorg' + } }) - - const mockArtifacts = [ - { id: 123, name: 'artifact1', size: 1024, digest: 'abc123' }, - { id: 456, name: 'artifact2', size: 2048, digest: 'def456' } - ] - - // Set up artifact mock after clearing mocks - jest.spyOn(artifact, 'listArtifacts').mockImplementation(() => - Promise.resolve({ artifacts: mockArtifacts }) - ) - - // Reset downloadArtifact mock as well - jest.spyOn(artifact, 'downloadArtifact').mockImplementation(() => - Promise.resolve({ digestMismatch: false }) - ) - - await run() + ) + }) - expect(core.info).toHaveBeenCalledWith('No input name or pattern filtered specified, downloading all artifacts') - - expect(core.info).toHaveBeenCalledWith('Total of 2 artifact(s) downloaded') - expect(artifact.downloadArtifact).toHaveBeenCalledTimes(2) - }) - - test('sets download path output even when no artifacts are found', async () => { - mockInputs({ [Inputs.Name]: '' }) - - await run() - - expect(core.setOutput).toHaveBeenCalledWith( - 'download-path', - expect.any(String) - ) - - expect(core.info).toHaveBeenCalledWith( - 'Download artifact has finished successfully' - ) - - expect(core.info).toHaveBeenCalledWith( - 'Total of 0 artifact(s) downloaded' - ) + test('throws error when repository format is invalid', async () => { + mockInputs({ + [Inputs.GitHubToken]: 'some-token', + [Inputs.Repository]: 'invalid-format' // Missing the owner/repo format }) - test('filters artifacts by pattern', async () => { - const mockArtifacts = [ - { id: 123, name: 'test-artifact', size: 1024, digest: 'abc123' }, - { id: 456, name: 'prod-artifact', size: 2048, digest: 'def456' } - ] - - jest.spyOn(artifact, 'listArtifacts').mockImplementation(() => - Promise.resolve({ artifacts: mockArtifacts }) - ) - - mockInputs({ - [Inputs.Name]: '', - [Inputs.Pattern]: 'test-*' - }) - - await run() - - expect(artifact.downloadArtifact).toHaveBeenCalledTimes(1) - expect(artifact.downloadArtifact).toHaveBeenCalledWith( - 123, - expect.anything() - ) - }) + await expect(run()).rejects.toThrow( + "Invalid repository: 'invalid-format'. Must be in format owner/repo" + ) + }) - test('uses token and repository information when provided', async () => { - const token = 'ghp_testtoken123' - - mockInputs({ - [Inputs.Name]: '', - [Inputs.GitHubToken]: token, - [Inputs.Repository]: 'myorg/myrepo', - [Inputs.RunID]: '789' - }) - - jest.spyOn(artifact, 'listArtifacts').mockImplementation(() => - Promise.resolve({ artifacts: [] }) - ) - - await run() - - expect(artifact.listArtifacts).toHaveBeenCalledWith( - expect.objectContaining({ - findBy: { - token, - workflowRunId: 789, - repositoryName: 'myrepo', - repositoryOwner: 'myorg' - } - }) - ) - }) + test('warns when digest validation fails', async () => { + const mockArtifact = { + id: 123, + name: 'corrupted-artifact', + size: 1024, + digest: 'abc123' + } - test('throws error when repository format is invalid', async () => { - mockInputs({ - [Inputs.GitHubToken]: 'some-token', - [Inputs.Repository]: 'invalid-format' // Missing the owner/repo format - }) - - await expect(run()).rejects.toThrow( - "Invalid repository: 'invalid-format'. Must be in format owner/repo" - ) - }) - - test('warns when digest validation fails', async () => { - const mockArtifact = { - id: 123, - name: 'corrupted-artifact', - size: 1024, - digest: 'abc123' - } - - jest.spyOn(artifact, 'getArtifact').mockImplementation(() => - Promise.resolve({ artifact: mockArtifact }) - ) - - jest.spyOn(artifact, 'downloadArtifact').mockImplementation(() => - Promise.resolve({ digestMismatch: true }) - ) - - await run() - - expect(core.warning).toHaveBeenCalledWith( - expect.stringContaining('digest validation failed') - ) - }) - }) \ No newline at end of file + jest + .spyOn(artifact, 'getArtifact') + .mockImplementation(() => Promise.resolve({artifact: mockArtifact})) + + jest + .spyOn(artifact, 'downloadArtifact') + .mockImplementation(() => Promise.resolve({digestMismatch: true})) + + await run() + + expect(core.warning).toHaveBeenCalledWith( + expect.stringContaining('digest validation failed') + ) + }) +})