diff --git a/__tests__/label/label.test.ts b/__tests__/label/label.test.ts index 01e04395..32383b7d 100644 --- a/__tests__/label/label.test.ts +++ b/__tests__/label/label.test.ts @@ -89,6 +89,33 @@ describe('protected labels', () => { }, ) + it('names the first protected label when several are requested', async () => { + issueCommentEvent.comment.body = '/label hold lgtm' + const commentContext = new utils.MockContext(issueCommentEvent) + + const observePost = new utils.ObserveRequest() + server.use( + http.post( + `${utils.api}/repos/Codertocat/Hello-World/issues/1/labels`, + utils.mockResponse(200, null, observePost), + ), + utils.repoHasLabels(['good-first-issue', 'help-wanted', 'documentation', 'tide/merge-method-squash']), + http.get( + `${utils.api}/repos/Codertocat/Hello-World/contents/.prowlabels.yaml`, + utils.mockResponse(200, withProtected), + ), + ...utils.noOrgOrRepoConfigExcept('.prowlabels.yaml'), + ) + + const setFailed = vi.spyOn(core, 'setFailed').mockImplementation(() => {}) + await handleIssueComment(commentContext) + await expect(observePost.notCalled()).resolves.toBe('not called') + expect(setFailed).toHaveBeenCalledTimes(1) + expect(setFailed).toHaveBeenCalledWith( + expect.stringContaining('label: hold is managed by its own command and cannot be changed with /label'), + ) + }) + it.each([ ['/remove-label hold', 'hold'], ['/remove-label LGTM', 'lgtm'], diff --git a/__tests__/label/lifecycle.test.ts b/__tests__/label/lifecycle.test.ts index 40a69be7..685aa649 100644 --- a/__tests__/label/lifecycle.test.ts +++ b/__tests__/label/lifecycle.test.ts @@ -86,6 +86,18 @@ describe('built-in lifecycle, stage and status commands', () => { expect(setFailed).not.toHaveBeenCalled() }) + it.each([ + ['/stage', 'beta', 'stage/alpha', 'stage%2Falpha', 'stage/beta'], + ['/status', 'in-review', 'status/in-progress', 'status%2Fin-progress', 'status/in-review'], + ])('%s %s replaces the existing %s', async (command, value, current, encoded, label) => { + const mutations = serveIssueAndRecordMutations([current]) + + const setFailed = await run(command, `${command} ${value}`) + + expect(mutations).toEqual([`DELETE ${encoded}`, `POST ${label}`]) + expect(setFailed).not.toHaveBeenCalled() + }) + it('/remove-lifecycle stale removes lifecycle/stale', async () => { const mutations = serveIssueAndRecordMutations(['lifecycle/stale']) @@ -95,6 +107,15 @@ describe('built-in lifecycle, stage and status commands', () => { expect(setFailed).not.toHaveBeenCalled() }) + it('/remove-lifecycle with two values removes both when both are on the issue', async () => { + const mutations = serveIssueAndRecordMutations(['lifecycle/stale', 'lifecycle/frozen']) + + const setFailed = await run('/lifecycle', '/remove-lifecycle stale frozen') + + expect(mutations).toEqual(['DELETE lifecycle%2Fstale', 'DELETE lifecycle%2Ffrozen']) + expect(setFailed).not.toHaveBeenCalled() + }) + it('/lifecycle fails for a value outside the defaults', async () => { const mutations = serveIssueAndRecordMutations([]) @@ -209,5 +230,36 @@ describe('built-in lifecycle, stage and status commands', () => { expect(mutations).toEqual(['POST lifecycle/frozen']) expect(setFailed).not.toHaveBeenCalled() }) + + describe('with a mixed-case yaml value', () => { + const mixedCase = yamlFile('lifecycle:\n - Frozen\n') + + it('/lifecycle matches the comment case-insensitively and applies the yaml casing', async () => { + const mutations = serveIssueAndRecordMutations([], mixedCase) + + const setFailed = await run('/lifecycle', '/lifecycle frozen') + + expect(mutations).toEqual(['POST lifecycle/Frozen']) + expect(setFailed).not.toHaveBeenCalled() + }) + + it('/lifecycle keeps a lower-case label on the issue that names the same value', async () => { + const mutations = serveIssueAndRecordMutations(['lifecycle/frozen'], mixedCase) + + const setFailed = await run('/lifecycle', '/lifecycle frozen') + + expect(mutations).toEqual(['POST lifecycle/Frozen']) + expect(setFailed).not.toHaveBeenCalled() + }) + + it('/remove-lifecycle removes a lower-case label on the issue that names the same value', async () => { + const mutations = serveIssueAndRecordMutations(['lifecycle/frozen'], mixedCase) + + const setFailed = await run('/lifecycle', '/remove-lifecycle frozen') + + expect(mutations).toEqual(['DELETE lifecycle%2Ffrozen']) + expect(setFailed).not.toHaveBeenCalled() + }) + }) }) })