Files
labeler/__tests__/main.test.ts
Mark Ridgwell 327d35fdca Added ability to pass in an optional PR number as a parameter (#349)
* Adding pr-number as an optional parameter

* Updated README

* Tests on the pr-number parameter

* Added missing | to table

* re-built script

* Adding support for multiple pr-numbers

* excluded .idea

* Updated readme to reflect that there might be more than one PR

* Additional warning

* Removed unused

* Reformatted and re-built

* Corrected message

* Removed required check

* Added (s) to pull request numbers in the description

Co-authored-by: MaksimZhukov <46996400+MaksimZhukov@users.noreply.github.com>

* Reworded PR-number parameter description

Co-authored-by: MaksimZhukov <46996400+MaksimZhukov@users.noreply.github.com>

* adding getMultilineInput into the tests

* Fixing tests for single pr

* Fixing tests for multiple prs

* Updated README.md to make it more obvious that it can take a list of PRs

* Added example that labels PR's 1-3

* Handled no pull requests better (from code review)

* Handled no pull requests better (from code review)

* Handled missing pull request better (from code review)

* Back out suggested change as it broke the tests

* Rebuilt dist

* Update src/labeler.ts

Co-authored-by: MaksimZhukov <46996400+MaksimZhukov@users.noreply.github.com>

* Added Emphasis to the note

Co-authored-by: MaksimZhukov <46996400+MaksimZhukov@users.noreply.github.com>

* Changed mockInput for pr-number to be string[]

---------

Co-authored-by: MaksimZhukov <46996400+MaksimZhukov@users.noreply.github.com>
2023-07-06 17:10:50 +02:00

310 lines
8.5 KiB
TypeScript

import {run} from '../src/labeler';
import * as github from '@actions/github';
import * as core from '@actions/core';
const fs = jest.requireActual('fs');
jest.mock('@actions/core');
jest.mock('@actions/github');
const gh = github.getOctokit('_');
const setLabelsMock = jest.spyOn(gh.rest.issues, 'setLabels');
const reposMock = jest.spyOn(gh.rest.repos, 'getContent');
const paginateMock = jest.spyOn(gh, 'paginate');
const getPullMock = jest.spyOn(gh.rest.pulls, 'get');
const coreWarningMock = jest.spyOn(core, 'warning');
const setOutputSpy = jest.spyOn(core, 'setOutput');
const yamlFixtures = {
'only_pdfs.yml': fs.readFileSync('__tests__/fixtures/only_pdfs.yml')
};
const configureInput = (
mockInput: Partial<{
'repo-token': string;
'configuration-path': string;
'sync-labels': boolean;
dot: boolean;
'pr-number': string[];
}>
) => {
jest
.spyOn(core, 'getInput')
.mockImplementation((name: string, ...opts) => mockInput[name]);
jest
.spyOn(core, 'getMultilineInput')
.mockImplementation((name: string, ...opts) => mockInput[name]);
jest
.spyOn(core, 'getBooleanInput')
.mockImplementation((name: string, ...opts) => mockInput[name]);
};
afterAll(() => jest.restoreAllMocks());
describe('run', () => {
it('(with dot: false) adds labels to PRs that match our glob patterns', async () => {
configureInput({});
usingLabelerConfigYaml('only_pdfs.yml');
mockGitHubResponseChangedFiles('foo.pdf');
getPullMock.mockResolvedValue(<any>{
data: {
labels: []
}
});
await run();
expect(setLabelsMock).toHaveBeenCalledTimes(1);
expect(setLabelsMock).toHaveBeenCalledWith({
owner: 'monalisa',
repo: 'helloworld',
issue_number: 123,
labels: ['touched-a-pdf-file']
});
expect(setOutputSpy).toHaveBeenCalledWith(
'new-labels',
'touched-a-pdf-file'
);
expect(setOutputSpy).toHaveBeenCalledWith(
'all-labels',
'touched-a-pdf-file'
);
});
it('(with dot: true) adds labels to PRs that match our glob patterns', async () => {
configureInput({dot: true});
usingLabelerConfigYaml('only_pdfs.yml');
mockGitHubResponseChangedFiles('.foo.pdf');
getPullMock.mockResolvedValue(<any>{
data: {
labels: []
}
});
await run();
expect(setLabelsMock).toHaveBeenCalledTimes(1);
expect(setLabelsMock).toHaveBeenCalledWith({
owner: 'monalisa',
repo: 'helloworld',
issue_number: 123,
labels: ['touched-a-pdf-file']
});
expect(setOutputSpy).toHaveBeenCalledWith(
'new-labels',
'touched-a-pdf-file'
);
expect(setOutputSpy).toHaveBeenCalledWith(
'all-labels',
'touched-a-pdf-file'
);
});
it('(with dot: false) does not add labels to PRs that do not match our glob patterns', async () => {
configureInput({});
usingLabelerConfigYaml('only_pdfs.yml');
mockGitHubResponseChangedFiles('.foo.pdf');
getPullMock.mockResolvedValue(<any>{
data: {
labels: []
}
});
await run();
expect(setLabelsMock).toHaveBeenCalledTimes(0);
expect(setOutputSpy).toHaveBeenCalledWith('new-labels', '');
expect(setOutputSpy).toHaveBeenCalledWith('all-labels', '');
});
it('(with dot: true) does not add labels to PRs that do not match our glob patterns', async () => {
configureInput({dot: true});
usingLabelerConfigYaml('only_pdfs.yml');
mockGitHubResponseChangedFiles('foo.txt');
await run();
expect(setLabelsMock).toHaveBeenCalledTimes(0);
});
it('(with sync-labels: true) it deletes preexisting PR labels that no longer match the glob pattern', async () => {
configureInput({
'repo-token': 'foo',
'configuration-path': 'bar',
'sync-labels': true
});
usingLabelerConfigYaml('only_pdfs.yml');
mockGitHubResponseChangedFiles('foo.txt');
getPullMock.mockResolvedValue(<any>{
data: {
labels: [{name: 'touched-a-pdf-file'}, {name: 'manually-added'}]
}
});
await run();
expect(setLabelsMock).toHaveBeenCalledTimes(1);
expect(setLabelsMock).toHaveBeenCalledWith({
owner: 'monalisa',
repo: 'helloworld',
issue_number: 123,
labels: ['manually-added']
});
expect(setOutputSpy).toHaveBeenCalledWith('new-labels', '');
expect(setOutputSpy).toHaveBeenCalledWith('all-labels', 'manually-added');
});
it('(with sync-labels: false) it issues no delete calls even when there are preexisting PR labels that no longer match the glob pattern', async () => {
configureInput({
'repo-token': 'foo',
'configuration-path': 'bar',
'sync-labels': false
});
usingLabelerConfigYaml('only_pdfs.yml');
mockGitHubResponseChangedFiles('foo.txt');
getPullMock.mockResolvedValue(<any>{
data: {
labels: [{name: 'touched-a-pdf-file'}, {name: 'manually-added'}]
}
});
await run();
expect(setLabelsMock).toHaveBeenCalledTimes(0);
expect(setOutputSpy).toHaveBeenCalledWith('new-labels', '');
expect(setOutputSpy).toHaveBeenCalledWith(
'all-labels',
'touched-a-pdf-file,manually-added'
);
});
it('(with sync-labels: false) it only logs the excess labels', async () => {
configureInput({
'repo-token': 'foo',
'configuration-path': 'bar',
'sync-labels': false
});
usingLabelerConfigYaml('only_pdfs.yml');
mockGitHubResponseChangedFiles('foo.pdf');
const existingLabels = Array.from({length: 100}).map((_, idx) => ({
name: `existing-label-${idx}`
}));
getPullMock.mockResolvedValue(<any>{
data: {
labels: existingLabels
}
});
await run();
expect(setLabelsMock).toHaveBeenCalledTimes(0);
expect(coreWarningMock).toHaveBeenCalledTimes(1);
expect(coreWarningMock).toHaveBeenCalledWith(
'Maximum of 100 labels allowed. Excess labels: touched-a-pdf-file',
{title: 'Label limit for a PR exceeded'}
);
const allLabels: string = existingLabels.map(i => i.name).join(',');
expect(setOutputSpy).toHaveBeenCalledWith('new-labels', '');
expect(setOutputSpy).toHaveBeenCalledWith('all-labels', allLabels);
});
it('(with pr-number: array of one item, uses the PR number specified in the parameters', async () => {
configureInput({
'repo-token': 'foo',
'configuration-path': 'bar',
'pr-number': ['104']
});
usingLabelerConfigYaml('only_pdfs.yml');
mockGitHubResponseChangedFiles('foo.pdf');
getPullMock.mockResolvedValue(<any>{
data: {
labels: [{name: 'manually-added'}]
}
});
await run();
expect(setLabelsMock).toHaveBeenCalledTimes(1);
expect(setLabelsMock).toHaveBeenCalledWith({
owner: 'monalisa',
repo: 'helloworld',
issue_number: 104,
labels: ['manually-added', 'touched-a-pdf-file']
});
expect(setOutputSpy).toHaveBeenCalledWith(
'new-labels',
'touched-a-pdf-file'
);
expect(setOutputSpy).toHaveBeenCalledWith(
'all-labels',
'manually-added,touched-a-pdf-file'
);
});
it('(with pr-number: array of two items, uses the PR number specified in the parameters', async () => {
configureInput({
'repo-token': 'foo',
'configuration-path': 'bar',
'pr-number': ['104', '150']
});
usingLabelerConfigYaml('only_pdfs.yml');
mockGitHubResponseChangedFiles('foo.pdf');
getPullMock.mockResolvedValueOnce(<any>{
data: {
labels: [{name: 'manually-added'}]
}
});
getPullMock.mockResolvedValueOnce(<any>{
data: {
labels: []
}
});
await run();
expect(setLabelsMock).toHaveBeenCalledTimes(2);
expect(setLabelsMock).toHaveBeenCalledWith({
owner: 'monalisa',
repo: 'helloworld',
issue_number: 104,
labels: ['manually-added', 'touched-a-pdf-file']
});
expect(setLabelsMock).toHaveBeenCalledWith({
owner: 'monalisa',
repo: 'helloworld',
issue_number: 150,
labels: ['touched-a-pdf-file']
});
expect(setOutputSpy).toHaveBeenCalledWith(
'new-labels',
'touched-a-pdf-file'
);
expect(setOutputSpy).toHaveBeenCalledWith(
'all-labels',
'manually-added,touched-a-pdf-file'
);
});
});
function usingLabelerConfigYaml(fixtureName: keyof typeof yamlFixtures): void {
reposMock.mockResolvedValue(<any>{
data: {content: yamlFixtures[fixtureName], encoding: 'utf8'}
});
}
function mockGitHubResponseChangedFiles(...files: string[]): void {
const returnValue = files.map(f => ({filename: f}));
paginateMock.mockReturnValue(<any>returnValue);
}