1
0
Fork 0

some test updates

pull/1591/head
Rob Herley 2023-12-01 00:31:27 +00:00 committed by GitHub
parent e9d6649a14
commit 22b7aeb707
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 237 additions and 237 deletions

View File

@ -2,18 +2,14 @@ import * as http from 'http'
import * as net from 'net' import * as net from 'net'
import {HttpClient} from '@actions/http-client' import {HttpClient} from '@actions/http-client'
import * as config from '../src/internal/shared/config' import * as config from '../src/internal/shared/config'
import {createArtifactTwirpClient} from '../src/internal/shared/artifact-twirp-client' import {internalArtifactTwirpClient} from '../src/internal/shared/artifact-twirp-client'
import * as core from '@actions/core' import {noopLogs} from './common.test'
jest.mock('@actions/http-client') jest.mock('@actions/http-client')
describe('artifact-http-client', () => { describe('artifact-http-client', () => {
beforeAll(() => { beforeAll(() => {
// mock all output so that there is less noise when running tests noopLogs()
jest.spyOn(console, 'log').mockImplementation(() => {})
jest.spyOn(core, 'debug').mockImplementation(() => {})
jest.spyOn(core, 'info').mockImplementation(() => {})
jest.spyOn(core, 'warning').mockImplementation(() => {})
jest jest
.spyOn(config, 'getResultsServiceUrl') .spyOn(config, 'getResultsServiceUrl')
.mockReturnValue('http://localhost:8080') .mockReturnValue('http://localhost:8080')
@ -25,7 +21,7 @@ describe('artifact-http-client', () => {
}) })
it('should successfully create a client', () => { it('should successfully create a client', () => {
const client = createArtifactTwirpClient('upload') const client = internalArtifactTwirpClient()
expect(client).toBeDefined() expect(client).toBeDefined()
}) })
@ -50,7 +46,7 @@ describe('artifact-http-client', () => {
} }
}) })
const client = createArtifactTwirpClient('upload') const client = internalArtifactTwirpClient()
const artifact = await client.CreateArtifact({ const artifact = await client.CreateArtifact({
workflowRunBackendId: '1234', workflowRunBackendId: '1234',
workflowJobRunBackendId: '5678', workflowJobRunBackendId: '5678',
@ -98,12 +94,11 @@ describe('artifact-http-client', () => {
} }
}) })
const client = createArtifactTwirpClient( const client = internalArtifactTwirpClient({
'upload', maxAttempts: 5,
5, // retry 5 times retryIntervalMs: 1,
1, // wait 1 ms retryMultiplier: 1.5
1.5 // backoff factor })
)
const artifact = await client.CreateArtifact({ const artifact = await client.CreateArtifact({
workflowRunBackendId: '1234', workflowRunBackendId: '1234',
workflowJobRunBackendId: '5678', workflowJobRunBackendId: '5678',
@ -138,12 +133,11 @@ describe('artifact-http-client', () => {
post: mockPost post: mockPost
} }
}) })
const client = createArtifactTwirpClient( const client = internalArtifactTwirpClient({
'upload', maxAttempts: 5,
5, // retry 5 times retryIntervalMs: 1,
1, // wait 1 ms retryMultiplier: 1.5
1.5 // backoff factor })
)
await expect(async () => { await expect(async () => {
await client.CreateArtifact({ await client.CreateArtifact({
workflowRunBackendId: '1234', workflowRunBackendId: '1234',
@ -178,12 +172,11 @@ describe('artifact-http-client', () => {
post: mockPost post: mockPost
} }
}) })
const client = createArtifactTwirpClient( const client = internalArtifactTwirpClient({
'upload', maxAttempts: 5,
5, // retry 5 times retryIntervalMs: 1,
1, // wait 1 ms retryMultiplier: 1.5
1.5 // backoff factor })
)
await expect(async () => { await expect(async () => {
await client.CreateArtifact({ await client.CreateArtifact({
workflowRunBackendId: '1234', workflowRunBackendId: '1234',

View File

@ -0,0 +1,9 @@
import * as core from '@actions/core'
// noopLogs mocks the console.log and core.* functions to prevent output in the console while testing
export const noopLogs = (): void => {
// jest.spyOn(console, 'log').mockImplementation(() => {})
jest.spyOn(core, 'debug').mockImplementation(() => {})
jest.spyOn(core, 'info').mockImplementation(() => {})
jest.spyOn(core, 'warning').mockImplementation(() => {})
}

View File

@ -2,14 +2,14 @@ import fs from 'fs'
import * as http from 'http' import * as http from 'http'
import * as net from 'net' import * as net from 'net'
import * as path from 'path' import * as path from 'path'
import * as core from '@actions/core'
import * as github from '@actions/github' import * as github from '@actions/github'
import {HttpClient} from '@actions/http-client' import {HttpClient} from '@actions/http-client'
import type {RestEndpointMethods} from '@octokit/plugin-rest-endpoint-methods/dist-types/generated/method-types' import type {RestEndpointMethods} from '@octokit/plugin-rest-endpoint-methods/dist-types/generated/method-types'
import archiver from 'archiver' import archiver from 'archiver'
import {downloadArtifact} from '../src/internal/download/download-artifact' import {downloadArtifactPublic} from '../src/internal/download/download-artifact'
import {getUserAgentString} from '../src/internal/shared/user-agent' import {getUserAgentString} from '../src/internal/shared/user-agent'
import {noopLogs} from './common.test'
type MockedDownloadArtifact = jest.MockedFunction< type MockedDownloadArtifact = jest.MockedFunction<
RestEndpointMethods['actions']['downloadArtifact'] RestEndpointMethods['actions']['downloadArtifact']
@ -74,206 +74,214 @@ const expectExtractedArchive = async (dir: string): Promise<void> => {
} }
} }
const setup = async (): Promise<void> => {
noopLogs()
await fs.promises.mkdir(testDir, {recursive: true})
await createTestArchive()
process.env['GITHUB_WORKSPACE'] = fixtures.workspaceDir
}
const cleanup = async (): Promise<void> => {
jest.restoreAllMocks()
await fs.promises.rm(testDir, {recursive: true})
delete process.env['GITHUB_WORKSPACE']
}
describe('download-artifact', () => { describe('download-artifact', () => {
beforeEach(async () => { describe('public', () => {
jest.spyOn(core, 'debug').mockImplementation(() => {}) beforeEach(setup)
jest.spyOn(core, 'info').mockImplementation(() => {}) afterEach(cleanup)
jest.spyOn(core, 'warning').mockImplementation(() => {})
await fs.promises.mkdir(testDir, {recursive: true}) it('should successfully download an artifact to $GITHUB_WORKSPACE', async () => {
await createTestArchive() const downloadArtifactMock = github.getOctokit(fixtures.token).rest
.actions.downloadArtifact as MockedDownloadArtifact
downloadArtifactMock.mockResolvedValueOnce({
headers: {
location: fixtures.blobStorageUrl
},
status: 302,
url: '',
data: Buffer.from('')
})
process.env['GITHUB_WORKSPACE'] = fixtures.workspaceDir const getMock = jest.fn(() => {
}) const message = new http.IncomingMessage(new net.Socket())
message.statusCode = 200
message.push(fs.readFileSync(fixtures.exampleArtifact.path))
return {
message
}
})
const httpClientMock = (HttpClient as jest.Mock).mockImplementation(
() => {
return {
get: getMock
}
}
)
afterEach(async () => { const response = await downloadArtifactPublic(
jest.restoreAllMocks()
await fs.promises.rm(testDir, {recursive: true})
delete process.env['GITHUB_WORKSPACE']
})
it('should successfully download an artifact to $GITHUB_WORKSPACE', async () => {
const downloadArtifactMock = github.getOctokit(fixtures.token).rest.actions
.downloadArtifact as MockedDownloadArtifact
downloadArtifactMock.mockResolvedValueOnce({
headers: {
location: fixtures.blobStorageUrl
},
status: 302,
url: '',
data: Buffer.from('')
})
const getMock = jest.fn(() => {
const message = new http.IncomingMessage(new net.Socket())
message.statusCode = 200
message.push(fs.readFileSync(fixtures.exampleArtifact.path))
return {
message
}
})
const httpClientMock = (HttpClient as jest.Mock).mockImplementation(() => {
return {
get: getMock
}
})
const response = await downloadArtifact(
fixtures.artifactID,
fixtures.repositoryOwner,
fixtures.repositoryName,
fixtures.token
)
expect(downloadArtifactMock).toHaveBeenCalledWith({
owner: fixtures.repositoryOwner,
repo: fixtures.repositoryName,
artifact_id: fixtures.artifactID,
archive_format: 'zip',
request: {
redirect: 'manual'
}
})
expect(httpClientMock).toHaveBeenCalledWith(getUserAgentString())
expect(getMock).toHaveBeenCalledWith(fixtures.blobStorageUrl)
expectExtractedArchive(fixtures.workspaceDir)
expect(response.success).toBe(true)
expect(response.downloadPath).toBe(fixtures.workspaceDir)
})
it('should successfully download an artifact to user defined path', async () => {
const customPath = path.join(testDir, 'custom')
const downloadArtifactMock = github.getOctokit(fixtures.token).rest.actions
.downloadArtifact as MockedDownloadArtifact
downloadArtifactMock.mockResolvedValueOnce({
headers: {
location: fixtures.blobStorageUrl
},
status: 302,
url: '',
data: Buffer.from('')
})
const getMock = jest.fn(() => {
const message = new http.IncomingMessage(new net.Socket())
message.statusCode = 200
message.push(fs.readFileSync(fixtures.exampleArtifact.path))
return {
message
}
})
const httpClientMock = (HttpClient as jest.Mock).mockImplementation(() => {
return {
get: getMock
}
})
const response = await downloadArtifact(
fixtures.artifactID,
fixtures.repositoryOwner,
fixtures.repositoryName,
fixtures.token,
{
path: customPath
}
)
expect(downloadArtifactMock).toHaveBeenCalledWith({
owner: fixtures.repositoryOwner,
repo: fixtures.repositoryName,
artifact_id: fixtures.artifactID,
archive_format: 'zip',
request: {
redirect: 'manual'
}
})
expect(httpClientMock).toHaveBeenCalledWith(getUserAgentString())
expect(getMock).toHaveBeenCalledWith(fixtures.blobStorageUrl)
expectExtractedArchive(customPath)
expect(response.success).toBe(true)
expect(response.downloadPath).toBe(customPath)
})
it('should fail if download artifact API does not respond with location', async () => {
const downloadArtifactMock = github.getOctokit(fixtures.token).rest.actions
.downloadArtifact as MockedDownloadArtifact
downloadArtifactMock.mockResolvedValueOnce({
headers: {},
status: 302,
url: '',
data: Buffer.from('')
})
await expect(
downloadArtifact(
fixtures.artifactID, fixtures.artifactID,
fixtures.repositoryOwner, fixtures.repositoryOwner,
fixtures.repositoryName, fixtures.repositoryName,
fixtures.token fixtures.token
) )
).rejects.toBeInstanceOf(Error)
expect(downloadArtifactMock).toHaveBeenCalledWith({ expect(downloadArtifactMock).toHaveBeenCalledWith({
owner: fixtures.repositoryOwner, owner: fixtures.repositoryOwner,
repo: fixtures.repositoryName, repo: fixtures.repositoryName,
artifact_id: fixtures.artifactID, artifact_id: fixtures.artifactID,
archive_format: 'zip', archive_format: 'zip',
request: { request: {
redirect: 'manual' redirect: 'manual'
} }
}) })
}) expect(httpClientMock).toHaveBeenCalledWith(getUserAgentString())
expect(getMock).toHaveBeenCalledWith(fixtures.blobStorageUrl)
it('should fail if blob storage response is non-200', async () => { expectExtractedArchive(fixtures.workspaceDir)
const downloadArtifactMock = github.getOctokit(fixtures.token).rest.actions
.downloadArtifact as MockedDownloadArtifact expect(response.success).toBe(true)
downloadArtifactMock.mockResolvedValueOnce({ expect(response.downloadPath).toBe(fixtures.workspaceDir)
headers: {
location: fixtures.blobStorageUrl
},
status: 302,
url: '',
data: Buffer.from('')
}) })
const getMock = jest.fn(() => { it('should successfully download an artifact to user defined path', async () => {
const message = new http.IncomingMessage(new net.Socket()) const customPath = path.join(testDir, 'custom')
message.statusCode = 500
message.push('Internal Server Error')
return {
message
}
})
const httpClientMock = (HttpClient as jest.Mock).mockImplementation(() => {
return {
get: getMock
}
})
await expect( const downloadArtifactMock = github.getOctokit(fixtures.token).rest
downloadArtifact( .actions.downloadArtifact as MockedDownloadArtifact
downloadArtifactMock.mockResolvedValueOnce({
headers: {
location: fixtures.blobStorageUrl
},
status: 302,
url: '',
data: Buffer.from('')
})
const getMock = jest.fn(() => {
const message = new http.IncomingMessage(new net.Socket())
message.statusCode = 200
message.push(fs.readFileSync(fixtures.exampleArtifact.path))
return {
message
}
})
const httpClientMock = (HttpClient as jest.Mock).mockImplementation(
() => {
return {
get: getMock
}
}
)
const response = await downloadArtifactPublic(
fixtures.artifactID, fixtures.artifactID,
fixtures.repositoryOwner, fixtures.repositoryOwner,
fixtures.repositoryName, fixtures.repositoryName,
fixtures.token fixtures.token,
{
path: customPath
}
) )
).rejects.toBeInstanceOf(Error)
expect(downloadArtifactMock).toHaveBeenCalledWith({ expect(downloadArtifactMock).toHaveBeenCalledWith({
owner: fixtures.repositoryOwner, owner: fixtures.repositoryOwner,
repo: fixtures.repositoryName, repo: fixtures.repositoryName,
artifact_id: fixtures.artifactID, artifact_id: fixtures.artifactID,
archive_format: 'zip', archive_format: 'zip',
request: { request: {
redirect: 'manual' redirect: 'manual'
} }
})
expect(httpClientMock).toHaveBeenCalledWith(getUserAgentString())
expect(getMock).toHaveBeenCalledWith(fixtures.blobStorageUrl)
expectExtractedArchive(customPath)
expect(response.success).toBe(true)
expect(response.downloadPath).toBe(customPath)
})
it('should fail if download artifact API does not respond with location', async () => {
const downloadArtifactMock = github.getOctokit(fixtures.token).rest
.actions.downloadArtifact as MockedDownloadArtifact
downloadArtifactMock.mockResolvedValueOnce({
headers: {},
status: 302,
url: '',
data: Buffer.from('')
})
await expect(
downloadArtifactPublic(
fixtures.artifactID,
fixtures.repositoryOwner,
fixtures.repositoryName,
fixtures.token
)
).rejects.toBeInstanceOf(Error)
expect(downloadArtifactMock).toHaveBeenCalledWith({
owner: fixtures.repositoryOwner,
repo: fixtures.repositoryName,
artifact_id: fixtures.artifactID,
archive_format: 'zip',
request: {
redirect: 'manual'
}
})
})
it('should fail if blob storage response is non-200', async () => {
const downloadArtifactMock = github.getOctokit(fixtures.token).rest
.actions.downloadArtifact as MockedDownloadArtifact
downloadArtifactMock.mockResolvedValueOnce({
headers: {
location: fixtures.blobStorageUrl
},
status: 302,
url: '',
data: Buffer.from('')
})
const getMock = jest.fn(() => {
const message = new http.IncomingMessage(new net.Socket())
message.statusCode = 500
message.push('Internal Server Error')
return {
message
}
})
const httpClientMock = (HttpClient as jest.Mock).mockImplementation(
() => {
return {
get: getMock
}
}
)
await expect(
downloadArtifactPublic(
fixtures.artifactID,
fixtures.repositoryOwner,
fixtures.repositoryName,
fixtures.token
)
).rejects.toBeInstanceOf(Error)
expect(downloadArtifactMock).toHaveBeenCalledWith({
owner: fixtures.repositoryOwner,
repo: fixtures.repositoryName,
artifact_id: fixtures.artifactID,
archive_format: 'zip',
request: {
redirect: 'manual'
}
})
expect(httpClientMock).toHaveBeenCalledWith(getUserAgentString())
expect(getMock).toHaveBeenCalledWith(fixtures.blobStorageUrl)
}) })
expect(httpClientMock).toHaveBeenCalledWith(getUserAgentString())
expect(getMock).toHaveBeenCalledWith(fixtures.blobStorageUrl)
}) })
}) })

View File

@ -3,15 +3,11 @@ import {
validateFilePath validateFilePath
} from '../src/internal/upload/path-and-artifact-name-validation' } from '../src/internal/upload/path-and-artifact-name-validation'
import * as core from '@actions/core' import {noopLogs} from './common.test'
describe('Path and artifact name validation', () => { describe('Path and artifact name validation', () => {
beforeAll(() => { beforeAll(() => {
// mock all output so that there is less noise when running tests noopLogs()
jest.spyOn(console, 'log').mockImplementation(() => {})
jest.spyOn(core, 'debug').mockImplementation(() => {})
jest.spyOn(core, 'info').mockImplementation(() => {})
jest.spyOn(core, 'warning').mockImplementation(() => {})
}) })
it('Check Artifact Name for any invalid characters', () => { it('Check Artifact Name for any invalid characters', () => {

View File

@ -1,4 +1,3 @@
import * as core from '@actions/core'
import * as uploadZipSpecification from '../src/internal/upload/upload-zip-specification' import * as uploadZipSpecification from '../src/internal/upload/upload-zip-specification'
import * as zip from '../src/internal/upload/zip' import * as zip from '../src/internal/upload/zip'
import * as util from '../src/internal/shared/util' import * as util from '../src/internal/shared/util'
@ -7,14 +6,11 @@ import * as config from '../src/internal/shared/config'
import {Timestamp, ArtifactServiceClientJSON} from '../src/generated' import {Timestamp, ArtifactServiceClientJSON} from '../src/generated'
import * as blobUpload from '../src/internal/upload/blob-upload' import * as blobUpload from '../src/internal/upload/blob-upload'
import {uploadArtifact} from '../src/internal/upload/upload-artifact' import {uploadArtifact} from '../src/internal/upload/upload-artifact'
import {noopLogs} from './common.test'
describe('upload-artifact', () => { describe('upload-artifact', () => {
beforeEach(() => { beforeEach(() => {
// mock all output so that there is less noise when running tests noopLogs()
jest.spyOn(console, 'log').mockImplementation(() => {})
jest.spyOn(core, 'debug').mockImplementation(() => {})
jest.spyOn(core, 'info').mockImplementation(() => {})
jest.spyOn(core, 'warning').mockImplementation(() => {})
}) })
afterEach(() => { afterEach(() => {

View File

@ -1,11 +1,11 @@
import * as io from '../../io/src/io' import * as io from '../../io/src/io'
import * as path from 'path' import * as path from 'path'
import {promises as fs} from 'fs' import {promises as fs} from 'fs'
import * as core from '@actions/core'
import { import {
getUploadZipSpecification, getUploadZipSpecification,
validateRootDirectory validateRootDirectory
} from '../src/internal/upload/upload-zip-specification' } from '../src/internal/upload/upload-zip-specification'
import {noopLogs} from './common.test'
const root = path.join(__dirname, '_temp', 'upload-specification') const root = path.join(__dirname, '_temp', 'upload-specification')
const goodItem1Path = path.join( const goodItem1Path = path.join(
@ -51,11 +51,7 @@ const artifactFilesToUpload = [
describe('Search', () => { describe('Search', () => {
beforeAll(async () => { beforeAll(async () => {
// mock all output so that there is less noise when running tests noopLogs()
jest.spyOn(console, 'log').mockImplementation(() => {})
jest.spyOn(core, 'debug').mockImplementation(() => {})
jest.spyOn(core, 'info').mockImplementation(() => {})
jest.spyOn(core, 'warning').mockImplementation(() => {})
// clear temp directory // clear temp directory
await io.rmRF(root) await io.rmRF(root)

View File

@ -1,13 +1,12 @@
import * as config from '../src/internal/shared/config' import * as config from '../src/internal/shared/config'
import * as util from '../src/internal/shared/util' import * as util from '../src/internal/shared/util'
export const testRuntimeToken =
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwic2NwIjoiQWN0aW9ucy5FeGFtcGxlIEFjdGlvbnMuQW5vdGhlckV4YW1wbGU6dGVzdCBBY3Rpb25zLlJlc3VsdHM6Y2U3ZjU0YzctNjFjNy00YWFlLTg4N2YtMzBkYTQ3NWY1ZjFhOmNhMzk1MDg1LTA0MGEtNTI2Yi0yY2U4LWJkYzg1ZjY5Mjc3NCIsImlhdCI6MTUxNjIzOTAyMn0.XYnI_wHPBlUi1mqYveJnnkJhp4dlFjqxzRmISPsqfw8'
describe('get-backend-ids-from-token', () => { describe('get-backend-ids-from-token', () => {
it('should return backend ids when the token is valid', () => { it('should return backend ids when the token is valid', () => {
jest jest.spyOn(config, 'getRuntimeToken').mockReturnValue(testRuntimeToken)
.spyOn(config, 'getRuntimeToken')
.mockReturnValue(
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwic2NwIjoiQWN0aW9ucy5FeGFtcGxlIEFjdGlvbnMuQW5vdGhlckV4YW1wbGU6dGVzdCBBY3Rpb25zLlJlc3VsdHM6Y2U3ZjU0YzctNjFjNy00YWFlLTg4N2YtMzBkYTQ3NWY1ZjFhOmNhMzk1MDg1LTA0MGEtNTI2Yi0yY2U4LWJkYzg1ZjY5Mjc3NCIsImlhdCI6MTUxNjIzOTAyMn0.XYnI_wHPBlUi1mqYveJnnkJhp4dlFjqxzRmISPsqfw8'
)
const backendIds = util.getBackendIdsFromToken() const backendIds = util.getBackendIdsFromToken()
expect(backendIds.workflowRunBackendId).toBe( expect(backendIds.workflowRunBackendId).toBe(

View File

@ -30,7 +30,7 @@
}, },
"scripts": { "scripts": {
"audit-moderate": "npm install && npm audit --json --audit-level=moderate > audit.json", "audit-moderate": "npm install && npm audit --json --audit-level=moderate > audit.json",
"test": "echo \"Error: run tests from root\" && exit 1", "test": "cd ../../ && npm run test ./packages/artifact",
"bootstrap": "cd ../../ && npm run bootstrap", "bootstrap": "cd ../../ && npm run bootstrap",
"tsc-run": "tsc", "tsc-run": "tsc",
"tsc": "npm run bootstrap && npm run tsc-run" "tsc": "npm run bootstrap && npm run tsc-run"

View File

@ -10,7 +10,10 @@ import {
import {getUserAgentString} from '../shared/user-agent' import {getUserAgentString} from '../shared/user-agent'
import {getGitHubWorkspaceDir} from '../shared/config' import {getGitHubWorkspaceDir} from '../shared/config'
import {internalArtifactTwirpClient} from '../shared/artifact-twirp-client' import {internalArtifactTwirpClient} from '../shared/artifact-twirp-client'
import {GetSignedArtifactURLRequest, ListArtifactsRequest} from 'src/generated' import {
GetSignedArtifactURLRequest,
ListArtifactsRequest
} from '../../generated'
import {getBackendIdsFromToken} from '../shared/util' import {getBackendIdsFromToken} from '../shared/util'
const scrubQueryParameters = (url: string): string => { const scrubQueryParameters = (url: string): string => {

View File

@ -160,13 +160,13 @@ class ArtifactHttpClient implements Rpc {
export function internalArtifactTwirpClient(options?: { export function internalArtifactTwirpClient(options?: {
maxAttempts?: number maxAttempts?: number
baseRetryIntervalMilliseconds?: number retryIntervalMs?: number
retryMultiplier?: number retryMultiplier?: number
}): ArtifactServiceClientJSON { }): ArtifactServiceClientJSON {
const client = new ArtifactHttpClient( const client = new ArtifactHttpClient(
getUserAgentString(), getUserAgentString(),
options?.maxAttempts, options?.maxAttempts,
options?.baseRetryIntervalMilliseconds, options?.retryIntervalMs,
options?.retryMultiplier options?.retryMultiplier
) )
return new ArtifactServiceClientJSON(client) return new ArtifactServiceClientJSON(client)