I have a function getIssuesWithWorklogs that returns an array of objects. Each object has a field worklogs, which is an array.
After getting the results of invokeWithRateLimit(“getIssues”), the array is iterated over, and if a particular object has worklogs.length > 20, then a second function (fetchAllWorklogs) is called to get additional worklogs.
I need to check if the nested function fetchAllWorklogs is called with the passed parameter of the third fetch result.
I am getting the response of invokeWithRateLimit, where the second object (results[2]) has more than 20 worklogs, and I want to check that fetchAdditionalWorklogs was called with the id of the third object.
But I am having problems with this, because when calling getIssuesWithWorklogs, the fetchAdditionalWorklogs function is not called, but the real one. Maybe I should rewrite the test differently, or is there a way to fix this?
export const getIssuesWithWorklogs = async (jqlQuery, fields, reportName, changelog, progressCallback) => {
try {
const totalNumberOfIssues = await invokeWithRateLimit("getTotalNumberIssues", {
jqlQuery: jqlQuery,
fields: fields,
reportName: reportName,
changelog
});
if (totalNumberOfIssues === 0) return [];
await progressCallback(0, totalNumberOfIssues);
const point = 100;
const numberOfApiCalls = Math.ceil(totalNumberOfIssues / point);
const rerenderInterval = Math.ceil(totalNumberOfIssues / MAX_PROGRESSBAR_UPDATES);
let issuesLoaded = 0;
let issuesLoadedByResponses = 0;
const apiCallPromises = [];
for (let i = 0; i < numberOfApiCalls; i++) {
const startAtIssues = i * point;
const promise = invokeWithRateLimit("getIssues", {
jqlQuery: jqlQuery,
fields: fields,
reportName: reportName ? reportName : "",
startAtIssues: startAtIssues,
maxResults: 100,
totalNumber: totalNumberOfIssues,
changelog
})
.then(async (issues) => {
for (const issue of issues) {
if (issue.fields.worklog && issue.fields.worklog.total > 20) {
const additionalWorklogs = await fetchAllWorklogs(issue.id);
console.log("Fetching ended", additionalWorklogs);
issue.fields.worklog.worklogs = [...issue.fields.worklog.worklogs, ...additionalWorklogs];
}
}
issuesLoadedByResponses += issues.length;
progressCallback(Math.min(issuesLoadedByResponses, totalNumberOfIssues), totalNumberOfIssues);
return issues;
})
.catch((error) => {
console.error("Error in getIssues:", error);
throw error;
});
apiCallPromises.push(promise);
await delay(30);
issuesLoaded += point;
}
const responses = await Promise.all(apiCallPromises);
let response = [];
responses.forEach((issues) => {
response = response.concat(issues);
});
return response;
} catch (error) {
console.error("Error in getIssues:", error, jqlQuery, fields);
throw error;
}
};
export const fetchAllWorklogs = async (issueId) => {
const worklogs = [];
let startAt = 20;
try {
const response = await invokeWithRateLimit("getIssueWorklogs", {
issueId: issueId,
startAt: startAt
});
worklogs.push(...response.worklogs);
} catch (error) {
console.error(`Error fetching worklogs for issue ${issueId}:`, error);
}
return worklogs;
};
import invokeWithRateLimit from "utils/invokeWithRateLImit";
import { mockParametersForReports, mockReportsResults, mockWorklogsForTimesheet } from "../__mocks__/mockData";
import * as JiraUtils from "../src/services/JiraUtils";
import { getIssuesWithWorklogs } from "../src/services/JiraUtils";
jest.mock("../src/services/JiraUtils", () => {
const actual = jest.requireActual("../src/services/JiraUtils");
return {
...jest.genMockFromModule("../src/services/JiraUtils"), // Generate mocks for all functions
getIssuesWithWorklogs: actual.getIssuesWithWorklogs // Keep this function real
};
});
jest.mock("@forge/bridge", () => ({
invoke: jest.fn()
}));
jest.mock("../src/utils/invokeWithRateLImit.js", () => jest.fn());
jest.mock("constants", () => require("../src/constants"));
describe("getIssuesWithWorklogs", () => {
let mockProgressCallback;
beforeEach(() => {
jest.clearAllMocks();
mockProgressCallback = jest.fn();
});
test("Should return issues with worklogs when totalNumberOfIssues = 3", async () => {
const mockedParameters = mockParametersForReports["Timesheet"];
invokeWithRateLimit.mockResolvedValueOnce(3).mockResolvedValueOnce(mockReportsResults["Timesheet"]);
invokeWithRateLimit.mockResolvedValueOnce({
worklogs: [{ id: "18920", issueId: "13202", timeSpent: "1h" }]
});
JiraUtils.fetchAllWorklogs.mockResolvedValue(mockWorklogsForTimesheet);
const result = await getIssuesWithWorklogs(
mockedParameters.jqlQuery,
mockedParameters.fields,
mockedParameters.reportName,
mockedParameters.changelog,
mockProgressCallback
);
expect(result).toHaveLength(3);
expect(result[2].fields.worklog.worklogs).toContainEqual(mockWorklogsForTimesheet[0]);
expect(mockProgressCallback).toHaveBeenCalledTimes(2);
expect(mockProgressCallback).toHaveBeenCalledWith(0, 3);
expect(mockProgressCallback).toHaveBeenCalledWith(3, 3);
expect(invokeWithRateLimit).toHaveBeenNthCalledWith(1, "getTotalNumberIssues", {
jqlQuery: mockedParameters.jqlQuery,
fields: mockedParameters.fields,
reportName: mockedParameters.reportName,
changelog: mockedParameters.changelog
});
expect(invokeWithRateLimit).toHaveBeenNthCalledWith(2, "getIssues", {
jqlQuery: mockedParameters.jqlQuery,
fields: mockedParameters.fields,
reportName: mockedParameters.reportName,
startAtIssues: 0,
maxResults: 100,
totalNumber: 3,
changelog: mockedParameters.changelog
});
console.log(result[2].id);
console.log("Mock calls:", JiraUtils.fetchAllWorklogs.mock.calls);
await new Promise((resolve) => setTimeout(resolve, 100));
await expect(JiraUtils.fetchAllWorklogs).toHaveBeenCalledWith(result[2].id);
expect(invokeWithRateLimit).toHaveBeenCalledTimes(2);
});
Here are my logs and error message:
console.log
Fetching ended [ { id: ‘18920’, issueId: ‘13202’, timeSpent: ‘1h’ } ]
at log (src/services/JiraUtils.js:427:23)
console.log
13202
at Object.log (__tests__/jiraUtils.test.js:176:13)
console.log
Mock calls: []
at Object.log (__tests__/jiraUtils.test.js:177:13)
FAIL tests/jiraUtils.test.js
getIssuesWithWorklogs
× Should return issues with worklogs when totalNumberOfIssues = 3 (167 ms)
● getIssuesWithWorklogs › Should return issues with worklogs when totalNumberOfIssues = 3
expect(jest.fn()).toHaveBeenCalledWith(...expected)
Expected: "13202"
Number of calls: 0
177 | console.log("Mock calls:", JiraUtils.fetchAllWorklogs.mock.calls);
178 | await new Promise((resolve) => setTimeout(resolve, 100));
> 179 | await expect(JiraUtils.fetchAllWorklogs).toHaveBeenCalledWith(result[2].id);
| ^
180 |
181 | expect(invokeWithRateLimit).toHaveBeenCalledTimes(2);
182 | });
at Object.toHaveBeenCalledWith (__tests__/jiraUtils.test.js:179:46)
I’ve also tried spy function