Skip to content

Commit

Permalink
fix(antora-action): Filter files analyze from status (#132)
Browse files Browse the repository at this point in the history
* Adding enum state to filter files touched in PR to run validation step
* Adding unit test on this functional code
  • Loading branch information
benjaminParisel authored Jun 12, 2024
1 parent 9ff741e commit f99e8f1
Show file tree
Hide file tree
Showing 10 changed files with 6,358 additions and 3,092 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import * as githubUtils from "../src/github-utils";
import { FILE_STATE } from "../src/github-utils";
import { GitHub } from "@actions/github/lib/utils";
import * as core from "@actions/core";
import * as github from "@actions/github";

jest.mock("@actions/github", () => ({
context: {
payload: {
pull_request: {
number: 1,
},
},
repo: {
owner: "owner",
repo: "repo",
},
},
getOctokit: jest.fn(),
}));

describe("github-utils", () => {
let octokit: InstanceType<typeof GitHub>;

beforeEach(async () => {
jest.clearAllMocks();
jest.spyOn(core, "error").mockImplementation(jest.fn());
jest.spyOn(core, "warning").mockImplementation(jest.fn());
jest.spyOn(core, "info").mockImplementation(jest.fn());
jest.spyOn(core, "debug").mockImplementation(jest.fn());
jest.spyOn(core, "setFailed").mockImplementation(jest.fn());

octokit = new GitHub({ auth: "fake-token" });

// Now, whenever github.context.payload.pull_request.number is accessed in your tests, it will return the mock number.
});

describe("getFilesFromPR", () => {
it("should return the files from the PR when no filter is given", async () => {
github.context!.payload!.pull_request!.number = 2;
const mockData = {
data: [
{ filename: "file1.ts", status: "modified" },
{ filename: "file2.ts", status: "added" },
{ filename: "file3.ts", status: "removed" },
],
};

(octokit.rest.pulls.listFiles as unknown as jest.Mock) = jest
.fn()
.mockResolvedValue(mockData);

const files: string[] = await githubUtils.getFilesFromPR(octokit);

expect(files).toEqual(["file1.ts", "file2.ts", "file3.ts"]);
expect(octokit.rest.pulls.listFiles).toHaveBeenCalled();
});

it("should filter the files based on the provided states", async () => {
const mockData = {
data: [
{ filename: "file1.ts", status: FILE_STATE.MODIFIED },
{ filename: "file2.ts", status: FILE_STATE.ADDED },
{ filename: "file3.ts", status: FILE_STATE.REMOVED },
],
};

(octokit.rest.pulls.listFiles as unknown as jest.Mock) = jest
.fn()
.mockResolvedValue(mockData);

const files = await githubUtils.getFilesFromPR(octokit, [
FILE_STATE.MODIFIED,
FILE_STATE.ADDED,
]);

expect(files).toEqual(["file1.ts", "file2.ts"]);
expect(octokit.rest.pulls.listFiles).toHaveBeenCalled();
});

it("should failed if prNumber is not set", async () => {
//Override the github context
//@ts-ignore
github.context.payload.pull_request.number = undefined;

const files: string[] = await githubUtils.getFilesFromPR(octokit, [
FILE_STATE.MODIFIED,
FILE_STATE.ADDED,
]);
expect(core.setFailed).toHaveBeenCalled();
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { GitHub } from "@actions/github/lib/utils";
import { AttributesCheckingStep } from "../../src/steps/AttributesCheckingStep";
import { getFileContent } from "../../src/github-utils";
import { Status } from "../../src/validation";
import * as core from "@actions/core";

jest.mock("../../src/github-utils", () => ({
getFileContent: jest.fn(),
}));

describe("AttributesCheckingStep", () => {
beforeEach(() => {
jest.spyOn(core, "debug").mockImplementation(jest.fn());
});

it("should validate attributes correctly", async () => {
const mockOctokit = {} as InstanceType<typeof GitHub>;
const files = ["modules/test/pages/test.adoc"];
const extensionsToCheck = ["adoc"];
const attributesToCheck = [":page-aliases:"];

(getFileContent as jest.Mock).mockImplementation(
() => ":page-aliases: test"
);

const attributesCheckingStep = new AttributesCheckingStep(
files,
extensionsToCheck,
attributesToCheck
);

const result = await attributesCheckingStep.validate(mockOctokit);

expect(result).toEqual({
status: Status.SUCCESS,
results: [],
});
});

it("should return error status when attributes are missing and write comment", async () => {
const mockOctokit = {} as InstanceType<typeof GitHub>;
const files = ["modules/test/pages/test.adoc"];
const extensionsToCheck = ["adoc"];
const attributesToCheck = [":description:"];

(getFileContent as jest.Mock).mockImplementation(
() => ":page-aliases: test"
);

const attributesCheckingStep = new AttributesCheckingStep(
files,
extensionsToCheck,
attributesToCheck
);

const result = await attributesCheckingStep.validate(mockOctokit);
const commentBody = attributesCheckingStep.formatCommentBody();

expect(result).toEqual({
status: Status.ERROR,
results: [
{
file: "modules/test/pages/test.adoc",
details: ":description:",
},
],
});

expect(commentBody).toEqual(
"## :pause_button: Attributes validation \n" +
"Some attributes are missing in the following files:\n" +
"- [ ] **:description:** are missing in **modules/test/pages/test.adoc** \n"
);
});

it("should comment nothing when the attribute check step is valid", async () => {
const mockOctokit = {} as InstanceType<typeof GitHub>;
const files = ["modules/test/pages/test.adoc"];
const extensionsToCheck = ["adoc"];
const attributesToCheck = [":description:"];

(getFileContent as jest.Mock).mockImplementation(
() => ":description: test"
);

const attributesCheckingStep = new AttributesCheckingStep(
files,
extensionsToCheck,
attributesToCheck
);

await attributesCheckingStep.validate(mockOctokit);
const commentBody = attributesCheckingStep.formatCommentBody();

expect(commentBody).toEqual("");
expect(core.debug).toHaveBeenCalled();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { GitHub } from "@actions/github/lib/utils";
import { ForbiddenPatternStep } from "../../src/steps/ForbiddenPatternStep";
import { getFileContent } from "../../src/github-utils";
import { Status } from "../../src/validation";
import * as core from "@actions/core";

jest.mock("../../src/github-utils", () => ({
getFileContent: jest.fn(),
}));

describe("ForbiddenPatternStep", () => {
beforeEach(() => {
jest.spyOn(core, "debug").mockImplementation(jest.fn());
});

it("should validate when content don't have forbiddenPattern", async () => {
const mockOctokit = {} as InstanceType<typeof GitHub>;
const files = ["modules/test/pages/test.adoc"];
const extensionsToCheck = ["adoc"];
const patternChecking = ["http://"];

(getFileContent as jest.Mock).mockImplementation(
() => "content without forbiddenPattern"
);

const forbiddenPatternStep = new ForbiddenPatternStep(
files,
extensionsToCheck,
patternChecking
);

const result = await forbiddenPatternStep.validate(mockOctokit);

expect(result).toEqual({
status: Status.SUCCESS,
results: [],
});
});

it("should return error status when forbidden patterns are found", async () => {
const mockOctokit = {} as InstanceType<typeof GitHub>;
const files = ["modules/test/pages/test.adoc"];
const extensionsToCheck = ["adoc"];
const patternChecking = ["http://test.com", "xref::"];

(getFileContent as jest.Mock).mockImplementation(
() => "You can check this url http://test.com"
);

const forbiddenPatternStep = new ForbiddenPatternStep(
files,
extensionsToCheck,
patternChecking
);

const result = await forbiddenPatternStep.validate(mockOctokit);
const commentBody = forbiddenPatternStep.formatCommentBody();

expect(result).toEqual({
status: Status.ERROR,
results: [
{
file: "modules/test/pages/test.adoc",
details: "http://test.com",
},
],
});
expect(commentBody).toEqual(
"## :no_entry: Forbidden pattern validation \n" +
"Some patterns are forbidden in the following files:\n" +
"- [ ] Update **http://test.com** syntax from **modules/test/pages/test.adoc** \n"
);
});
});
Loading

0 comments on commit f99e8f1

Please sign in to comment.