2022-02-01 22:08:12 +00:00
import * as core from '@actions/core'
import * as github from '@actions/github'
2022-05-19 16:16:43 +00:00
2022-03-29 00:23:33 +00:00
import { addToProject , mustGetOwnerTypeQuery } from '../src/add-to-project'
2022-02-01 22:08:12 +00:00
describe ( 'addToProject' , () => {
let outputs : Record < string , string >
beforeEach (() => {
jest . spyOn ( process . stdout , 'write' ). mockImplementation (() => true )
})
beforeEach (() => {
mockGetInput ({
2022-06-30 10:48:09 +01:00
'project-url' : 'https://github.com/orgs/actions/projects/1' ,
2023-02-27 13:15:25 +00:00
'github-token' : 'gh_token' ,
2022-02-01 22:08:12 +00:00
})
outputs = mockSetOutput ()
})
afterEach (() => {
github . context . payload = {}
jest . restoreAllMocks ()
})
2022-06-30 10:48:09 +01:00
test ( 'adds an issue from the same organization to the project' , async () => {
github . context . payload = {
issue : {
number : 1 ,
labels : [{ name : 'bug' }],
// eslint-disable-next-line camelcase
2023-02-27 13:15:25 +00:00
html_url : 'https://github.com/actions/add-to-project/issues/74' ,
2022-06-30 10:48:09 +01:00
},
repository : {
name : 'add-to-project' ,
owner : {
2023-02-27 13:15:25 +00:00
login : 'actions' ,
},
},
2022-06-30 10:48:09 +01:00
}
2022-02-01 22:08:12 +00:00
mockGraphQL (
{
test : /getProject/ ,
return : {
organization : {
2022-05-19 16:16:43 +00:00
projectV2 : {
2023-02-27 13:15:25 +00:00
id : 'project-id' ,
},
},
},
2022-02-01 22:08:12 +00:00
},
{
2022-05-19 16:16:43 +00:00
test : /addProjectV2ItemById/ ,
2022-02-01 22:08:12 +00:00
return : {
2022-05-19 16:16:43 +00:00
addProjectV2ItemById : {
2022-06-27 15:01:14 +02:00
item : {
2023-02-27 13:15:25 +00:00
id : 'project-item-id' ,
},
},
},
},
2022-02-01 22:08:12 +00:00
)
await addToProject ()
2022-05-19 16:16:43 +00:00
expect ( outputs . itemId ). toEqual ( 'project-item-id' )
2022-02-01 22:08:12 +00:00
})
2022-06-30 10:48:09 +01:00
test ( 'adds an issue from a different organization to the project' , async () => {
github . context . payload = {
issue : {
number : 2221 ,
labels : [{ name : 'bug' }],
// eslint-disable-next-line camelcase
2023-02-27 13:15:25 +00:00
html_url : 'https://github.com/octokit/octokit.js/issues/2221' ,
2022-06-30 10:48:09 +01:00
},
repository : {
name : 'octokit.js' ,
owner : {
2023-02-27 13:15:25 +00:00
login : 'octokit' ,
},
},
2022-06-30 10:48:09 +01:00
}
mockGraphQL (
{
test : /getProject/ ,
return : {
organization : {
projectV2 : {
2023-02-27 13:15:25 +00:00
id : 'project-id' ,
},
},
},
2022-06-30 10:48:09 +01:00
},
{
test : /addProjectV2DraftIssue/ ,
return : {
addProjectV2DraftIssue : {
projectItem : {
2023-02-27 13:15:25 +00:00
id : 'project-item-id' ,
},
},
},
},
2022-06-30 10:48:09 +01:00
)
await addToProject ()
expect ( outputs . itemId ). toEqual ( 'project-item-id' )
})
2022-03-23 12:34:46 +02:00
test ( 'adds matching issues with a label filter without label-operator' , async () => {
2022-02-01 22:08:12 +00:00
mockGetInput ({
2022-06-30 10:48:09 +01:00
'project-url' : 'https://github.com/orgs/actions/projects/1' ,
2022-02-01 22:08:12 +00:00
'github-token' : 'gh_token' ,
2023-02-27 13:15:25 +00:00
labeled : 'bug, new' ,
2022-02-01 22:08:12 +00:00
})
github . context . payload = {
issue : {
number : 1 ,
2022-06-30 10:48:09 +01:00
labels : [{ name : 'bug' }],
// eslint-disable-next-line camelcase
2023-02-27 13:15:25 +00:00
html_url : 'https://github.com/actions/add-to-project/issues/74' ,
2022-06-30 10:48:09 +01:00
},
repository : {
name : 'add-to-project' ,
owner : {
2023-02-27 13:15:25 +00:00
login : 'actions' ,
},
},
2022-02-01 22:08:12 +00:00
}
mockGraphQL (
{
test : /getProject/ ,
return : {
organization : {
2022-05-19 16:16:43 +00:00
projectV2 : {
2023-02-27 13:15:25 +00:00
id : 'project-id' ,
},
},
},
2022-02-01 22:08:12 +00:00
},
{
2022-05-19 16:16:43 +00:00
test : /addProjectV2ItemById/ ,
2022-02-01 22:08:12 +00:00
return : {
2022-05-19 16:16:43 +00:00
addProjectV2ItemById : {
2022-06-27 15:01:14 +02:00
item : {
2023-02-27 13:15:25 +00:00
id : 'project-item-id' ,
},
},
},
},
2022-02-01 22:08:12 +00:00
)
await addToProject ()
2022-05-19 16:16:43 +00:00
expect ( outputs . itemId ). toEqual ( 'project-item-id' )
2022-02-01 22:08:12 +00:00
})
2022-03-29 00:23:33 +00:00
test ( 'adds matching pull-requests with a label filter without label-operator' , async () => {
mockGetInput ({
2022-06-30 10:48:09 +01:00
'project-url' : 'https://github.com/orgs/actions/projects/1' ,
2022-03-29 00:23:33 +00:00
'github-token' : 'gh_token' ,
2023-02-27 13:15:25 +00:00
labeled : 'bug, new' ,
2022-03-29 00:23:33 +00:00
})
github . context . payload = {
// eslint-disable-next-line camelcase
pull_request : {
number : 1 ,
2022-06-30 10:48:09 +01:00
labels : [{ name : 'bug' }],
// eslint-disable-next-line camelcase
2023-02-27 13:15:25 +00:00
html_url : 'https://github.com/actions/add-to-project/pull/136' ,
2022-06-30 10:48:09 +01:00
},
repository : {
name : 'add-to-project' ,
owner : {
2023-02-27 13:15:25 +00:00
login : 'actions' ,
},
},
2022-03-29 00:23:33 +00:00
}
mockGraphQL (
{
test : /getProject/ ,
return : {
organization : {
2022-05-19 16:16:43 +00:00
projectV2 : {
2023-02-27 13:15:25 +00:00
id : 'project-id' ,
},
},
},
2022-03-29 00:23:33 +00:00
},
{
2022-05-19 16:16:43 +00:00
test : /addProjectV2ItemById/ ,
2022-03-29 00:23:33 +00:00
return : {
2022-05-19 16:16:43 +00:00
addProjectV2ItemById : {
2022-06-27 15:01:14 +02:00
item : {
2023-02-27 13:15:25 +00:00
id : 'project-item-id' ,
},
},
},
},
2022-03-29 00:23:33 +00:00
)
await addToProject ()
2022-05-19 16:16:43 +00:00
expect ( outputs . itemId ). toEqual ( 'project-item-id' )
2022-03-29 00:23:33 +00:00
})
2022-03-23 12:34:46 +02:00
test ( 'does not add un-matching issues with a label filter without label-operator' , async () => {
2022-02-01 22:08:12 +00:00
mockGetInput ({
2022-06-30 10:48:09 +01:00
'project-url' : 'https://github.com/orgs/actions/projects/1' ,
2022-02-01 22:08:12 +00:00
'github-token' : 'gh_token' ,
2023-02-27 13:15:25 +00:00
labeled : 'bug' ,
2022-02-01 22:08:12 +00:00
})
github . context . payload = {
issue : {
number : 1 ,
2022-06-30 10:48:09 +01:00
labels : [],
// eslint-disable-next-line camelcase
2023-02-27 13:15:25 +00:00
html_url : 'https://github.com/actions/add-to-project/issues/74' ,
2022-06-30 10:48:09 +01:00
},
repository : {
name : 'add-to-project' ,
owner : {
2023-02-27 13:15:25 +00:00
login : 'actions' ,
},
},
2022-02-01 22:08:12 +00:00
}
const infoSpy = jest . spyOn ( core , 'info' )
const gqlMock = mockGraphQL ()
await addToProject ()
expect ( infoSpy ). toHaveBeenCalledWith ( `Skipping issue 1 because it does not have one of the labels: bug` )
expect ( gqlMock ). not . toHaveBeenCalled ()
})
2022-03-23 12:34:46 +02:00
test ( 'adds matching issues with labels filter with AND label-operator' , async () => {
mockGetInput ({
2022-06-30 10:48:09 +01:00
'project-url' : 'https://github.com/orgs/actions/projects/1' ,
2022-03-23 12:34:46 +02:00
'github-token' : 'gh_token' ,
labeled : 'bug, new' ,
2023-02-27 13:15:25 +00:00
'label-operator' : 'AND' ,
2022-03-23 12:34:46 +02:00
})
github . context . payload = {
issue : {
number : 1 ,
2022-06-30 10:48:09 +01:00
labels : [{ name : 'bug' }, { name : 'new' }],
// eslint-disable-next-line camelcase
2023-02-27 13:15:25 +00:00
html_url : 'https://github.com/actions/add-to-project/issues/74' ,
2022-06-30 10:48:09 +01:00
},
repository : {
name : 'add-to-project' ,
owner : {
2023-02-27 13:15:25 +00:00
login : 'actions' ,
},
},
2022-03-23 12:34:46 +02:00
}
mockGraphQL (
{
test : /getProject/ ,
return : {
organization : {
2022-05-19 16:16:43 +00:00
projectV2 : {
2023-02-27 13:15:25 +00:00
id : 'project-id' ,
},
},
},
2022-03-23 12:34:46 +02:00
},
{
2022-05-19 16:16:43 +00:00
test : /addProjectV2ItemById/ ,
2022-03-23 12:34:46 +02:00
return : {
2022-05-19 16:16:43 +00:00
addProjectV2ItemById : {
2022-06-27 15:01:14 +02:00
item : {
2023-02-27 13:15:25 +00:00
id : 'project-item-id' ,
},
},
},
},
2022-03-23 12:34:46 +02:00
)
await addToProject ()
2022-05-19 16:16:43 +00:00
expect ( outputs . itemId ). toEqual ( 'project-item-id' )
2022-03-23 12:34:46 +02:00
})
test ( 'does not add un-matching issues with labels filter with AND label-operator' , async () => {
mockGetInput ({
2022-06-30 10:48:09 +01:00
'project-url' : 'https://github.com/orgs/actions/projects/1' ,
2022-03-23 12:34:46 +02:00
'github-token' : 'gh_token' ,
labeled : 'bug, new' ,
2023-02-27 13:15:25 +00:00
'label-operator' : 'AND' ,
2022-03-23 12:34:46 +02:00
})
github . context . payload = {
issue : {
number : 1 ,
2022-06-30 10:48:09 +01:00
labels : [{ name : 'bug' }, { name : 'other' }],
// eslint-disable-next-line camelcase
2023-02-27 13:15:25 +00:00
html_url : 'https://github.com/actions/add-to-project/issues/74' ,
2022-06-30 10:48:09 +01:00
},
repository : {
name : 'add-to-project' ,
owner : {
2023-02-27 13:15:25 +00:00
login : 'actions' ,
},
},
2022-03-23 12:34:46 +02:00
}
const infoSpy = jest . spyOn ( core , 'info' )
const gqlMock = mockGraphQL ()
await addToProject ()
expect ( infoSpy ). toHaveBeenCalledWith ( `Skipping issue 1 because it doesn't match all the labels: bug, new` )
expect ( gqlMock ). not . toHaveBeenCalled ()
})
2022-03-25 20:43:58 +00:00
2022-06-16 17:50:53 +02:00
test ( 'does not add matching issues with labels filter with NOT label-operator' , async () => {
mockGetInput ({
2022-06-30 10:48:09 +01:00
'project-url' : 'https://github.com/orgs/actions/projects/1' ,
2022-06-16 17:50:53 +02:00
'github-token' : 'gh_token' ,
labeled : 'bug, new' ,
2023-02-27 13:15:25 +00:00
'label-operator' : 'NOT' ,
2022-06-16 17:50:53 +02:00
})
github . context . payload = {
issue : {
number : 1 ,
2022-06-30 10:48:09 +01:00
labels : [{ name : 'bug' }],
// eslint-disable-next-line camelcase
2023-02-27 13:15:25 +00:00
html_url : 'https://github.com/actions/add-to-project/issues/74' ,
2022-06-30 10:48:09 +01:00
},
repository : {
name : 'add-to-project' ,
owner : {
2023-02-27 13:15:25 +00:00
login : 'actions' ,
},
},
2022-06-16 17:50:53 +02:00
}
const infoSpy = jest . spyOn ( core , 'info' )
const gqlMock = mockGraphQL ()
await addToProject ()
expect ( infoSpy ). toHaveBeenCalledWith ( `Skipping issue 1 because it contains one of the labels: bug, new` )
expect ( gqlMock ). not . toHaveBeenCalled ()
})
2022-06-16 18:11:37 +02:00
test ( 'adds issues that do not have labels present in the label list with NOT label-operator' , async () => {
mockGetInput ({
2022-06-30 10:48:09 +01:00
'project-url' : 'https://github.com/orgs/actions/projects/1' ,
2022-06-16 18:11:37 +02:00
'github-token' : 'gh_token' ,
labeled : 'bug, new' ,
2023-02-27 13:15:25 +00:00
'label-operator' : 'NOT' ,
2022-06-16 18:11:37 +02:00
})
github . context . payload = {
issue : {
number : 1 ,
2022-06-30 10:48:09 +01:00
labels : [{ name : 'other' }],
// eslint-disable-next-line camelcase
2023-02-27 13:15:25 +00:00
html_url : 'https://github.com/actions/add-to-project/issues/74' ,
2022-06-30 10:48:09 +01:00
},
repository : {
name : 'add-to-project' ,
owner : {
2023-02-27 13:15:25 +00:00
login : 'actions' ,
},
},
2022-06-16 18:11:37 +02:00
}
mockGraphQL (
{
test : /getProject/ ,
return : {
organization : {
2022-06-30 13:13:58 +00:00
projectV2 : {
2023-02-27 13:15:25 +00:00
id : 'project-next-id' ,
},
},
},
2022-06-16 18:11:37 +02:00
},
{
2022-06-30 13:13:58 +00:00
test : /addProjectV2ItemById/ ,
2022-06-16 18:11:37 +02:00
return : {
2022-06-30 13:13:58 +00:00
addProjectV2ItemById : {
item : {
2023-02-27 13:15:25 +00:00
id : 'project-next-item-id' ,
},
},
},
},
2022-06-16 18:11:37 +02:00
)
await addToProject ()
expect ( outputs . itemId ). toEqual ( 'project-next-item-id' )
})
2022-03-25 00:07:54 +00:00
test ( 'adds matching issues with multiple label filters' , async () => {
mockGetInput ({
2022-06-30 10:48:09 +01:00
'project-url' : 'https://github.com/orgs/actions/projects/1' ,
2022-03-25 00:07:54 +00:00
'github-token' : 'gh_token' ,
2023-02-27 13:15:25 +00:00
labeled : 'accessibility,backend,bug' ,
2022-03-25 00:07:54 +00:00
})
github . context . payload = {
issue : {
number : 1 ,
2022-06-30 10:48:09 +01:00
labels : [{ name : 'accessibility' }, { name : 'backend' }],
// eslint-disable-next-line camelcase
2023-02-27 13:15:25 +00:00
html_url : 'https://github.com/actions/add-to-project/issues/74' ,
2022-06-30 10:48:09 +01:00
},
repository : {
name : 'add-to-project' ,
owner : {
2023-02-27 13:15:25 +00:00
login : 'actions' ,
},
},
2022-03-25 00:07:54 +00:00
}
const gqlMock = mockGraphQL (
{
test : /getProject/ ,
return : {
organization : {
2022-05-19 16:16:43 +00:00
projectV2 : {
2023-02-27 13:15:25 +00:00
id : 'project-id' ,
},
},
},
2022-03-25 00:07:54 +00:00
},
{
2022-05-19 16:16:43 +00:00
test : /addProjectV2ItemById/ ,
2022-03-25 00:07:54 +00:00
return : {
2022-05-19 16:16:43 +00:00
addProjectV2ItemById : {
2022-06-27 15:01:14 +02:00
item : {
2023-02-27 13:15:25 +00:00
id : 'project-item-id' ,
},
},
},
},
2022-03-25 00:07:54 +00:00
)
const infoSpy = jest . spyOn ( core , 'info' )
await addToProject ()
expect ( gqlMock ). toHaveBeenCalled ()
2022-06-30 15:28:57 +01:00
expect ( infoSpy ). toHaveBeenCalledWith ( 'Creating project item' )
// We shouldn't have any logs relating to the issue being skipped
expect ( infoSpy . mock . calls . length ). toEqual ( 1 )
2022-05-19 16:16:43 +00:00
expect ( outputs . itemId ). toEqual ( 'project-item-id' )
2022-03-25 00:07:54 +00:00
})
test ( 'does not add un-matching issues with multiple label filters' , async () => {
mockGetInput ({
2022-06-30 10:48:09 +01:00
'project-url' : 'https://github.com/orgs/actions/projects/1' ,
2022-03-25 00:07:54 +00:00
'github-token' : 'gh_token' ,
2023-02-27 13:15:25 +00:00
labeled : 'accessibility, backend, bug' ,
2022-03-25 00:07:54 +00:00
})
github . context . payload = {
issue : {
number : 1 ,
2022-06-30 10:48:09 +01:00
labels : [{ name : 'data' }, { name : 'frontend' }, { name : 'improvement' }],
// eslint-disable-next-line camelcase
2023-02-27 13:15:25 +00:00
html_url : 'https://github.com/actions/add-to-project/issues/74' ,
2022-06-30 10:48:09 +01:00
},
repository : {
name : 'add-to-project' ,
owner : {
2023-02-27 13:15:25 +00:00
login : 'actions' ,
},
},
2022-03-25 00:07:54 +00:00
}
const infoSpy = jest . spyOn ( core , 'info' )
const gqlMock = mockGraphQL ()
await addToProject ()
expect ( infoSpy ). toHaveBeenCalledWith (
2023-02-27 13:15:25 +00:00
`Skipping issue 1 because it does not have one of the labels: accessibility, backend, bug` ,
2022-03-25 00:07:54 +00:00
)
expect ( gqlMock ). not . toHaveBeenCalled ()
})
2022-03-29 00:23:33 +00:00
test ( 'handles spaces and extra commas gracefully in label filter input' , async () => {
mockGetInput ({
2022-06-30 10:48:09 +01:00
'project-url' : 'https://github.com/orgs/actions/projects/1' ,
2022-03-29 00:23:33 +00:00
'github-token' : 'gh_token' ,
2023-02-27 13:15:25 +00:00
labeled : 'accessibility , backend ,, . , bug' ,
2022-03-29 00:23:33 +00:00
})
github . context . payload = {
issue : {
number : 1 ,
labels : [{ name : 'accessibility' }, { name : 'backend' }, { name : 'bug' }],
2022-06-30 10:48:09 +01:00
'label-operator' : 'AND' ,
// eslint-disable-next-line camelcase
2023-02-27 13:15:25 +00:00
html_url : 'https://github.com/actions/add-to-project/issues/74' ,
2022-06-30 10:48:09 +01:00
},
repository : {
name : 'add-to-project' ,
owner : {
2023-02-27 13:15:25 +00:00
login : 'actions' ,
},
},
2022-03-29 00:23:33 +00:00
}
const gqlMock = mockGraphQL (
{
test : /getProject/ ,
return : {
organization : {
2022-05-19 16:16:43 +00:00
projectV2 : {
2023-02-27 13:15:25 +00:00
id : 'project-id' ,
},
},
},
2022-03-29 00:23:33 +00:00
},
{
2022-05-19 16:16:43 +00:00
test : /addProjectV2ItemById/ ,
2022-03-29 00:23:33 +00:00
return : {
2022-05-19 16:16:43 +00:00
addProjectV2ItemById : {
2022-06-27 15:01:14 +02:00
item : {
2023-02-27 13:15:25 +00:00
id : 'project-item-id' ,
},
},
},
},
2022-03-29 00:23:33 +00:00
)
const infoSpy = jest . spyOn ( core , 'info' )
await addToProject ()
expect ( gqlMock ). toHaveBeenCalled ()
2022-06-30 15:28:57 +01:00
expect ( infoSpy ). toHaveBeenCalledWith ( 'Creating project item' )
// We shouldn't have any logs relating to the issue being skipped
expect ( infoSpy . mock . calls . length ). toEqual ( 1 )
2022-05-19 16:16:43 +00:00
expect ( outputs . itemId ). toEqual ( 'project-item-id' )
2022-03-29 00:23:33 +00:00
})
2022-03-25 00:07:54 +00:00
test ( `throws an error when url isn't a valid project url` , async () => {
mockGetInput ({
'project-url' : 'https://github.com/orgs/github/repositories' ,
2023-02-27 13:15:25 +00:00
'github-token' : 'gh_token' ,
2022-03-25 00:07:54 +00:00
})
github . context . payload = {
issue : {
number : 1 ,
2022-06-30 10:48:09 +01:00
labels : [],
// eslint-disable-next-line camelcase
2023-02-27 13:15:25 +00:00
html_url : 'https://github.com/actions/add-to-project/issues/74' ,
2022-06-30 10:48:09 +01:00
},
repository : {
name : 'add-to-project' ,
owner : {
2023-02-27 13:15:25 +00:00
login : 'actions' ,
},
},
2022-03-25 00:07:54 +00:00
}
const infoSpy = jest . spyOn ( core , 'info' )
const gqlMock = mockGraphQL ()
await expect ( addToProject ()). rejects . toThrow (
2023-03-30 21:35:55 +04:00
'Invalid project URL: https://github.com/orgs/github/repositories. Project URL should match the format <Github server domain name>/<orgs-or-users>/<ownerName>/projects/<projectNumber>' ,
2022-03-25 00:07:54 +00:00
)
expect ( infoSpy ). not . toHaveBeenCalled ()
expect ( gqlMock ). not . toHaveBeenCalled ()
})
2022-03-25 20:43:58 +00:00
test ( `throws an error when url isn't under the github.com domain` , async () => {
mockGetInput ({
'project-url' : 'https://notgithub.com/orgs/github/projects/1' ,
2023-02-27 13:15:25 +00:00
'github-token' : 'gh_token' ,
2022-03-25 20:43:58 +00:00
})
2022-03-25 00:07:54 +00:00
2022-03-25 20:43:58 +00:00
github . context . payload = {
issue : {
number : 1 ,
2022-06-30 10:48:09 +01:00
labels : [],
// eslint-disable-next-line camelcase
2023-02-27 13:15:25 +00:00
html_url : 'https://github.com/actions/add-to-project/issues/74' ,
2022-06-30 10:48:09 +01:00
},
repository : {
name : 'add-to-project' ,
owner : {
2023-02-27 13:15:25 +00:00
login : 'actions' ,
},
},
2022-03-25 00:07:54 +00:00
}
2022-03-25 20:43:58 +00:00
const infoSpy = jest . spyOn ( core , 'info' )
const gqlMock = mockGraphQL ()
await expect ( addToProject ()). rejects . toThrow (
2023-02-27 13:15:25 +00:00
'https://notgithub.com/orgs/github/projects/1. Project URL should match the format https://github.com/<orgs-or-users>/<ownerName>/projects/<projectNumber>' ,
2022-03-25 20:43:58 +00:00
)
expect ( infoSpy ). not . toHaveBeenCalled ()
expect ( gqlMock ). not . toHaveBeenCalled ()
})
2022-03-25 21:32:04 +00:00
test ( 'constructs the correct graphQL query given an organization owner' , async () => {
mockGetInput ({
2022-06-30 10:48:09 +01:00
'project-url' : 'https://github.com/orgs/actions/projects/1' ,
2022-03-25 21:32:04 +00:00
'github-token' : 'gh_token' ,
2023-02-27 13:15:25 +00:00
labeled : 'bug, new' ,
2022-03-25 21:32:04 +00:00
})
github . context . payload = {
issue : {
number : 1 ,
2022-06-30 10:48:09 +01:00
labels : [{ name : 'bug' }],
// eslint-disable-next-line camelcase
2023-02-27 13:15:25 +00:00
html_url : 'https://github.com/actions/add-to-project/issues/74' ,
2022-06-30 10:48:09 +01:00
},
repository : {
name : 'add-to-project' ,
owner : {
2023-02-27 13:15:25 +00:00
login : 'actions' ,
},
},
2022-03-25 21:32:04 +00:00
}
const gqlMock = mockGraphQL (
{
test : /getProject/ ,
return : {
organization : {
2022-05-19 16:16:43 +00:00
projectV2 : {
2023-02-27 13:15:25 +00:00
id : 'project-id' ,
},
},
},
2022-03-25 21:32:04 +00:00
},
{
2022-05-19 16:16:43 +00:00
test : /addProjectV2ItemById/ ,
2022-03-25 21:32:04 +00:00
return : {
2022-05-19 16:16:43 +00:00
addProjectV2ItemById : {
2022-06-27 15:01:14 +02:00
item : {
2023-02-27 13:15:25 +00:00
id : 'project-item-id' ,
},
},
},
},
2022-03-25 21:32:04 +00:00
)
await addToProject ()
2022-06-30 10:48:09 +01:00
expect ( gqlMock ). toHaveBeenNthCalledWith ( 1 , expect . stringContaining ( 'organization(login: $projectOwnerName)' ), {
projectOwnerName : 'actions' ,
2023-02-27 13:15:25 +00:00
projectNumber : 1 ,
2022-03-25 21:32:04 +00:00
})
})
test ( 'constructs the correct graphQL query given a user owner' , async () => {
mockGetInput ({
'project-url' : 'https://github.com/users/monalisa/projects/1' ,
'github-token' : 'gh_token' ,
2023-02-27 13:15:25 +00:00
labeled : 'bug, new' ,
2022-03-25 21:32:04 +00:00
})
github . context . payload = {
issue : {
number : 1 ,
2022-06-30 10:48:09 +01:00
labels : [{ name : 'bug' }],
// eslint-disable-next-line camelcase
2023-02-27 13:15:25 +00:00
html_url : 'https://github.com/monalisa/add-to-project/issues/74' ,
2022-06-30 10:48:09 +01:00
},
repository : {
name : 'add-to-project' ,
owner : {
2023-02-27 13:15:25 +00:00
login : 'monalisa' ,
},
},
2022-03-25 21:32:04 +00:00
}
const gqlMock = mockGraphQL (
{
test : /getProject/ ,
return : {
organization : {
2022-05-19 16:16:43 +00:00
projectV2 : {
2023-02-27 13:15:25 +00:00
id : 'project-id' ,
},
},
},
2022-03-25 21:32:04 +00:00
},
{
2022-05-19 16:16:43 +00:00
test : /addProjectV2ItemById/ ,
2022-03-25 21:32:04 +00:00
return : {
2022-05-19 16:16:43 +00:00
addProjectV2ItemById : {
2022-06-27 15:01:14 +02:00
item : {
2023-02-27 13:15:25 +00:00
id : 'project-item-id' ,
},
},
},
},
2022-03-25 21:32:04 +00:00
)
await addToProject ()
2022-06-30 10:48:09 +01:00
expect ( gqlMock ). toHaveBeenNthCalledWith ( 1 , expect . stringContaining ( 'user(login: $projectOwnerName)' ), {
projectOwnerName : 'monalisa' ,
2023-02-27 13:15:25 +00:00
projectNumber : 1 ,
2022-03-25 21:32:04 +00:00
})
})
2022-06-22 15:33:54 +02:00
test ( 'compares labels case-insensitively' , async () => {
mockGetInput ({
2022-06-30 10:48:09 +01:00
'project-url' : 'https://github.com/orgs/actions/projects/1' ,
2022-06-22 15:33:54 +02:00
'github-token' : 'gh_token' ,
labeled : 'FOO, Bar, baz' ,
2023-02-27 13:15:25 +00:00
'label-operator' : 'AND' ,
2022-06-22 15:33:54 +02:00
})
github . context . payload = {
issue : {
number : 1 ,
2022-06-30 10:48:09 +01:00
labels : [{ name : 'foo' }, { name : 'BAR' }, { name : 'baz' }],
// eslint-disable-next-line camelcase
2023-02-27 13:15:25 +00:00
html_url : 'https://github.com/actions/add-to-project/issues/74' ,
2022-06-30 10:48:09 +01:00
},
repository : {
name : 'add-to-project' ,
owner : {
2023-02-27 13:15:25 +00:00
login : 'actions' ,
},
},
2022-06-22 15:33:54 +02:00
}
mockGraphQL (
{
test : /getProject/ ,
return : {
organization : {
2022-06-30 13:13:58 +00:00
projectV2 : {
2023-02-27 13:15:25 +00:00
id : 'project-next-id' ,
},
},
},
2022-06-22 15:33:54 +02:00
},
{
2022-06-30 13:13:58 +00:00
test : /addProjectV2ItemById/ ,
2022-06-22 15:33:54 +02:00
return : {
2022-06-30 13:13:58 +00:00
addProjectV2ItemById : {
item : {
2023-02-27 13:15:25 +00:00
id : 'project-next-item-id' ,
},
},
},
},
2022-06-22 15:33:54 +02:00
)
await addToProject ()
expect ( outputs . itemId ). toEqual ( 'project-next-item-id' )
})
2022-02-01 22:08:12 +00:00
})
2022-03-29 00:23:33 +00:00
describe ( 'mustGetOwnerTypeQuery' , () => {
test ( 'returns organization for orgs ownerType' , async () => {
const ownerTypeQuery = mustGetOwnerTypeQuery ( 'orgs' )
expect ( ownerTypeQuery ). toEqual ( 'organization' )
})
test ( 'returns user for users ownerType' , async () => {
const ownerTypeQuery = mustGetOwnerTypeQuery ( 'users' )
expect ( ownerTypeQuery ). toEqual ( 'user' )
})
test ( 'throws an error when an unsupported ownerType is set' , async () => {
expect (() => {
mustGetOwnerTypeQuery ( 'unknown' )
}). toThrow ( `Unsupported ownerType: unknown. Must be one of 'orgs' or 'users'` )
})
})
2022-02-01 22:08:12 +00:00
function mockGetInput ( mocks : Record < string , string >) : jest . SpyInstance {
const mock = ( key : string ) => mocks [ key ] ?? ''
return jest . spyOn ( core , 'getInput' ). mockImplementation ( mock )
}
function mockSetOutput () : Record < string , string > {
const output : Record < string , string > = {}
jest . spyOn ( core , 'setOutput' ). mockImplementation (( key , value ) => ( output [ key ] = value ))
return output
}
function mockGraphQL (... mocks : { test : RegExp ; return : unknown }[]) : jest . Mock {
const mock = jest . fn (). mockImplementation (( query : string ) => {
const match = mocks . find ( m => m . test . test ( query ))
if ( match ) {
return match . return
}
throw new Error ( `Unexpected GraphQL query: ${ query } ` )
})
jest . spyOn ( github , 'getOctokit' ). mockImplementation (() => {
return {
2023-02-27 13:15:25 +00:00
graphql : mock ,
2022-02-01 22:08:12 +00:00
} as unknown as ReturnType < typeof github.getOctokit >
})
return mock
}