|
1 | 1 | import { NodeConfigurationDiffTransport } from "../../../src/commands/configuration-management/interfaces/node-diff.interfaces"; |
2 | 2 | import { NodeConfigurationChangeType } from "../../../src/commands/configuration-management/interfaces/diff-package.interfaces"; |
3 | | -import { mockAxiosGet } from "../../utls/http-requests-mock"; |
| 3 | +import { |
| 4 | + mockAxiosGet, |
| 5 | + mockAxiosPost, |
| 6 | + mockedAxiosInstance, |
| 7 | + mockedPostRequestBodyByUrl, |
| 8 | +} from "../../utls/http-requests-mock"; |
4 | 9 | import { NodeDiffService } from "../../../src/commands/configuration-management/node-diff.service"; |
5 | 10 | import { testContext } from "../../utls/test-context"; |
6 | 11 | import { loggingTestTransport, mockWriteFileSync } from "../../jest.setup"; |
7 | 12 | import { FileService } from "../../../src/core/utils/file-service"; |
| 13 | +import { mockCreateReadStream } from "../../utls/fs-mock-utils"; |
| 14 | +import * as FormData from "form-data"; |
8 | 15 | import * as path from "path"; |
9 | 16 |
|
10 | 17 | describe("Node diff", () => { |
@@ -290,4 +297,130 @@ describe("Node diff", () => { |
290 | 297 | const changeDateLog = loggingTestTransport.logMessages.find(log => log.message.includes("Change Date:")); |
291 | 298 | expect(changeDateLog.message).toContain(specificDate); |
292 | 299 | }); |
| 300 | + |
| 301 | + it("Should throw a FatalError when the diff API call fails", async () => { |
| 302 | + (mockedAxiosInstance.get as jest.Mock).mockRejectedValueOnce(new Error("network down")); |
| 303 | + |
| 304 | + await expect( |
| 305 | + new NodeDiffService(testContext).diff(packageKey, nodeKey, baseVersion, compareVersion, false) |
| 306 | + ).rejects.toThrow(/Problem getting the node diff/); |
| 307 | + |
| 308 | + expect(mockWriteFileSync).not.toHaveBeenCalled(); |
| 309 | + }); |
| 310 | + |
| 311 | + it("Should request the diff with both baseVersion and compareVersion query parameters", async () => { |
| 312 | + const expectedUrl = `https://myTeam.celonis.cloud/pacman/api/core/packages/${packageKey}/nodes/${nodeKey}/diff/configuration?baseVersion=${baseVersion}&compareVersion=${compareVersion}`; |
| 313 | + mockAxiosGet(expectedUrl, nodeDiff); |
| 314 | + |
| 315 | + await new NodeDiffService(testContext).diff(packageKey, nodeKey, baseVersion, compareVersion, false); |
| 316 | + |
| 317 | + expect(mockedAxiosInstance.get as jest.Mock).toHaveBeenCalledTimes(1); |
| 318 | + const calledUrl = (mockedAxiosInstance.get as jest.Mock).mock.calls[0][0]; |
| 319 | + expect(calledUrl).toBe(expectedUrl); |
| 320 | + }); |
| 321 | + |
| 322 | + describe("With file", () => { |
| 323 | + const file = "./node.json"; |
| 324 | + const nodeJsonContent = Buffer.from(JSON.stringify({ key: nodeKey, configuration: { foo: "bar" } })); |
| 325 | + |
| 326 | + beforeEach(() => { |
| 327 | + mockCreateReadStream(nodeJsonContent); |
| 328 | + }); |
| 329 | + |
| 330 | + it("Should diff a node file against STAGING and log all fields", async () => { |
| 331 | + const url = `https://myTeam.celonis.cloud/pacman/api/core/packages/${packageKey}/nodes/${nodeKey}/diff/configuration/with-file?baseVersion=STAGING`; |
| 332 | + mockAxiosPost(url, nodeDiff); |
| 333 | + |
| 334 | + await new NodeDiffService(testContext).diffWithFile(packageKey, nodeKey, "STAGING", file, false); |
| 335 | + |
| 336 | + expect(loggingTestTransport.logMessages.length).toBe(11); |
| 337 | + expect(loggingTestTransport.logMessages[0].message.trim()).toEqual(`Package Key: ${nodeDiff.packageKey}`); |
| 338 | + expect(loggingTestTransport.logMessages[1].message.trim()).toEqual(`Node Key: ${nodeDiff.nodeKey}`); |
| 339 | + expect(loggingTestTransport.logMessages[2].message.trim()).toEqual(`Name: ${nodeDiff.name}`); |
| 340 | + expect(loggingTestTransport.logMessages[3].message.trim()).toEqual(`Type: ${nodeDiff.type}`); |
| 341 | + expect(loggingTestTransport.logMessages[4].message.trim()).toEqual( |
| 342 | + `Is invalid configuration: ${nodeDiff.invalidContent}` |
| 343 | + ); |
| 344 | + expect(loggingTestTransport.logMessages[5].message.trim()).toEqual( |
| 345 | + `Parent Node Key: ${nodeDiff.parentNodeKey}` |
| 346 | + ); |
| 347 | + expect(loggingTestTransport.logMessages[6].message.trim()).toEqual(`Change Date: ${nodeDiff.changeDate}`); |
| 348 | + expect(loggingTestTransport.logMessages[7].message.trim()).toEqual(`Updated By: ${nodeDiff.updatedBy}`); |
| 349 | + expect(loggingTestTransport.logMessages[8].message.trim()).toEqual(`Change Type: ${nodeDiff.changeType}`); |
| 350 | + expect(loggingTestTransport.logMessages[9].message.trim()).toEqual( |
| 351 | + `Changes: ${JSON.stringify(nodeDiff.changes)}` |
| 352 | + ); |
| 353 | + expect(loggingTestTransport.logMessages[10].message.trim()).toEqual( |
| 354 | + `Metadata Changes: ${JSON.stringify(nodeDiff.metadataChanges)}` |
| 355 | + ); |
| 356 | + }); |
| 357 | + |
| 358 | + it("Should diff a node file against STAGING and return as JSON", async () => { |
| 359 | + const url = `https://myTeam.celonis.cloud/pacman/api/core/packages/${packageKey}/nodes/${nodeKey}/diff/configuration/with-file?baseVersion=STAGING`; |
| 360 | + mockAxiosPost(url, nodeDiff); |
| 361 | + |
| 362 | + await new NodeDiffService(testContext).diffWithFile(packageKey, nodeKey, "STAGING", file, true); |
| 363 | + |
| 364 | + const expectedFileName = loggingTestTransport.logMessages[0].message.split( |
| 365 | + FileService.fileDownloadedMessage |
| 366 | + )[1]; |
| 367 | + |
| 368 | + expect(mockWriteFileSync).toHaveBeenCalledWith( |
| 369 | + path.resolve(process.cwd(), expectedFileName), |
| 370 | + expect.any(String), |
| 371 | + { encoding: "utf-8", mode: 0o600 } |
| 372 | + ); |
| 373 | + |
| 374 | + const savedDiff = JSON.parse(mockWriteFileSync.mock.calls[0][1]) as NodeConfigurationDiffTransport; |
| 375 | + |
| 376 | + expect(savedDiff.packageKey).toEqual(nodeDiff.packageKey); |
| 377 | + expect(savedDiff.nodeKey).toEqual(nodeDiff.nodeKey); |
| 378 | + expect(savedDiff.changeType).toEqual(nodeDiff.changeType); |
| 379 | + expect(savedDiff.changes).toEqual(nodeDiff.changes); |
| 380 | + expect(savedDiff.metadataChanges).toEqual(nodeDiff.metadataChanges); |
| 381 | + }); |
| 382 | + |
| 383 | + it("Should diff a node file against a specific base version", async () => { |
| 384 | + const specificBaseVersion = "1.0.0"; |
| 385 | + const url = `https://myTeam.celonis.cloud/pacman/api/core/packages/${packageKey}/nodes/${nodeKey}/diff/configuration/with-file?baseVersion=${specificBaseVersion}`; |
| 386 | + mockAxiosPost(url, nodeDiff); |
| 387 | + |
| 388 | + await new NodeDiffService(testContext).diffWithFile(packageKey, nodeKey, specificBaseVersion, file, false); |
| 389 | + |
| 390 | + expect(loggingTestTransport.logMessages.length).toBe(11); |
| 391 | + expect(loggingTestTransport.logMessages[0].message.trim()).toEqual(`Package Key: ${nodeDiff.packageKey}`); |
| 392 | + }); |
| 393 | + |
| 394 | + it("Should send the node file as multipart/form-data with a 'file' field", async () => { |
| 395 | + const url = `https://myTeam.celonis.cloud/pacman/api/core/packages/${packageKey}/nodes/${nodeKey}/diff/configuration/with-file?baseVersion=STAGING`; |
| 396 | + mockAxiosPost(url, nodeDiff); |
| 397 | + |
| 398 | + await new NodeDiffService(testContext).diffWithFile(packageKey, nodeKey, "STAGING", file, false); |
| 399 | + |
| 400 | + const sentBody = mockedPostRequestBodyByUrl.get(url); |
| 401 | + expect(sentBody).toBeInstanceOf(FormData); |
| 402 | + |
| 403 | + const headers = (sentBody as FormData).getHeaders(); |
| 404 | + expect(headers["content-type"]).toMatch(/^multipart\/form-data; boundary=/); |
| 405 | + |
| 406 | + // form-data keeps the registered parts in its internal `_streams` array. Each form |
| 407 | + // field is represented by a header string followed by the value; assert that the |
| 408 | + // header chunk for the 'file' field is present. |
| 409 | + const streams: unknown[] = ((sentBody as unknown) as { _streams: unknown[] })._streams; |
| 410 | + const fileFieldHeader = streams.find( |
| 411 | + chunk => typeof chunk === "string" && chunk.includes('name="file"') |
| 412 | + ); |
| 413 | + expect(fileFieldHeader).toBeDefined(); |
| 414 | + }); |
| 415 | + |
| 416 | + it("Should throw a FatalError when the diff-with-file API call fails", async () => { |
| 417 | + (mockedAxiosInstance.post as jest.Mock).mockRejectedValueOnce(new Error("upload failed")); |
| 418 | + |
| 419 | + await expect( |
| 420 | + new NodeDiffService(testContext).diffWithFile(packageKey, nodeKey, "STAGING", file, false) |
| 421 | + ).rejects.toThrow(/Problem getting the node diff/); |
| 422 | + |
| 423 | + expect(mockWriteFileSync).not.toHaveBeenCalled(); |
| 424 | + }); |
| 425 | + }); |
293 | 426 | }); |
0 commit comments