upload-artifact/__tests__/merge.test.ts

176 lines
4.1 KiB
TypeScript

import * as core from '@actions/core'
import artifact from '@actions/artifact'
import {run} from '../src/merge/merge-artifacts'
import {Inputs} from '../src/merge/constants'
import * as search from '../src/shared/search'
const fixtures = {
artifactName: 'my-merged-artifact',
tmpDirectory: '/tmp/merge-artifact',
filesToUpload: [
'/some/artifact/path/file-a.txt',
'/some/artifact/path/file-b.txt',
'/some/artifact/path/file-c.txt'
],
artifacts: [
{
name: 'my-artifact-a',
id: 1,
size: 100,
createdAt: new Date('2024-01-01T00:00:00Z')
},
{
name: 'my-artifact-b',
id: 2,
size: 100,
createdAt: new Date('2024-01-01T00:00:00Z')
},
{
name: 'my-artifact-c',
id: 3,
size: 100,
createdAt: new Date('2024-01-01T00:00:00Z')
}
]
}
jest.mock('@actions/github', () => ({
context: {
repo: {
owner: 'actions',
repo: 'toolkit'
},
runId: 123,
serverUrl: 'https://github.com'
}
}))
jest.mock('@actions/core')
jest.mock('fs/promises', () => ({
mkdtemp: jest.fn().mockResolvedValue('/tmp/merge-artifact'),
rm: jest.fn().mockResolvedValue(undefined)
}))
/* eslint-disable no-unused-vars */
const mockInputs = (overrides?: Partial<{[K in Inputs]?: any}>) => {
const inputs = {
[Inputs.Name]: 'my-merged-artifact',
[Inputs.Pattern]: '*',
[Inputs.SeparateDirectories]: false,
[Inputs.RetentionDays]: 0,
[Inputs.CompressionLevel]: 6,
[Inputs.DeleteMerged]: false,
...overrides
}
;(core.getInput as jest.Mock).mockImplementation((name: string) => {
return inputs[name]
})
;(core.getBooleanInput as jest.Mock).mockImplementation((name: string) => {
return inputs[name]
})
return inputs
}
describe('merge', () => {
beforeEach(async () => {
mockInputs()
jest
.spyOn(artifact, 'listArtifacts')
.mockResolvedValue({artifacts: fixtures.artifacts})
jest.spyOn(artifact, 'downloadArtifact').mockResolvedValue({
downloadPath: fixtures.tmpDirectory
})
jest.spyOn(search, 'findFilesToUpload').mockResolvedValue({
filesToUpload: fixtures.filesToUpload,
rootDirectory: fixtures.tmpDirectory
})
jest.spyOn(artifact, 'uploadArtifact').mockResolvedValue({
size: 123,
id: 1337
})
jest
.spyOn(artifact, 'deleteArtifact')
.mockImplementation(async artifactName => {
const artifact = fixtures.artifacts.find(a => a.name === artifactName)
if (!artifact) throw new Error(`Artifact ${artifactName} not found`)
return {id: artifact.id}
})
})
it('merges artifacts', async () => {
await run()
for (const a of fixtures.artifacts) {
expect(artifact.downloadArtifact).toHaveBeenCalledWith(a.id, {
path: fixtures.tmpDirectory
})
}
expect(artifact.uploadArtifact).toHaveBeenCalledWith(
fixtures.artifactName,
fixtures.filesToUpload,
fixtures.tmpDirectory,
{compressionLevel: 6}
)
})
it('fails if no artifacts found', async () => {
mockInputs({[Inputs.Pattern]: 'this-does-not-match'})
expect(run()).rejects.toThrow()
expect(artifact.uploadArtifact).not.toBeCalled()
expect(artifact.downloadArtifact).not.toBeCalled()
})
it('supports custom compression level', async () => {
mockInputs({
[Inputs.CompressionLevel]: 2
})
await run()
expect(artifact.uploadArtifact).toHaveBeenCalledWith(
fixtures.artifactName,
fixtures.filesToUpload,
fixtures.tmpDirectory,
{compressionLevel: 2}
)
})
it('supports custom retention days', async () => {
mockInputs({
[Inputs.RetentionDays]: 7
})
await run()
expect(artifact.uploadArtifact).toHaveBeenCalledWith(
fixtures.artifactName,
fixtures.filesToUpload,
fixtures.tmpDirectory,
{retentionDays: 7, compressionLevel: 6}
)
})
it('supports deleting artifacts after merge', async () => {
mockInputs({
[Inputs.DeleteMerged]: true
})
await run()
for (const a of fixtures.artifacts) {
expect(artifact.deleteArtifact).toHaveBeenCalledWith(a.name)
}
})
})