build: inline external Github Actions to unblock CI (#12241)

* build: inline cached-dependencies to unblock CI

* Run E2E on pull_request on;y

* Inline all external actions

* Checkout needed for internal actions

Also fixes pre-commit

* Add missing files
This commit is contained in:
Jesse Yang
2021-01-04 04:16:07 -08:00
committed by GitHub
parent 7cc0de1694
commit a3bbbf8ea3
173 changed files with 48871 additions and 78 deletions

View File

@@ -0,0 +1,240 @@
import {Env, p, getTestFiles, getTestEvents} from './mocks/env'
let env: Env
describe('Testing FilesHelper.ts...', () => {
describe('...with push event...', () => {
beforeAll(() => {
env = new Env({}, {githubToken: 'TestToken'}, 'push')
})
afterEach(() => {
process.env = {...env.envStart}
jest.resetModules()
env = new Env({}, {}, 'push')
})
/**
* @function sortChangedFiles
*/
describe('...with function sortChangedFiles...', () => {
it.each([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])(
'...correctly sorts GithubFile array into ChangedFiles object %i/10 times',
() => {
const {files, stats} = getTestFiles()
const changedFiles = require('../FilesHelper').sortChangedFiles(files)
const coreDebug = require('@actions/core').debug
expect(coreDebug).toHaveBeenCalledWith(
expect.stringContaining(JSON.stringify(files, null, 2))
)
const retStats = {
files: 0,
added: 0,
removed: 0,
modified: 0,
renamed: 0
} as {
[key: string]: number
}
Object.keys(changedFiles).forEach(key => {
retStats[key] = changedFiles[key].length
})
expect(retStats).toStrictEqual(stats)
}
)
it.each([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])(
'...correctly sorts GithubFile array into ChangedFiles object without filenames %i/10 times',
() => {
const {files, stats} = getTestFiles()
const changedFiles = require('../FilesHelper').sortChangedFiles(files)
const coreDebug = require('@actions/core').debug
expect(coreDebug).toHaveBeenCalledWith(
expect.stringContaining(JSON.stringify(files, null, 2))
)
const retStats = {
files: 0,
added: 0,
removed: 0,
modified: 0,
renamed: 0
} as {
[key: string]: number
}
Object.keys(changedFiles).forEach(key => {
retStats[key] = changedFiles[key].length
})
expect(retStats).toStrictEqual(stats)
}
)
it('...throws an error', () => {
expect(() =>
require('../FilesHelper').sortChangedFiles({
filename: '/test/file.txt',
status: 'noexist'
})
).toThrowError(
JSON.stringify(
{
error: '500/TypeError',
from: 'sortChangedFiles',
message: 'There was an issue sorting files changed.',
payload: JSON.stringify({})
},
null,
2
)
)
})
})
/**
* @function getFormatExt
*/
describe('...with function getFormatExt...', () => {
it.each(getTestEvents(p.getFormatExtInputs, 'push'))(
'...sets %s ext for input "%s" should be "%s"',
(inputName, input, expected) => {
const ext = require('../FilesHelper').getFormatExt(input)
expect(ext).toBe(expected)
}
)
})
/**
* @function formatChangedFiles
*/
describe('...with function formatChangedFiles...', () => {
it.each(
getTestEvents(
p.changedFilesInput('push', ['/test/file', '/test/file2']),
'push'
)
)('... with %o', (format, input, expected) => {
const ext = require('../FilesHelper').formatChangedFiles(format, input)
expect(ext).toBe(expected)
if (format === 'json') expect(ext).toBe(`["${input[0]}","${input[1]}"]`)
else expect(ext).toBe(`${input[0]}${format}${input[1]}`)
})
it.each(getTestEvents(p.changedFilesInput('push'), 'push'))(
'...formats a big list %s',
(inputName, input, expected) => {
const ext = require('../FilesHelper').formatChangedFiles(
inputName,
input
)
expect(ext).toBe(expected)
}
)
})
/**
* @function writeFiles
*/
describe('...with function writeFiles...', () => {
it.each(getTestEvents(p.changedFilesInput('push'), 'push'))(
'...writesFiles %s',
(inputName, input, expected) => {
const coreDebug = require('@actions/core').debug
const fsWriteFilesSync = require('fs').writeFileSync
const format = require('../FilesHelper').getFormatExt(inputName)
require('../FilesHelper').writeFiles(inputName, 'testKey', input)
expect(coreDebug).toHaveBeenCalledWith(
expect.stringContaining(JSON.stringify(input, null, 2))
)
expect(fsWriteFilesSync).toHaveBeenCalledWith(
`${process.env.HOME}/files_testKey${format}`,
expected,
'utf-8'
)
}
)
it.each(getTestEvents(p.changedFilesInput('push'), 'push'))(
'...writesFiles %s with files key',
(inputName, input, expected) => {
const coreDebug = require('@actions/core').debug
const fsWriteFilesSync = require('fs').writeFileSync
const format = require('../FilesHelper').getFormatExt(inputName)
require('../FilesHelper').writeFiles(inputName, 'files', input)
expect(coreDebug).toHaveBeenCalledWith(
expect.stringContaining(JSON.stringify(input, null, 2))
)
expect(fsWriteFilesSync).toHaveBeenCalledWith(
`${process.env.HOME}/files${format}`,
expected,
'utf-8'
)
}
)
it('...throws error', () => {
const coreDebug = require('@actions/core').debug
expect(() =>
require('../FilesHelper').writeFiles('error', 'testKey', 'json')
).toThrowError(
new Error(
JSON.stringify(
{
error: '500/TypeError',
from: 'writeFiles',
message: 'There was an issue writing output files.',
payload: JSON.stringify({})
},
null,
2
)
)
)
expect(coreDebug).toHaveBeenCalledWith(
expect.stringContaining(
`Writing output file ${process.env.HOME}/files_testKey.txt with error and files "json"`
)
)
})
})
/**
* @function writeOutput
*/
describe('...with function writeOutput...', () => {
it.each(getTestEvents(p.changedFilesInput('push'), 'push'))(
'...writeOutput %o',
(inputName, input, expected) => {
const coreDebug = require('@actions/core').debug
const coreSetOutput = require('@actions/core').setOutput
require('../FilesHelper').writeOutput(inputName, 'testKey', input)
expect(coreDebug).toHaveBeenCalledWith(
expect.stringContaining(JSON.stringify(input, null, 2))
)
expect(coreSetOutput).toHaveBeenCalledWith(`files_testKey`, expected)
}
)
it.each(getTestEvents(p.changedFilesInput('push'), 'push'))(
'...writeOutput %o with files key',
(inputName, input, expected) => {
const coreDebug = require('@actions/core').debug
const coreSetOutput = require('@actions/core').setOutput
require('../FilesHelper').writeOutput(inputName, 'files', input)
expect(coreDebug).toHaveBeenCalledWith(
expect.stringContaining(JSON.stringify(input, null, 2))
)
expect(coreSetOutput).toHaveBeenCalledWith(`files`, expected)
}
)
it('...throws error', () => {
const coreDebug = require('@actions/core').debug
expect(() =>
require('../FilesHelper').writeOutput('error', 'testKey', 'json')
).toThrowError(
new Error(
JSON.stringify(
{
error: '500/TypeError',
from: 'writeOutput',
message: 'There was an issue setting action outputs.',
payload: JSON.stringify({})
},
null,
2
)
)
)
expect(coreDebug).toHaveBeenCalledWith(
'Writing output files_testKey with error and files "json"'
)
})
})
})
})

View File

@@ -0,0 +1,241 @@
import {Env, p, getTestEvents} from './mocks/env'
let env: Env
describe('Testing GithubHelper.ts...', () => {
describe.each(p.testEvents)('...with %s event...', event => {
beforeAll(() => {
env = new Env({}, {githubToken: 'TestToken'}, event)
})
afterEach(() => {
process.env = {...env.envStart}
jest.resetModules()
env = new Env({}, {}, event)
})
/**
* @function initClient
*/
describe('...with function initClientTests...', () => {
it.each(getTestEvents(p.initClientTestInputs, event))(
'...%s',
async (title, input, expected) => {
process.env = {...env.envStart}
env = new Env({}, {}, event)
let gh
if (title.includes('without a token'))
expect(() =>
require('../GithubHelper').initClient(input)
).toThrowError(
new Error(
JSON.stringify(
{
error: '500/Error',
from: 'initClient',
message:
'There was an error creating github client. Please check your token.',
payload: {}
},
null,
2
)
)
)
else {
gh = require('../GithubHelper').initClient(input)
const {GitHub} = require('@actions/github')
expect(GitHub).toHaveBeenCalledTimes(1)
expect(GitHub).toHaveBeenCalledWith(expected)
expect(gh).toEqual(env.octokitMock)
}
}
)
})
/**
* @function getChangedPRFiles
*/
describe('...with function getChangedPRFiles...', () => {
it.each(getTestEvents(p.getChangedPRFilesTestInputs, event))(
'...%s',
async (title, input, expected) => {
if (title.includes('throws an error')) {
expect.assertions(1)
await expect(
require('../GithubHelper').getChangedPRFiles(
env.octokitMock,
input.repo,
input.owner,
input.pullNumber
)
).rejects.toThrowError(new Error(JSON.stringify(expected, null, 2)))
} else {
let files: any[] = []
files = await require('../GithubHelper').getChangedPRFiles(
env.octokitMock,
input.repo,
input.owner,
input.pullNumber
)
expect(files).toStrictEqual(expected)
expect(files.length).toBe(7)
}
}
)
it('...throws errows', async () => {
await expect(
require('../GithubHelper').getChangedPRFiles(
env.octokitMock,
'trilom/file-changes-action',
'error',
'error'
)
).rejects.toThrowError(
new Error(
JSON.stringify(
{
error: '500/Unknown Error:Error',
from: 'getChangedPRFiles',
message:
'There was an error getting change files for repo:trilom/file-changes-action owner:error pr:error',
payload: JSON.stringify({name: 'HttpError', status: '500'})
},
null,
2
)
)
)
await expect(
require('../GithubHelper').getChangedPRFiles(
env.octokitMock,
'trilom/file-changes-action',
'unknown',
'unknown'
)
).rejects.toThrowError(
new Error(
JSON.stringify(
{
error: '500/Unknown Error:',
from: 'getChangedPRFiles',
message:
'There was an error getting change files for repo:trilom/file-changes-action owner:unknown pr:unknown',
payload: ''
},
null,
2
)
)
)
})
})
/**
* @function getChangedPushFiles
*/
describe('...with function getChangedPushFiles...', () => {
it.each(getTestEvents(p.getChangedPushFilesTestInputs, event))(
'...%s',
async (title, input, expected) => {
if (title.includes('throws an error')) {
expect.assertions(1)
await expect(
require('../GithubHelper').getChangedPushFiles(
env.octokitMock,
input.repo,
input.owner,
input.before,
input.after
)
).rejects.toThrowError(new Error(JSON.stringify(expected, null, 2)))
} else {
let files: any[] = []
files = await require('../GithubHelper').getChangedPushFiles(
env.octokitMock,
input.repo,
input.owner,
input.before,
input.after
)
expect(files).toStrictEqual(expected)
expect(files.length).toBe(7)
}
}
)
it('...throws errows', async () => {
await expect(
require('../GithubHelper').getChangedPushFiles(
env.octokitMock,
'trilom/file-changes-action',
'error',
'error',
'error'
)
).rejects.toThrowError(
new Error(
JSON.stringify(
{
error: '500/Unknown Error:Error',
from: 'getChangedPushFiles',
message:
'There was an error getting change files for repo:trilom/file-changes-action owner:error base:error head:error',
payload: JSON.stringify({name: 'HttpError', status: '500'})
},
null,
2
)
)
)
await expect(
require('../GithubHelper').getChangedPushFiles(
env.octokitMock,
'trilom/file-changes-action',
'unknown',
'unknown',
'unknown'
)
).rejects.toThrowError(
new Error(
JSON.stringify(
{
error: '500/Unknown Error:',
from: 'getChangedPushFiles',
message:
'There was an error getting change files for repo:trilom/file-changes-action owner:unknown base:unknown head:unknown',
payload: ''
},
null,
2
)
)
)
})
})
/**
* @function getChangedFiles
*/
describe('...with function getChangedFiles...', () => {
it.each(getTestEvents(p.getChangedFilesTestInputs, event))(
'...%s',
async (title, input, expected) => {
if (title.includes('throws an error')) {
expect.assertions(1)
await expect(
require('../GithubHelper').getChangedFiles(
env.octokitMock,
input.repo,
{...input}
)
).rejects.toThrowError(new Error(JSON.stringify(expected, null, 2)))
} else {
let files: any[] = []
files = await require('../GithubHelper').getChangedFiles(
env.octokitMock,
input.repo,
{...input}
)
expect(files).toStrictEqual(expected)
expect(files.length).toBe(7)
}
}
)
})
})
})

View File

@@ -0,0 +1,222 @@
import {Env, eventName, getTestEvents, p} from './mocks/env'
let env: Env
describe('Testing InputHelper.ts...', () => {
describe.each(p.testEvents)('...with %s event...', event => {
beforeAll(() => {
env = new Env({}, {githubToken: 'TestToken'}, event)
})
afterEach(() => {
process.env = {...env.envStart}
jest.resetModules()
env = new Env({}, {}, event)
})
/**
* @function getInputs
*/
describe('...with function getInputs...', () => {
it('...sets correct default input parameters.', () => {
const {payload, issue, eventName: contextEventName} = env.context
const {
prNumber,
pushAfter,
pushBefore,
githubToken,
githubRepo,
output,
fileOutput,
event: inputEventName
} = require('../InputHelper').getInputs()
const {getInput} = require('@actions/core')
if (event.includes('push')) {
expect(prNumber).toBe(NaN)
expect(pushAfter).toBe(payload.after)
expect(pushBefore).toBe(payload.before)
}
if (event.includes('pull_request') || event.includes('issue_comment')) {
expect(prNumber).toBe(issue.number)
if (event === 'pull_request_synchronize') {
expect(pushAfter).toBe(payload.after)
expect(pushBefore).toBe(payload.before)
} else {
expect(pushAfter).toBeFalsy()
expect(pushBefore).toBeFalsy()
}
}
expect(githubToken).toBe(process.env.INPUT_GITHUBTOKEN)
expect(githubRepo).toBe(process.env.GITHUB_REPOSITORY)
expect(output).toBe(' ')
expect(fileOutput).toBe(' ')
expect(inputEventName).toBe(contextEventName)
expect(getInput).toHaveBeenCalled()
})
it('...throws error with no token (undefined) process.env["GITHUB_TOKEN"] or (undefined) input githubToken', () => {
delete process.env.GITHUB_TOKEN
delete process.env.INPUT_GITHUBTOKEN
const {getInput} = require('@actions/core')
expect(() => {
require('../InputHelper').getInputs()
}).toThrowError()
expect(getInput).toHaveBeenCalledTimes(1)
})
it('...throws error with empty string ("") process.env["GITHUB_TOKEN"] or empty string ("") input githubToken', () => {
env.updateInput({githubToken: ''})
process.env.GITHUB_TOKEN = ''
const {getInput} = require('@actions/core')
expect(() => {
require('../InputHelper').getInputs()
}).toThrowError()
expect(getInput).toHaveBeenCalledTimes(1)
})
it.each(getTestEvents(p.inputTestInputs, event))(
'...sets %s input "%s" should be %p',
(inputName, input, expected) => {
env.updateInput({[inputName]: input})
const {payload, issue, eventName: contextEventName} = env.context
const {
prNumber,
pushAfter,
pushBefore,
githubToken,
githubRepo,
output,
fileOutput,
event: inputEventName
} = require('../InputHelper').getInputs()
const {getInput} = require('@actions/core')
if (event.includes('push')) {
expect(prNumber).toBe(inputName === 'prNumber' ? expected : NaN)
expect(pushAfter).toBe(
inputName === 'pushAfter' ? expected : payload.after
)
expect(pushBefore).toBe(
inputName === 'pushBefore' ? expected : payload.before
)
}
if (
event.includes('pull_request') ||
event.includes('issue_comment')
) {
expect(prNumber).toBe(
inputName === 'prNumber' ? expected : issue.number
)
if (event === 'pull_request_synchronize') {
expect(pushAfter).toBe(
inputName === 'pushAfter' ? expected : payload.after
)
expect(pushBefore).toBe(
inputName === 'pushBefore' ? expected : payload.before
)
} else {
expect(pushAfter).toBe(
inputName === 'pushAfter' ? expected : false
)
expect(pushBefore).toBe(
inputName === 'pushBefore' ? expected : false
)
}
}
expect(githubToken).toBe(
inputName === 'githubToken' ? expected : 'EnvDefaultToken'
)
expect(githubRepo).toBe(
inputName === 'githubRepo'
? expected
: process.env.GITHUB_REPOSITORY
)
expect(output).toBe(inputName === 'output' ? expected : ' ')
expect(fileOutput).toBe(inputName === 'fileOutput' ? expected : ' ')
expect(inputEventName).toBe(contextEventName)
expect(getInput).toBeCalled()
}
)
})
/**
* @function inferInput
*/
describe('...with function inferInput...', () => {
it.each(getTestEvents(p.inferTestInputs, event))(
'...%s',
(title, input, expected) => {
const {error} = require('@actions/core')
const {warning} = require('@actions/core')
if (title.includes('ERROR with no')) {
expect(() => {
require('../InputHelper').inferInput(
input.before,
input.after,
input.pr
)
}).toThrowError(
new Error(
JSON.stringify(
{
error: '500/inferInput Error',
from: 'inferInput',
message: `Received event from ${eventName(
event
)}, but received no inputs. {event_name:${eventName(
event
)}, pr: NaN, before:, after:}`,
payload: ''
},
null,
2
)
)
)
} else if (title.includes('ERROR with single')) {
expect(() => {
require('../InputHelper').inferInput(
input.before,
input.after,
input.pr
)
}).toThrowError(
new Error(
JSON.stringify(
{
error: '500/inferInput Error',
from: 'inferInput',
message: `Received event from ${eventName(
event
)}, but only received a before(${input.before}) or after(${
input.after
}).\n I need both of these if you want to use a Push event.`,
payload: ''
},
null,
2
)
)
)
} else {
const data = require('../InputHelper').inferInput(
input.before,
input.after,
input.pr
)
Object.keys(data).forEach(key =>
expect(data[key]).toBe(expected[key])
)
expect(error).not.toHaveBeenCalled()
}
if (title.includes('WARN weird'))
expect(warning).toHaveBeenCalledWith(
expect.stringContaining(
`received a before(${input.before}) or after(${input.after}) value.`
)
)
if (title.includes('WARN all'))
expect(warning).toHaveBeenCalledWith(
expect.stringContaining(
`but received a before(${input.before}), after(${input.after}), and PR(${input.pr}).`
)
)
else expect(error).not.toHaveBeenCalled()
}
)
})
})
})

View File

@@ -0,0 +1,67 @@
import {Env, p, getTestEvents} from './mocks/env'
let env: Env
describe('Testing UtilsHelper.ts...', () => {
describe('...with push event...', () => {
beforeAll(() => {
env = new Env({}, {githubToken: 'TestToken'}, 'push')
})
afterEach(() => {
process.env = {...env.envStart}
jest.resetModules()
env = new Env({}, {}, 'push')
})
/**
* @function getErrorString
*/
describe('...with function getErrorString...', () => {
it('...can throw an error', () => {
const error = require('../UtilsHelper').getErrorString()
expect(JSON.stringify(JSON.parse(error))).toBe(
JSON.stringify({error: '500/undefined', payload: ''})
)
})
it('...can throw an error for my error', () => {
const {setFailed, error: coreError} = require('@actions/core')
const obj = {a: {}}
obj.a = {b: obj}
expect(() =>
require('../UtilsHelper').getErrorString(
'test',
200,
'test',
'test',
obj
)
).toThrowError(
JSON.stringify({
name: '500/undefined',
message: 'Error throwing error.'
})
)
// expect(JSON.stringify(JSON.parse(error))).toBe(JSON.stringify({error:'500/undefined', payload:''}))
expect(setFailed).toBeCalledWith(
expect.stringContaining('Error throwing error.')
)
expect(coreError).toBeCalledWith(
expect.stringContaining('Error throwing error.')
)
})
})
/**
* @function errorMessage
*/
describe('...with function errorMessage...', () => {
it.each(getTestEvents(p.errorMessageInputs, 'push'))(
'...for function %s',
(f, e, expected) => {
const error = require('../UtilsHelper').errorMessage(f, e)
expect(error).toBe(
`${expected}\nException: ${JSON.stringify(e, null, 2)}`
)
}
)
})
})
})

View File

@@ -0,0 +1,129 @@
import {existsSync, mkdirSync, readFileSync, rmdirSync, unlinkSync} from 'fs'
import {resolve as _resolve} from 'path'
import {
eventName as formatEventName,
formatInput,
getTestEvents,
p
} from './mocks/env'
// debugger
const pEnv: {[key: string]: string | undefined} = {...process.env}
let processStdoutMock: jest.SpyInstance
let consoleLogMock: jest.SpyInstance
let output = ''
describe.each(p.testEvents)('Testing main.ts with %s event...', event => {
/**
* @function run
*/
describe.each(getTestEvents(p.mainInputs, event))(
'...function run with %s event inputs non mocked...',
(eventName, eventInput, eventExpected) => {
describe.each(getTestEvents(p.getFormatExtInputs, 'push'))(
'...with output %s...',
(outputName, outputInput, outputExpected) => {
describe.each(getTestEvents(p.getFormatExtInputs, 'push'))(
'...with fileOutput %s...',
(fileOutputName, fileOutputInput, fileOutputExpected) => {
beforeEach(() => {
consoleLogMock = jest
.spyOn(console, 'log')
.mockImplementation((message: string) => {
output += ` ${message}`
})
processStdoutMock = jest
.spyOn(process.stdout, 'write')
.mockImplementation(
(
command: string | Uint8Array,
encoding?: string,
cb?: () => void
) => {
output += ` ${command}`
return false
}
)
mkdirSync(
_resolve(
__dirname,
`outputs/${event}/${eventName}/o_${outputName}f_${fileOutputName}`
),
{recursive: true}
)
process.env = {
HOME: _resolve(
__dirname,
`outputs/${event}/${eventName}/o_${outputName}f_${fileOutputName}`
),
GITHUB_EVENT_NAME: formatEventName(event),
GITHUB_EVENT_PATH: _resolve(
__dirname,
`mocks/env/events/${event}.json`
),
...formatInput({
githubRepo: 'trilom/file-changes-action',
githubToken: process.env.GITHUB_TOKEN || '',
output: outputInput,
fileOutput: fileOutputInput,
...eventInput
})
}
})
afterEach(() => {
process.env = {...pEnv}
output = ''
jest.restoreAllMocks()
})
it('...no-mock', async () => {
await expect(require('../main').run()).resolves.toBe(undefined)
const counts = {
files: 73,
files_added: 52,
files_modified: 13,
files_removed: 8
} as {[key: string]: number}
Object.keys(counts).forEach(async key => {
expect(output).toContain(`::set-output name=${key}`)
expect(
existsSync(
_resolve(
__dirname,
`outputs/${event}/${eventName}/o_${outputName}f_${fileOutputName}/${key}${fileOutputExpected}`
)
)
).toBeTruthy()
if (fileOutputExpected === '.json') {
expect(
JSON.parse(
readFileSync(
_resolve(
__dirname,
`outputs/${event}/${eventName}/o_${outputName}f_${fileOutputName}/${key}${fileOutputExpected}`
),
'utf8'
)
)
).toHaveLength(counts[key])
} else {
expect(
readFileSync(
_resolve(
__dirname,
`outputs/${event}/${eventName}/o_${outputName}f_${fileOutputName}/${key}${fileOutputExpected}`
),
'utf8'
).split(fileOutputInput)
).toHaveLength(counts[key])
}
})
}, 10000)
}
)
}
)
}
)
})

View File

@@ -0,0 +1,89 @@
import {Env, getTestEvents, getTestFiles, p} from './mocks/env'
let env: Env
describe('Testing main.ts...', () => {
describe.each(p.testEvents)('...with %s event...', event => {
/**
* @function run
*/
describe('...with function run...', () => {
describe.each(getTestEvents(p.getFormatExtInputs, 'push'))(
'...with fileOutput %s...',
(fileOutputName, fileOutputInput, fileOutputExpected) => {
describe.each(getTestEvents(p.getFormatExtInputs, 'push'))(
'...with output %o...',
(outputName, outputInput, outputExpected) => {
describe.each(getTestEvents(p.mainInputs, event))(
'...with %s event inputs mocked...',
(eventName, eventInput, eventExpected) => {
beforeEach(() => {
env = new Env(
{},
{
githubRepo: 'trilom/file-changes-action',
githubToken: 'TestToken',
output: outputInput,
fileOutput: fileOutputInput,
...eventInput,
mock: 'true'
},
event
)
})
afterEach(() => {
process.env = env.envStart
jest.resetModules()
jest.unmock('@actions/core')
jest.unmock('@actions/github')
jest.unmock('../InputHelper')
jest.unmock('../FilesHelper')
jest.unmock('../GithubHelper')
})
it('...mocked', async () => {
const githubHelper = require('../GithubHelper')
const filesHelper = require('../FilesHelper')
githubHelper.getChangedFiles = jest.fn(
() => getTestFiles().files
)
filesHelper.writeOutput = jest.fn(() => {})
filesHelper.writeFiles = jest.fn(() => {})
await expect(require('../main').run()).resolves.toBe(
undefined
)
expect(githubHelper.getChangedFiles).toBeCalled()
expect(filesHelper.writeOutput).toBeCalled()
expect(filesHelper.writeFiles).toBeCalled()
})
it.each(getTestEvents(p.mainErrorInputs, 'push'))(
'...throws error for mocked function %s...',
async (f, e, expected) => {
const inputHelper = require('../InputHelper')
let thrown = false
inputHelper.getInputs = jest.fn(() => {
thrown = true
throw new Error(e)
})
await expect(
require('../main').run()
).rejects.toThrowError(
new Error(
JSON.stringify({
name: 'Error',
message: 'Error',
from: f
})
)
)
expect(inputHelper.getInputs).toHaveBeenCalledTimes(1)
}
)
}
)
}
)
}
)
})
})
})

View File

@@ -0,0 +1,55 @@
import {mock} from '.'
const core = mock()
describe('Testing CoreMock object...', () => {
beforeAll(() => jest.restoreAllMocks())
it('...CoreMock is a mock', () => {
expect(jest.isMockFunction(core.getInput)).toBe(true)
expect(jest.isMockFunction(core.setFailed)).toBe(true)
expect(jest.isMockFunction(core.setOutput)).toBe(true)
expect(jest.isMockFunction(core.debug)).toBe(true)
expect(jest.isMockFunction(core.warning)).toBe(true)
expect(jest.isMockFunction(core.info)).toBe(true)
expect(jest.isMockFunction(core.error)).toBe(true)
})
it('...CoreMock mocks core', () => {
const realCore = require('@actions/core')
expect(core).toMatchObject(realCore)
})
it('...CoreMock mocks setFailed', () => {
core.setFailed('Test Message')
expect(core.error).toBeCalledWith('Test Message')
expect(core.setFailed).toBeCalledWith('Test Message')
})
it('...CoreMock mocks setOutput', () => {
core.setOutput('TestName', 'TestValue')
expect(core.setOutput).toBeCalledWith('TestName', 'TestValue')
})
it('...CoreMock mocks setOutput error', () => {
expect(() => core.setOutput('ERROROUTPUT', 'TestValue')).toThrowError(
new Error(JSON.stringify({name: 'CoreError', status: '500'}))
)
})
it('...CoreMock mocks getInput', () => {
process.env.INPUT_TEST = 'TESTINPUT'
const input = core.getInput('TEST')
expect(input).toBe('TESTINPUT')
})
it('...CoreMock mocks debug', () => {
core.debug('Test Message')
expect(core.debug).toBeCalledWith('Test Message')
})
it('...CoreMock mocks warning', () => {
core.warning('Test Message')
expect(core.warning).toBeCalledWith('Test Message')
})
it('...CoreMock mocks info', () => {
core.info('Test Message')
expect(core.info).toBeCalledWith('Test Message')
})
it('...CoreMock mocks error', () => {
core.error('Test Message')
expect(core.error).toBeCalledWith('Test Message')
})
})

View File

@@ -0,0 +1,34 @@
import {CoreMock} from 'typings/CoreMock'
const coreMock: CoreMock = {
setFailed: jest.fn(message => {
coreMock.error(message)
// console.error(`setFailed triggered`)
}),
setOutput: jest.fn((name, value) => {
if (name === 'ERROROUTPUT')
throw new Error(JSON.stringify({name: 'CoreError', status: '500'}))
// console.log(`setOutputName: ${name} value: ${value}`)
}),
// eslint-disable-next-line @typescript-eslint/no-unused-vars
getInput: jest.fn((name, options) => {
return process.env[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`]
}),
debug: jest.fn(message => {
// console.debug(`core.debug triggered: ${message}`)
}),
warning: jest.fn(message => {
// console.warn(`core.warning triggered: ${message}`)
}),
info: jest.fn(message => {
// console.info(`core.info triggered: ${message}`)
}),
error: jest.fn(message => {
// console.error(`core.error triggered: ${message}`)
})
}
export function mock(): CoreMock {
jest.mock('@actions/core', () => coreMock)
return coreMock
}

View File

@@ -0,0 +1,23 @@
import {mock} from '.'
const fs = mock()
describe('Testing FsMock object...', () => {
beforeAll(() => jest.restoreAllMocks())
it('...FsMock is a mock', () => {
expect(jest.isMockFunction(fs.writeFileSync)).toBe(true)
})
it('...FsMock mocks fs', () => {
const realFs = require('fs')
expect(fs).toMatchObject(realFs)
})
it('...FsMock mocks writeFileSync', () => {
fs.writeFileSync('a', 'b', 'c')
expect(fs.writeFileSync).toBeCalledWith('a', 'b', 'c')
})
it('...FsMock mocks an error', async () => {
expect(() => fs.writeFileSync('error', 'b', 'c')).toThrowError(
new Error(JSON.stringify({name: 'PathError', status: '500'}))
)
})
})

View File

@@ -0,0 +1,14 @@
import {FsMock} from 'typings/FsMock'
const fsMock = {
writeFileSync: jest.fn((path, data, options) => {
if (path === 'error')
throw new Error(JSON.stringify({name: 'PathError', status: '500'}))
// console.log(`fs.writeFileSync triggered with path: ${path} data: ${data} options: ${options}`)
})
}
export function mock(): FsMock {
jest.mock('fs', () => fsMock)
return fsMock
}

View File

@@ -0,0 +1,29 @@
import {Context} from '@actions/github/lib/context'
import {mock} from '.'
import {octokitMock} from '../octokit'
const github = mock()
describe('Testing GitHubMock object ...', () => {
beforeAll(() => jest.restoreAllMocks())
it('...GitHubMock is a mock', () => {
expect(jest.isMockFunction(github.github.GitHub)).toBe(true)
expect(github.context).toMatchObject(new Context())
})
it('...GitHubMock mocks GitHub', () => {
const {GitHub} = require('@actions/github')
const mockGitHub = GitHub('test')
expect(mockGitHub).toMatchObject(octokitMock)
})
it('...GitHubMock mocks unauthorized GitHub', () => {
const GitHub = mock()
expect(jest.isMockFunction(GitHub.github.GitHub)).toBe(true)
})
it('...GitHubMock mocks authorizing GitHub', () => {
const GitHub = mock()
const octokit = GitHub.github.GitHub('token')
expect(jest.isMockFunction(GitHub.github.GitHub)).toBe(true)
expect(GitHub.github.GitHub).toBeCalledWith('token')
expect(octokit).toMatchObject(octokitMock)
})
})

View File

@@ -0,0 +1,29 @@
import {Context} from '@actions/github/lib/context'
import {GitHubMock} from 'typings/GitHubMock'
import {OctokitMock} from 'typings/OctokitMock'
import {octokitMock} from '../octokit'
function getGitHubMock(context: Context): GitHubMock {
return {
GitHub: jest.fn(token => {
// console.log(`I am authorizing GitHub with token: ${token}`)
if (!token)
throw new Error(
JSON.stringify({name: 'GithubInitError', status: '500'})
)
return octokitMock
}),
context
}
}
export function mock(): {
github: GitHubMock
octokit: OctokitMock
context: Context
} {
const context = new Context()
const github = getGitHubMock(context)
jest.mock('@actions/github', () => github)
return {github, octokit: octokitMock, context}
}

View File

@@ -0,0 +1,48 @@
import {EndpointOptions} from '@octokit/types'
import {fn as merge} from './merge'
import {
OctokitPullsListFilesEndpointMergeRequest,
OctokitPullsListFilesEndpointMergeResponse,
OctokitReposCompareCommitsEndpointMergeRequest,
OctokitReposCompareCommitsEndpointMergeResponse
} from '../payloads'
describe('Testing Octokit object...', () => {
beforeAll(() => {
jest.restoreAllMocks()
})
it('...endpoint.merge returns 500 error with pull_number "error"', () => {
expect(() => {
merge(({pull_number: 'error'} as unknown) as EndpointOptions)
}).toThrowError(
new Error(JSON.stringify({name: 'HttpError', status: '500'}))
)
})
it('...endpoint.merge returns 500 error with base "error"', () => {
expect(() => {
merge(({base: 'error'} as unknown) as EndpointOptions)
}).toThrowError(
new Error(JSON.stringify({name: 'HttpError', status: '500'}))
)
})
it('...endpoint.merge returns empty object', async () => {
const request = OctokitPullsListFilesEndpointMergeRequest
const data = merge({...request, pull_number: NaN})
expect(data).toStrictEqual({
...OctokitPullsListFilesEndpointMergeResponse,
...{pull_number: NaN, base: '', head: ''}
})
})
it('...endpoint.merge for pull request', () => {
const request = OctokitPullsListFilesEndpointMergeRequest
const response = OctokitPullsListFilesEndpointMergeResponse
const data = merge(request)
expect(data).toStrictEqual(response)
})
it('...endpoint.merge for push', () => {
const request = OctokitReposCompareCommitsEndpointMergeRequest
const response = OctokitReposCompareCommitsEndpointMergeResponse
const data = merge(request)
expect(data).toStrictEqual(response)
})
})

View File

@@ -0,0 +1,39 @@
// Import Request and Response Objects
import {EndpointOptions, RequestOptions} from '@octokit/types'
import {
// OctokitReposCompareCommitsEndpointMergeRequest,
OctokitReposCompareCommitsEndpointMergeResponse,
// OctokitPullsListFilesEndpointMergeRequest,
OctokitPullsListFilesEndpointMergeResponse
} from '../payloads'
// Form and export Response Objects
export {OctokitReposCompareCommitsEndpointMergeResponse as pushResponse}
export {OctokitPullsListFilesEndpointMergeResponse as prResponse}
// Export mock function
export const fn = jest.fn((data: EndpointOptions, response?: number) => {
if (data.base === 'error' || data.pull_number === 'error') {
throw new Error(JSON.stringify({name: 'HttpError', status: '500'}))
}
if (data.base === 'unknown' || data.pull_number === 'unknown') {
throw JSON.stringify({idk: 'error', message: 'test'})
}
if (
(!data.base && !data.head && Number.isNaN(data.pull_number)) ||
(!data.base && data.head) ||
(data.base && !data.head)
)
return {
...OctokitPullsListFilesEndpointMergeResponse,
...{pull_number: NaN, base: '', head: ''}
} as RequestOptions
if (data.pull_number) {
return {
...OctokitPullsListFilesEndpointMergeResponse,
...data
} as RequestOptions
}
return {
...OctokitReposCompareCommitsEndpointMergeResponse,
...data
} as RequestOptions
})

View File

@@ -0,0 +1,11 @@
import {octokitMock} from '.'
describe('Testing Octokit object ...', () => {
beforeAll(() => jest.restoreAllMocks())
it('...Octokit is a mock', () => {
expect(octokitMock).toHaveProperty('paginate')
expect(octokitMock).toHaveProperty('pulls')
expect(octokitMock).toHaveProperty('repos')
expect(octokitMock).not.toHaveProperty('actions')
})
})

View File

@@ -0,0 +1,32 @@
import {EndpointOptions, OctokitResponse} from '@octokit/types'
import {OctokitMock} from 'typings/OctokitMock'
// mock endpoints
import {fn as endpointMerge} from './endpoint/merge'
import {fn as paginate} from './paginate'
import {fn as listFiles} from './pulls/listFiles'
import {fn as compareCommits} from './repos/compareCommits'
// new object
export const octokitMock: OctokitMock = {
paginate: (
data: EndpointOptions,
cb?: (response: OctokitResponse<any>) => Promise<any[]>
) => paginate(data, cb),
pulls: {
listFiles: Object.assign((data: EndpointOptions) => listFiles(data), {
endpoint: {
merge: (data: EndpointOptions) => endpointMerge(data)
}
})
},
repos: {
compareCommits: Object.assign(
(data: EndpointOptions) => compareCommits(data),
{
endpoint: {
merge: (data: EndpointOptions) => endpointMerge(data)
}
}
)
}
}

View File

@@ -0,0 +1,55 @@
import {fn as paginate} from './paginate'
import {
OctokitPaginatePrRequest,
OctokitPaginatePrResponse,
OctokitPaginatePushRequest,
OctokitPaginatePushResponse
} from './payloads'
describe('Testing Octokit object...', () => {
beforeAll(() => {
jest.restoreAllMocks()
})
it('...paginate(request) throws a 404', async () => {
const request = OctokitPaginatePrRequest
await expect(
paginate({...request, pull_number: NaN})
).rejects.toMatchObject({name: 'HttpError', status: '404'})
})
it('...paginate(request) for pull request', () => {
const request = OctokitPaginatePrRequest
const response = OctokitPaginatePrResponse
return paginate(request).then(data => {
expect(data).toStrictEqual(response)
return expect(data.length).toBe(7)
})
})
it('...paginate(request, callback) for pull request', () => {
const request = OctokitPaginatePrRequest
const response = OctokitPaginatePrResponse
return paginate(request, res => {
return res.data
}).then(data => {
expect(data).toStrictEqual(response)
return expect(data.length).toBe(7)
})
})
it('...paginate(request) for push', async () => {
const request = OctokitPaginatePushRequest
const response = OctokitPaginatePushResponse
expect.assertions(1)
const files = await paginate(request).then(data => {
return data.map(commit => commit.files)
})
expect(files).toStrictEqual([response])
})
it('...paginate(request, callback) for push', async () => {
const request = OctokitPaginatePushRequest
const response = OctokitPaginatePushResponse
const files = await paginate(request, res => {
return res.data.files
})
expect(files).toStrictEqual(response)
expect(files.length).toBe(7)
})
})

View File

@@ -0,0 +1,39 @@
// Import Request and Response Objects
import {EndpointOptions, OctokitResponse} from '@octokit/types'
import {
// OctokitPaginatePrRequest,
OctokitPaginatePrResponse,
// OctokitPaginatePushRequest,
OctokitPaginatePushResponse
} from './payloads'
// Form and export Response Objects
export const prResponse = OctokitPaginatePrResponse
export const pushResponse = {files: OctokitPaginatePushResponse}
// Export mock function
export const fn = jest.fn(
(
data: EndpointOptions,
cb?: (response: OctokitResponse<any>) => Promise<any[]>
) => {
if (
data.owner !== 'trilom' ||
data.repo !== 'file-changes-action' ||
(data.base && !data.head) ||
(!data.base && data.head) ||
// the github api doesn't seem to return an error
// eslint-disable-next-line prefer-promise-reject-errors
(!data.base && !data.head && !data.pull_number)
)
// eslint-disable-next-line prefer-promise-reject-errors
return Promise.reject({name: 'HttpError', status: '404'})
if (data.pull_number) {
if (cb)
return Promise.resolve(cb({data: prResponse} as OctokitResponse<any>))
return Promise.resolve(prResponse)
}
if (cb)
return Promise.resolve(cb({data: pushResponse} as OctokitResponse<any>))
return Promise.resolve([pushResponse])
}
)

View File

@@ -0,0 +1,178 @@
import {EndpointOptions} from '@octokit/types'
/**
* FILES
*/
const listFilesResponse: any[] = [
{
filename: '.github/CONTRIBUTING.md',
status: 'added'
},
{
filename: '.github/craneEventLambda.md',
status: 'added'
},
{
filename: '.github/readme.md',
status: 'added'
},
{
filename: 'functions/twitch-sadako/webhookSubscribeLambda/handler.py',
status: 'added'
},
{
filename: 'functions/twitch-sadako/getCraneStatsLambda/handler.py',
status: 'removed'
},
{
filename: '.github/ISSUE_TEMPLATE/bug_report.md',
status: 'modified'
},
{
filename:
'functions/twitch-sadako/webhookSubscribeLambda/test/webhookSubscribeLambda.json',
status: 'renamed'
}
]
const pushRequest: any = {
owner: 'trilom',
repo: 'file-changes-action',
base: '01a956ad7dbd39773299d421b402535cef6ab1f3',
head: '513ca39ff3756e5b510ad752edaba6a0aeb2efac'
}
const prRequest: any = {
owner: 'trilom',
repo: 'file-changes-action',
pull_number: 79
}
const pushEndpointOptions: EndpointOptions = {
method: 'GET',
baseUrl: 'https://api.github.com',
url: '/repos/:owner/:repo/compare/:base...:head',
owner: 'trilom',
repo: 'file-changes-action',
base: '01a956ad7dbd39773299d421b402535cef6ab1f3',
head: '513ca39ff3756e5b510ad752edaba6a0aeb2efac'
}
const prEndpointOptions: EndpointOptions = {
method: 'GET',
baseUrl: 'https://api.github.com',
url: '/repos/:owner/:repo/pulls/:pull_number/files',
owner: 'trilom',
repo: 'file-changes-action',
pull_number: 79
}
export const normalFileArray: string[] = [
'.github/actions/deploy_infrastructure/deploy',
'.github/actions/deploy_infrastructure/deploy_delete_commands.json',
'.github/actions/deploy_infrastructure/deploy_deploy_commands.json',
'.github/actions/deploy_infrastructure/deploy_validate_commands.json',
'.github/actions/deploy_infrastructure/prefix_deploy_commands.json',
'.github/actions/deploy_infrastructure/suffix_deploy_commands.json',
'.python-version',
'cloudformation/.python-version',
'cloudformation/mappings/mappings.twitch.yml',
'cloudformation/order/twitch.yml',
'cloudformation/templates/twitch-sadako.yml',
'cloudformation/templates/twitch-secrets.yml',
'functions/twitch-sadako/Makefile',
'functions/twitch-sadako/craneEventLambda/handler.py',
'functions/twitch-sadako/craneEventLambda/requirements.txt',
'functions/twitch-sadako/craneEventLambda/test/craneEventLambda.json',
'functions/twitch-sadako/followEventLambda/handler.py',
'functions/twitch-sadako/followEventLambda/requirements.txt',
'functions/twitch-sadako/followEventLambda/test/followEventLambda_get.json',
'functions/twitch-sadako/followEventLambda/test/followEventLambda_post.json',
'functions/twitch-sadako/getCraneStatsLambda/handler.py',
'functions/twitch-sadako/getCraneStatsLambda/requirements.txt',
'functions/twitch-sadako/getCraneStatsLambda/test/getCraneStatsLambda.json',
'functions/twitch-sadako/getTokenLambda/handler.py',
'functions/twitch-sadako/getTokenLambda/requirements.txt',
'functions/twitch-sadako/getTokenLambda/test/getTokenLambda.json',
'functions/twitch-sadako/slackNotifyLambda/handler.py',
'functions/twitch-sadako/slackNotifyLambda/requirements.txt',
'functions/twitch-sadako/slackNotifyLambda/test/slackNotifyLambda.json',
'functions/twitch-sadako/webhookSubscribeCronLambda/handler.py',
'functions/twitch-sadako/webhookSubscribeCronLambda/requirements.txt',
'functions/twitch-sadako/webhookSubscribeCronLambda/test/webhookSubscribeCronLambda.json',
'functions/twitch-sadako/webhookSubscribeLambda/handler.py',
'functions/twitch-sadako/webhookSubscribeLambda/requirements.txt',
'functions/twitch-sadako/webhookSubscribeLambda/test/webhookSubscribeLambda.json',
'functions/twitch-sadako/webhookSubscribeLambda/test/webhookSubscribeLambda_post.json',
'.github/ISSUE_TEMPLATE/bug_report.md',
'.github/ISSUE_TEMPLATE/feature_request.md',
'.github/workflows/nodejs.yml',
'.gitignore',
'.npmignore',
'.vscode/launch.json',
'README-template.md',
'README.md',
'jest.config.js',
'package-lock.json',
'package.json',
'src/boolean-serializer.ts',
'src/date-serializer.ts',
'src/deserialize.ts',
'src/index.ts',
'src/model.ts',
'src/serialize-set.ts',
'src/serialize.ts',
'src/utilities.ts',
'src/validation.ts',
'test/unit/_ramda.sp.ts',
'test/unit/benchmark.spec.ts',
'test/unit/boolean-serializer.spec.ts',
'test/unit/data/generators.ts',
'test/unit/date-serializer.spec.ts',
'test/unit/deserialize.spec.ts',
'test/unit/sandbox.spec.ts',
'test/unit/sap/input.ts',
'test/unit/sap/json-object-mapper.ts',
'test/unit/sap/output.ts',
'test/unit/sap/serializers.ts',
'test/unit/serialize.spec.ts',
'test/unit/setup.ts',
'test/unit/test-typings.ts',
'test/unit/test-typings2.ts',
'tsconfig.build.json',
'tsconfig.json'
]
export const weirdFileArray: string[] = [
'.cfnlintrc',
".github/actions/deploy_infrastruc1234'ture/deploy.sh",
'.github/actions/make_commands/&&&index.js',
'.github/actions/make_comdf&*(@mands/test/files_added.json',
'.github/actions/make_c``ommands/test/files_removed.json',
'.github/actions/make commands/test/files_modified.json',
'.pre-commit-config.yaml',
'cloudformation/Makefile',
'cloudformation/mappings/mappings.awsaccount.yml'
]
/**
* REQUESTS
*/
// Octokit.pulls.listFiles
export {prRequest as OctokitPullsListFilesRequest}
// Octokit.pulls.listFiles.endpoint.merge
export {prRequest as OctokitPullsListFilesEndpointMergeRequest}
// Octokit.repos.compareCommits
export {pushRequest as OctokitReposCompareCommitsRequest}
// Octokit.repos.compareCommits.endpoint.merge
export {pushRequest as OctokitReposCompareCommitsEndpointMergeRequest}
// Octokit.paginate
export {prEndpointOptions as OctokitPaginatePrRequest} // pr
export {pushEndpointOptions as OctokitPaginatePushRequest} // push
/**
* RESPONSES
*/
// Octokit.pulls.listFiles
export {listFilesResponse as OctokitPullsListFilesResponse}
// Octokit.pulls.listFiles.endpoint.merge
export {prEndpointOptions as OctokitPullsListFilesEndpointMergeResponse}
// Octokit.repos.compareCommits
export {listFilesResponse as OctokitReposCompareCommitsResponse}
// Octokit.repos.compareCommits.endpoint.merge
export {pushEndpointOptions as OctokitReposCompareCommitsEndpointMergeResponse}
// Octokit.paginate
export {listFilesResponse as OctokitPaginatePrResponse} // pr
export {listFilesResponse as OctokitPaginatePushResponse} // push

View File

@@ -0,0 +1,19 @@
import {fn as listFiles} from './listFiles'
import {
OctokitPullsListFilesRequest,
OctokitPullsListFilesResponse
} from '../payloads'
describe('Testing Octokit object...', () => {
beforeAll(() => {
jest.restoreAllMocks()
})
it('...pulls.listFiles(request) for pull request', () => {
const request = OctokitPullsListFilesRequest
const response = OctokitPullsListFilesResponse
return listFiles(request).then(data => {
expect(data.data).toBe(response)
return expect(data.data.length).toBe(7)
})
})
})

View File

@@ -0,0 +1,14 @@
// Import Request and Response Objects
import {EndpointOptions, OctokitResponse} from '@octokit/types'
import {
// OctokitPullsListFilesRequest,
OctokitPullsListFilesResponse
} from '../payloads'
// Form and export Response Objects
export {OctokitPullsListFilesResponse as response}
// Export mock function
export const fn = jest.fn((data: EndpointOptions) => {
return Promise.resolve({
data: OctokitPullsListFilesResponse
} as OctokitResponse<any>)
})

View File

@@ -0,0 +1,19 @@
import {fn as compareCommits} from './compareCommits'
import {
OctokitReposCompareCommitsRequest,
OctokitReposCompareCommitsResponse
} from '../payloads'
describe('Testing Octokit object...', () => {
beforeAll(() => {
jest.restoreAllMocks()
})
it('...repos.compareCommits(request) for push', () => {
const request = OctokitReposCompareCommitsRequest
const response = OctokitReposCompareCommitsResponse
return compareCommits(request).then(data => {
expect(data.data.files).toBe(response)
return expect(data.data.files.length).toBe(7)
})
})
})

View File

@@ -0,0 +1,16 @@
// Import Request and Response Objects
import {EndpointOptions, OctokitResponse} from '@octokit/types'
import {
// OctokitReposCompareCommitsRequest,
OctokitReposCompareCommitsResponse
} from '../payloads'
// Form and export Response Objects
export {OctokitReposCompareCommitsResponse as response}
// Export mock function
export const fn = jest.fn((data: EndpointOptions) => {
return Promise.resolve({
data: {
files: OctokitReposCompareCommitsResponse
}
} as OctokitResponse<any>)
})

View File

@@ -0,0 +1,61 @@
import {Env, p, getTestFiles, getTestEvents} from './mocks/env'
let env: Env
it('set default inputs', () => {
const input = p.changedFilesInput()
const defaultFormats = ['json', ',', ' ', '_<br />&nbsp;&nbsp;_']
expect(input.length).toBe(4)
input.forEach((t, i) => {
expect(t.events).toBe('pull')
if (Array.isArray(t.inputs)) {
expect(t.inputs[0]).toBe(defaultFormats[i])
expect(t.inputs[1]).toBe(p.normalFileArray)
if (defaultFormats[i] === 'json')
expect(t.inputs[2]).toBe(JSON.stringify(t.inputs[1]))
else if (Array.isArray(t.inputs[1]))
expect(t.inputs[2]).toBe(t.inputs[1].join(defaultFormats[i]))
}
})
expect(input[0].events).toBe('pull')
})
describe('Testing payloads.ts...', () => {
describe.each([
{files: ['/test/file', '/test/file2']},
{files: ['/test/&&&file', '/test/&&&file2']},
{files: ['/test/f&*(@mafile1', '/test/f&*(@mafile2']},
{files: ['/test/ke_c``ommands1', '/test/ke_c``ommands2']}
])('...changedFilesInput default with files %p...', files => {
describe.each(['json', ',', ' ', '_<br />&nbsp;&nbsp;_'])(
'...with format %s...',
format => {
it(`set default inputs files:${JSON.stringify(
files,
null,
2
)} format:${format}`, () => {
const input = p.changedFilesInput('pull', files.files, [format])
expect(input.length).toBe(1)
expect(input[0].events).toBe('pull')
if (Array.isArray(input[0].inputs)) {
expect(input[0].inputs[0]).toBe(format)
expect(input[0].inputs[1]).toBe(files.files)
if (format === 'json' && Array.isArray(input[0].inputs[2]))
expect(input[0].inputs[2]).toBe(
`[ "${input[0].inputs[2][0]}", "${input[0].inputs[2][1]}" ]`
)
else if (
Array.isArray(input[0].inputs[1]) &&
Array.isArray(input[0].inputs[2])
) {
expect(input[0].inputs[2]).toBe(
`${input[0].inputs[2][0]}${format}${input[0].inputs[2][1]}`
)
}
}
})
}
)
})
})

View File

@@ -0,0 +1,709 @@
// Imports
import {Inferred} from 'typings/Inferred'
import {TestInput} from 'typings/TestInput'
import * as p from './mocks/octokit/payloads'
/**
* Events to Test
*/
export const testEvents: string[] = [
'issue_comment_created',
'issue_comment_edited',
'pull_request_opened',
'pull_request_reopened',
'pull_request_synchronize',
'push_merge',
'push',
'schedule'
]
export function changedFilesInput(
event = 'pull',
files: string[] = p.normalFileArray,
formats: string[] = ['json', ',', ' ', '_<br />&nbsp;&nbsp;_']
): TestInput[] {
return formats.map(format => {
if (format === 'json')
return {
inputs: [format, files, JSON.stringify(files)],
events: event
} as TestInput
return {
inputs: [format, files, files.join(format)],
events: event
} as TestInput
})
}
/**
* FilesHelper Test inputs
*/
export const getFormatExtInputs: TestInput[] = [
{inputs: ['json', 'json', '.json'], events: 'push'},
{inputs: ['csv', ',', '.csv'], events: 'push'},
{inputs: ['txt', ' ', '.txt'], events: 'push'},
{inputs: ['txt_hard', '_<br />&nbsp;&nbsp;_', '.txt'], events: 'push'}
]
/**
* GithubHelper Test inputs
*/
export const initClientTestInputs: TestInput[] = [
{
inputs: [
'calls the Github client constructor with a token',
'12345abcde',
'12345abcde'
],
events: 'all'
},
{
inputs: ['calls the Github client constructor without a token', '', ''],
events: 'all'
}
]
export const getChangedPRFilesTestInputs: TestInput[] = [
{
inputs: [
'gets changed files for a pull request',
{owner: 'trilom', repo: 'file-changes-action', pullNumber: 83},
p.OctokitPaginatePrResponse
],
events: 'all'
},
{
inputs: [
'throws an error with no pull request',
{owner: 'trilom', repo: 'file-changes-action', pullNumber: NaN},
{
error: '404/HttpError',
from: 'getChangedPRFiles',
message:
'There was an error getting change files for repo:file-changes-action owner:trilom pr:NaN',
payload: {name: 'HttpError', status: '404'}
}
],
events: 'all'
},
{
inputs: [
'throws an error with invalid repo for pull request',
{
owner: 'trilom',
repo: 'file-chandkdk-action-thatdoesntreallyexist',
pullNumber: 83
},
{
error: '404/HttpError',
from: 'getChangedPRFiles',
message:
'There was an error getting change files for repo:file-chandkdk-action-thatdoesntreallyexist owner:trilom pr:83',
payload: {name: 'HttpError', status: '404'}
}
],
events: 'all'
},
{
inputs: [
'throws an error with invalid owner for pull request',
{
owner: 'this-isntareal-githubowner',
repo: 'file-changes-action',
pullNumber: 83
},
{
error: '404/HttpError',
from: 'getChangedPRFiles',
message:
'There was an error getting change files for repo:file-changes-action owner:this-isntareal-githubowner pr:83',
payload: {name: 'HttpError', status: '404'}
}
],
events: 'all'
}
]
export const getChangedPushFilesTestInputs: TestInput[] = [
{
inputs: [
'gets changed files for a push',
{
owner: 'trilom',
repo: 'file-changes-action',
before: '6ac7697cd1c4f23a08d4d4edbe7dab06b34c58a2',
after: '4ee1a1a2515f4ac1b90a56aaeb060b97f20c8968'
},
p.OctokitPaginatePushResponse
],
events: 'all'
},
{
inputs: [
'throws an error with no before for a push',
{
owner: 'trilom',
repo: 'file-changes-action',
before: '',
after: '4ee1a1a2515f4ac1b90a56aaeb060b97f20c8968'
},
{
error: '404/HttpError',
from: 'getChangedPushFiles',
message:
'There was an error getting change files for repo:file-changes-action owner:trilom base: head:4ee1a1a2515f4ac1b90a56aaeb060b97f20c8968',
payload: {name: 'HttpError', status: '404'}
}
],
events: 'all'
},
{
inputs: [
'throws an error with no after for a push',
{
owner: 'trilom',
repo: 'file-changes-action',
before: '6ac7697cd1c4f23a08d4d4edbe7dab06b34c58a2',
after: ''
},
{
error: '404/HttpError',
from: 'getChangedPushFiles',
message:
'There was an error getting change files for repo:file-changes-action owner:trilom base:6ac7697cd1c4f23a08d4d4edbe7dab06b34c58a2 head:',
payload: {name: 'HttpError', status: '404'}
}
],
events: 'all'
},
{
inputs: [
'throws an error with invalid repo for a push',
{
owner: 'trilom',
repo: 'file-chandkdk-action-thatdoesntreallyexist',
before: '6ac7697cd1c4f23a08d4d4edbe7dab06b34c58a2',
after: '4ee1a1a2515f4ac1b90a56aaeb060b97f20c8968'
},
{
error: '404/HttpError',
from: 'getChangedPushFiles',
message:
'There was an error getting change files for repo:file-chandkdk-action-thatdoesntreallyexist owner:trilom base:6ac7697cd1c4f23a08d4d4edbe7dab06b34c58a2 head:4ee1a1a2515f4ac1b90a56aaeb060b97f20c8968',
payload: {name: 'HttpError', status: '404'}
}
],
events: 'all'
},
{
inputs: [
'throws an error with invalid owner for a push',
{
owner: 'this-isntareal-githubowner',
repo: 'file-changes-action',
before: '6ac7697cd1c4f23a08d4d4edbe7dab06b34c58a2',
after: '4ee1a1a2515f4ac1b90a56aaeb060b97f20c8968'
},
{
error: '404/HttpError',
from: 'getChangedPushFiles',
message:
'There was an error getting change files for repo:file-changes-action owner:this-isntareal-githubowner base:6ac7697cd1c4f23a08d4d4edbe7dab06b34c58a2 head:4ee1a1a2515f4ac1b90a56aaeb060b97f20c8968',
payload: {name: 'HttpError', status: '404'}
}
],
events: 'all'
}
]
export const getChangedFilesTestInputs: TestInput[] = [
{
inputs: [
'gets changed files for a push',
{
repo: 'trilom/file-changes-action',
...({
before: '6ac7697cd1c4f23a08d4d4edbe7dab06b34c58a2',
after: '4ee1a1a2515f4ac1b90a56aaeb060b97f20c8968'
} as Inferred)
},
p.OctokitPaginatePushResponse
],
events: 'all'
},
{
inputs: [
'throws an error with a malformed owner/repo for a push',
{
repo: 'trilom/testing/afew/backslash',
...({
before: '6ac7697cd1c4f23a08d4d4edbe7dab06b34c58a2',
after: '4ee1a1a2515f4ac1b90a56aaeb060b97f20c8968'
} as Inferred)
},
{
error: '500/Unknown Error:Error',
from: 'getChangedFiles',
message:
'There was an error getting change files outputs pr: NaN before: 6ac7697cd1c4f23a08d4d4edbe7dab06b34c58a2 after: 4ee1a1a2515f4ac1b90a56aaeb060b97f20c8968',
payload: JSON.stringify(
{
error: '500/Bad-Repo',
from: 'self',
message:
'Repo input of trilom/testing/afew/backslash has more than 2 length after splitting.',
payload: ''
},
null,
2
)
}
],
events: 'all'
},
{
inputs: [
'throws an error with invalid owner for a push',
{
repo: 'trilom-NOTREAL/backslash',
...({
before: '6ac7697cd1c4f23a08d4d4edbe7dab06b34c58a2',
after: '4ee1a1a2515f4ac1b90a56aaeb060b97f20c8968'
} as Inferred)
},
{
error: '404/HttpError',
from: 'undefined/Error',
message:
'There was an error getting change files for repo:backslash owner:trilom-NOTREAL base:6ac7697cd1c4f23a08d4d4edbe7dab06b34c58a2 head:4ee1a1a2515f4ac1b90a56aaeb060b97f20c8968',
payload: {name: 'HttpError', status: '404'}
}
],
events: 'all'
},
{
inputs: [
'throws an error with no after for a push',
{
repo: 'trilom/cloudformation',
...({before: '6ac7697cd1c4f23a08d4d4edbe7dab06b34c58a2'} as Inferred)
},
{
error: '404/HttpError',
from: 'undefined/Error',
message:
'There was an error getting change files for repo:cloudformation owner:trilom base:6ac7697cd1c4f23a08d4d4edbe7dab06b34c58a2 head:',
payload: {name: 'HttpError', status: '404'}
}
],
events: 'all'
},
{
inputs: [
'throws an error with no before for a push',
{
repo: 'trilom/cloudformation',
...({after: '4ee1a1a2515f4ac1b90a56aaeb060b97f20c8968'} as Inferred)
},
{
error: '404/HttpError',
from: 'undefined/Error',
message:
'There was an error getting change files for repo:cloudformation owner:trilom base: head:4ee1a1a2515f4ac1b90a56aaeb060b97f20c8968',
payload: {name: 'HttpError', status: '404'}
}
],
events: 'all'
},
{
inputs: [
'gets changed files for a pull request',
{repo: 'trilom/file-changes-action', ...({pr: 83} as Inferred)},
p.OctokitPaginatePrResponse
],
events: 'all'
},
{
inputs: [
'throws an error with a malformed owner/repo for a pr',
{repo: 'trilom/testing/afew/backslash', ...({pr: 83} as Inferred)},
{
error: '500/Unknown Error:Error',
from: 'getChangedFiles',
message:
'There was an error getting change files outputs pr: 83 before: undefined after: undefined',
payload: JSON.stringify(
{
error: '500/Bad-Repo',
from: 'self',
message:
'Repo input of trilom/testing/afew/backslash has more than 2 length after splitting.',
payload: ''
},
null,
2
)
}
],
events: 'all'
},
{
inputs: [
'throws an error with invalid owner for a pr',
{repo: 'trilom-NOTREAL/backslash', ...({pr: 80} as Inferred)},
{
error: '404/HttpError',
from: 'undefined/Error',
message:
'There was an error getting change files for repo:backslash owner:trilom-NOTREAL pr:80',
payload: {name: 'HttpError', status: '404'}
}
],
events: 'all'
},
{
inputs: [
'throws an error with no pull request',
{repo: 'trilom/cloudformation', ...({} as Inferred)},
{
error: '404/HttpError',
from: 'undefined/Error',
message:
'There was an error getting change files for repo:cloudformation owner:trilom base: head:',
payload: {name: 'HttpError', status: '404'}
}
],
events: 'all'
},
{
inputs: [
'throws an error with no pull request',
{repo: 'trilom/cloudformation', ...({} as Inferred)},
{
error: '404/HttpError',
from: 'undefined/Error',
message:
'There was an error getting change files for repo:cloudformation owner:trilom base: head:',
payload: {name: 'HttpError', status: '404'}
}
],
events: 'all'
}
]
/**
* InputHelper Test inputs
*/
export const inputTestInputs: TestInput[] = [
{
inputs: [
'githubRepo',
'trilom-test/file-changes-action',
'trilom-test/file-changes-action'
],
events: 'all'
},
{inputs: ['githubToken', 'InputTestToken', 'InputTestToken'], events: 'all'},
{
inputs: [
'pushBefore',
'6ac7697cd1c4f23a08d4d4edbe7dab06b34c58a2',
'6ac7697cd1c4f23a08d4d4edbe7dab06b34c58a2'
],
events: 'all'
},
{
inputs: [
'pushAfter',
'4ee1a1a2515f4ac1b90a56aaeb060b97f20c8968',
'4ee1a1a2515f4ac1b90a56aaeb060b97f20c8968'
],
events: 'all'
},
{inputs: ['prNumber', '83', 83], events: 'all'},
{inputs: ['output', 'json', 'json'], events: 'all'},
{inputs: ['fileOutput', 'json', 'json'], events: 'all'}
]
export const inferTestInputs: TestInput[] = [
{
inputs: [
'sets PUSH inferred outputs with pr inputs and PUSH inputs and PULL_REQUEST event',
{
event: 'pull_request',
before: '6ac7697cd1c4f23a08d4d4edbe7dab06b34c58a2',
after: '4ee1a1a2515f4ac1b90a56aaeb060b97f20c8968',
pr: 83
},
{
before: '6ac7697cd1c4f23a08d4d4edbe7dab06b34c58a2',
after: '4ee1a1a2515f4ac1b90a56aaeb060b97f20c8968'
} as Inferred
],
events: ['pull_request_opened', 'pull_request_reopened']
},
{
inputs: [
'sets PR inferred outputs with pr inputs and PUSH inputs and PULL_REQUEST_SYNCHRONIZE event',
{
event: 'pull_request',
before: '6ac7697cd1c4f23a08d4d4edbe7dab06b34c58a2',
after: '4ee1a1a2515f4ac1b90a56aaeb060b97f20c8968',
pr: 83
},
{
before: '6ac7697cd1c4f23a08d4d4edbe7dab06b34c58a2',
after: '4ee1a1a2515f4ac1b90a56aaeb060b97f20c8968'
} as Inferred
],
events: ['pull_request_synchronize']
},
{
inputs: [
'sets PULL_REQUEST inferred outputs with single PUSH input and PULL_REQUEST event, ALSO WARN weird',
{
event: 'pull_request',
before: '787a72d40923de2f5308e7095ff9e6063fdbc219',
after: '',
pr: 83
},
{pr: 83} as Inferred
],
events: [
'pull_request_opened',
'pull_request_reopened',
'pull_request_synchronize'
]
},
{
inputs: [
'sets PULL_REQUEST inferred outputs with no PUSH inputs and PULL_REQUEST event',
{event: 'pull_request', before: '', after: '', pr: 83},
{pr: 83} as Inferred
],
events: [
'pull_request_opened',
'pull_request_reopened',
'pull_request_synchronize'
]
},
{
inputs: [
'sets PULL_REQUEST inferred outputs with pr input and PUSH event',
{
event: 'push',
before: '6ac7697cd1c4f23a08d4d4edbe7dab06b34c58a2',
after: '4ee1a1a2515f4ac1b90a56aaeb060b97f20c8968',
pr: 83
},
{pr: 83} as Inferred
],
events: ['push', 'push_merge']
},
{
inputs: [
'sets PUSH inferred outputs with no pr input and PUSH event',
{
event: 'push',
before: '6ac7697cd1c4f23a08d4d4edbe7dab06b34c58a2',
after: '4ee1a1a2515f4ac1b90a56aaeb060b97f20c8968',
pr: NaN
},
{
before: '6ac7697cd1c4f23a08d4d4edbe7dab06b34c58a2',
after: '4ee1a1a2515f4ac1b90a56aaeb060b97f20c8968'
} as Inferred
],
events: ['push', 'push_merge']
},
{
inputs: [
'sets PUSH inferred outputs with PUSH and PULL_REQUEST inputs NOT PUSH or PULL_REQUEST event, ALSO WARN all',
{
event: 'schedule',
before: '6ac7697cd1c4f23a08d4d4edbe7dab06b34c58a2',
after: '4ee1a1a2515f4ac1b90a56aaeb060b97f20c8968',
pr: 83
},
{
before: '6ac7697cd1c4f23a08d4d4edbe7dab06b34c58a2',
after: '4ee1a1a2515f4ac1b90a56aaeb060b97f20c8968'
} as Inferred
],
events: ['issue_comment_created', 'issue_comment_edited']
},
{
inputs: [
'sets PUSH inferred outputs with PUSH and PULL_REQUEST inputs NOT PUSH or PULL_REQUEST event, ALSO WARN all',
{
event: 'schedule',
before: '6ac7697cd1c4f23a08d4d4edbe7dab06b34c58a2',
after: '4ee1a1a2515f4ac1b90a56aaeb060b97f20c8968',
pr: 83
},
{pr: 83} as Inferred
],
events: ['schedule']
},
{
inputs: [
'sets PULL_REQUEST inferred outputs with single PUSH and PULL_REQUEST inputs NOT PUSH or PULL_REQUEST event, ALSO WARN weird',
{
event: 'schedule',
before: '',
after: '4ee1a1a2515f4ac1b90a56aaeb060b97f20c8968',
pr: 83
},
{pr: 83} as Inferred
],
events: ['issue_comment_created', 'issue_comment_edited', 'schedule']
},
{
inputs: [
'sets PULL_REQUEST inferred outputs with PULL_REQUEST input NOT PUSH or PULL_REQUEST event',
{event: 'schedule', before: '', after: '', pr: 83},
{pr: 83} as Inferred
],
events: ['issue_comment_created', 'issue_comment_edited', 'schedule']
},
{
inputs: [
'sets PUSH inferred outputs with PUSH inputs NOT PUSH or PULL_REQUEST event',
{
event: 'schedule',
before: '6ac7697cd1c4f23a08d4d4edbe7dab06b34c58a2',
after: '4ee1a1a2515f4ac1b90a56aaeb060b97f20c8968',
pr: NaN
},
{
before: '6ac7697cd1c4f23a08d4d4edbe7dab06b34c58a2',
after: '4ee1a1a2515f4ac1b90a56aaeb060b97f20c8968'
} as Inferred
],
events: ['issue_comment_created', 'issue_comment_edited', 'schedule']
},
{
inputs: [
'throws ERROR with no inputs NOT PUSH or PULL_REQUEST event',
{before: '', after: '', pr: NaN},
{} as Inferred
],
events: ['issue_comment_created', 'issue_comment_edited', 'schedule']
},
{
inputs: [
'throws ERROR with single only before NOT PUSH or PULL_REQUEST event',
{before: '6ac7697cd1c4f23a08d4d4edbe7dab06b34c58a2', pr: NaN},
{} as Inferred
],
events: ['issue_comment_created', 'issue_comment_edited', 'schedule']
},
{
inputs: [
'throws ERROR with single only after NOT PUSH or PULL_REQUEST event',
{after: '4ee1a1a2515f4ac1b90a56aaeb060b97f20c8968', pr: NaN},
{} as Inferred
],
events: ['issue_comment_created', 'issue_comment_edited', 'schedule']
}
]
/**
* UtilsHelper Test inputs
*/
export const errorMessageInputs: TestInput[] = [
{
inputs: [
'getInputs',
JSON.stringify(
{name: 'Error', message: 'Error', from: 'getInputs'},
null,
2
),
'There was an getting action inputs.'
],
events: 'all'
},
{
inputs: [
'inferInput',
JSON.stringify(
{name: 'Error', message: 'Error', from: 'inferInput'},
null,
2
),
'There was an issue inferring inputs to the action.'
],
events: 'all'
},
{
inputs: [
'initClient',
JSON.stringify(
{name: 'Error', message: 'Error', from: 'initClient'},
null,
2
),
'There was an issue initilizing the github client.'
],
events: 'all'
},
{
inputs: [
'getChangedFiles',
JSON.stringify(
{name: 'Error', message: 'Error', from: 'getChangedFiles'},
null,
2
),
'There was an issue getting changed files from Github.'
],
events: 'all'
},
{
inputs: [
'sortChangedFiles',
JSON.stringify(
{name: 'Error', message: 'Error', from: 'sortChangedFiles'},
null,
2
),
'There was an issue sorting changed files from Github.'
],
events: 'all'
},
{
inputs: [
'writeFiles',
JSON.stringify(
{name: 'Error', message: 'Error', from: 'writeFiles'},
null,
2
),
'There was an issue writing output files.'
],
events: 'all'
},
{
inputs: [
'writeOutput',
JSON.stringify(
{name: 'Error', message: 'Error', from: 'writeOutput'},
null,
2
),
'There was an issue writing output variables.'
],
events: 'all'
}
]
/**
* main Test inputs
*/
export const mainInputs: TestInput[] = [
{
inputs: [
'push',
{
pushBefore: '6ac7697cd1c4f23a08d4d4edbe7dab06b34c58a2',
pushAfter: '4ee1a1a2515f4ac1b90a56aaeb060b97f20c8968'
},
'push'
],
events: 'all'
},
{inputs: ['pull_request', {prNumber: '83'}, 'pull_request'], events: 'all'}
]
export {errorMessageInputs as mainErrorInputs}