diff --git a/.github/workflows/changeValidator.yml b/.github/workflows/changeValidator.yml index 1876ebf..2b9133d 100644 --- a/.github/workflows/changeValidator.yml +++ b/.github/workflows/changeValidator.yml @@ -23,8 +23,8 @@ jobs: node-version: 16 - name: Setup project run: npm i - - name: Run unit tests - run: npm test + - name: Run unit tests and system test + run: npm test -- --coverage windows: runs-on: windows-latest steps: @@ -36,8 +36,8 @@ jobs: node-version: 16 - name: Setup project run: npm i - - name: Run unit tests - run: npm test + - name: Run unit tests and system test + run: npm test -- --coverage mac: runs-on: macos-latest steps: @@ -49,5 +49,5 @@ jobs: node-version: 16 - name: Setup project run: npm i - - name: Run unit tests - run: npm test + - name: Run unit tests and system test + run: npm test -- --coverage diff --git a/.gitignore b/.gitignore index d2b46a7..3a1c770 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,6 @@ node_modules package-lock.json __test__/collection/output __test__/collection/new_collection.json -__test__/*copy* \ No newline at end of file +__test__/*copy* +coverage +new_collection.json \ No newline at end of file diff --git a/__test__/__snapshots__/test-cli-unit.test.js.snap b/__test__/__snapshots__/test-cli-unit.test.js.snap new file mode 100644 index 0000000..c3ac289 --- /dev/null +++ b/__test__/__snapshots__/test-cli-unit.test.js.snap @@ -0,0 +1,303 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validate index.js unit tests Validate cli output messages Should show file not found error if collection doesnt exists 1`] = `[MockFunction]`; + +exports[`Validate index.js unit tests Validate cli output messages Should show file not found error if collection doesnt exists 2`] = `[MockFunction]`; + +exports[`Validate index.js unit tests Validate cli output messages Should show file not found error if collection doesnt exists 3`] = `[MockFunction]`; + +exports[`Validate index.js unit tests Validate cli output messages Should show file not found error if collection doesnt exists 4`] = `"exit"`; + +exports[`Validate index.js unit tests Validate cli output messages Should show file not found error if collection doesnt exists 5`] = ` +[MockFunction] { + "calls": Array [ + Array [], + ], + "results": Array [ + Object { + "type": "throw", + "value": [Error: exit], + }, + ], +} +`; + +exports[`Validate index.js unit tests Validate cli output messages Should show file not found error if collection doesnt exists 6`] = ` +[MockFunction] { + "calls": Array [ + Array [ + "ENOENT: no such file or directory, open 'test/collection/collection.json'", + ], + ], + "results": Array [ + Object { + "type": "return", + "value": undefined, + }, + ], +} +`; + +exports[`Validate index.js unit tests Validate cli output messages Should show file not found error if collection doesnt exists 7`] = `[MockFunction]`; + +exports[`Validate index.js unit tests Validate cli output messages Should show file saved message correctly with custom path 1`] = `[MockFunction]`; + +exports[`Validate index.js unit tests Validate cli output messages Should show file saved message correctly with custom path 2`] = `[MockFunction]`; + +exports[`Validate index.js unit tests Validate cli output messages Should show file saved message correctly with custom path 3`] = `[MockFunction]`; + +exports[`Validate index.js unit tests Validate cli output messages Should show file saved message correctly with custom path 4`] = `[MockFunction]`; + +exports[`Validate index.js unit tests Validate cli output messages Should show file saved message correctly with custom path 5`] = `[MockFunction]`; + +exports[`Validate index.js unit tests Validate cli output messages Should show file saved message correctly with default path 1`] = `[MockFunction]`; + +exports[`Validate index.js unit tests Validate cli output messages Should show file saved message correctly with default path 2`] = `[MockFunction]`; + +exports[`Validate index.js unit tests Validate cli output messages Should show file saved message correctly with default path 3`] = `[MockFunction]`; + +exports[`Validate index.js unit tests Validate cli output messages Should show file saved message correctly with default path 4`] = `[MockFunction]`; + +exports[`Validate index.js unit tests Validate cli output messages Should show file saved message correctly with default path 5`] = `[MockFunction]`; + +exports[`Validate index.js unit tests Validate cli output messages Should show help if -c argument is missing 1`] = `"exit"`; + +exports[`Validate index.js unit tests Validate cli output messages Should show help if -c argument is missing 2`] = ` +[MockFunction] { + "calls": Array [ + Array [ + 1, + ], + ], + "results": Array [ + Object { + "type": "throw", + "value": [Error: exit], + }, + ], +} +`; + +exports[`Validate index.js unit tests Validate cli output messages Should show help if -c argument is missing 3`] = ` +[MockFunction] { + "calls": Array [ + Array [ + "Usage: -c \\"root/collection_name.json\\" -r \\"{{Baseurl}}/path1/path2\\" -w +\\"{{Baseurl}}/{{path}}\\" -s \\"root/new_collection_name.json\\" + +Options: + --help Show help [boolean] + --version Show version number [boolean] + -c, --collection_path Path to Collection file [string] [required] + -r, --replace_url_part Replaces only the matching part of the URL + [string] [required] + -w, --with_url_part Replaces the matching part of the URL with provided + value [string] [required] + -s, --save_as path to save new collection + [string] [default: \\"root/new_.json\\"]", + ], + Array [], + Array [ + "Missing required argument: c", + ], + ], + "results": Array [ + Object { + "type": "return", + "value": undefined, + }, + Object { + "type": "return", + "value": undefined, + }, + Object { + "type": "return", + "value": undefined, + }, + ], +} +`; + +exports[`Validate index.js unit tests Validate cli output messages Should show help if -c argument is missing 4`] = `[MockFunction]`; + +exports[`Validate index.js unit tests Validate cli output messages Should show help if -r argument is missing 1`] = `"exit"`; + +exports[`Validate index.js unit tests Validate cli output messages Should show help if -r argument is missing 2`] = ` +[MockFunction] { + "calls": Array [ + Array [ + 1, + ], + ], + "results": Array [ + Object { + "type": "throw", + "value": [Error: exit], + }, + ], +} +`; + +exports[`Validate index.js unit tests Validate cli output messages Should show help if -r argument is missing 3`] = ` +[MockFunction] { + "calls": Array [ + Array [ + "Usage: -c \\"root/collection_name.json\\" -r \\"{{Baseurl}}/path1/path2\\" -w +\\"{{Baseurl}}/{{path}}\\" -s \\"root/new_collection_name.json\\" + +Options: + --help Show help [boolean] + --version Show version number [boolean] + -c, --collection_path Path to Collection file [string] [required] + -r, --replace_url_part Replaces only the matching part of the URL + [string] [required] + -w, --with_url_part Replaces the matching part of the URL with provided + value [string] [required] + -s, --save_as path to save new collection + [string] [default: \\"root/new_.json\\"]", + ], + Array [], + Array [ + "Missing required argument: r", + ], + ], + "results": Array [ + Object { + "type": "return", + "value": undefined, + }, + Object { + "type": "return", + "value": undefined, + }, + Object { + "type": "return", + "value": undefined, + }, + ], +} +`; + +exports[`Validate index.js unit tests Validate cli output messages Should show help if -r argument is missing 4`] = `[MockFunction]`; + +exports[`Validate index.js unit tests Validate cli output messages Should show help if -w argument is missing 1`] = `"exit"`; + +exports[`Validate index.js unit tests Validate cli output messages Should show help if -w argument is missing 2`] = ` +[MockFunction] { + "calls": Array [ + Array [ + 1, + ], + ], + "results": Array [ + Object { + "type": "throw", + "value": [Error: exit], + }, + ], +} +`; + +exports[`Validate index.js unit tests Validate cli output messages Should show help if -w argument is missing 3`] = ` +[MockFunction] { + "calls": Array [ + Array [ + "Usage: -c \\"root/collection_name.json\\" -r \\"{{Baseurl}}/path1/path2\\" -w +\\"{{Baseurl}}/{{path}}\\" -s \\"root/new_collection_name.json\\" + +Options: + --help Show help [boolean] + --version Show version number [boolean] + -c, --collection_path Path to Collection file [string] [required] + -r, --replace_url_part Replaces only the matching part of the URL + [string] [required] + -w, --with_url_part Replaces the matching part of the URL with provided + value [string] [required] + -s, --save_as path to save new collection + [string] [default: \\"root/new_.json\\"]", + ], + Array [], + Array [ + "Missing required argument: w", + ], + ], + "results": Array [ + Object { + "type": "return", + "value": undefined, + }, + Object { + "type": "return", + "value": undefined, + }, + Object { + "type": "return", + "value": undefined, + }, + ], +} +`; + +exports[`Validate index.js unit tests Validate cli output messages Should show help if -w argument is missing 4`] = `[MockFunction]`; + +exports[`Validate index.js unit tests Validate cli output messages Should show help if arguments are missing 1`] = `"exit"`; + +exports[`Validate index.js unit tests Validate cli output messages Should show help if arguments are missing 2`] = ` +[MockFunction] { + "calls": Array [ + Array [ + 1, + ], + ], + "results": Array [ + Object { + "type": "throw", + "value": [Error: exit], + }, + ], +} +`; + +exports[`Validate index.js unit tests Validate cli output messages Should show help if arguments are missing 3`] = ` +[MockFunction] { + "calls": Array [ + Array [ + "Usage: -c \\"root/collection_name.json\\" -r \\"{{Baseurl}}/path1/path2\\" -w +\\"{{Baseurl}}/{{path}}\\" -s \\"root/new_collection_name.json\\" + +Options: + --help Show help [boolean] + --version Show version number [boolean] + -c, --collection_path Path to Collection file [string] [required] + -r, --replace_url_part Replaces only the matching part of the URL + [string] [required] + -w, --with_url_part Replaces the matching part of the URL with provided + value [string] [required] + -s, --save_as path to save new collection + [string] [default: \\"root/new_.json\\"]", + ], + Array [], + Array [ + "Missing required arguments: c, r, w", + ], + ], + "results": Array [ + Object { + "type": "return", + "value": undefined, + }, + Object { + "type": "return", + "value": undefined, + }, + Object { + "type": "return", + "value": undefined, + }, + ], +} +`; + +exports[`Validate index.js unit tests Validate cli output messages Should show help if arguments are missing 4`] = `[MockFunction]`; + +exports[`Validate index.js unit tests Validate cli output messages Should throw error if exception thrown doesnt contain error code ENOENT 1`] = `"Error: Custom error"`; diff --git a/__test__/__snapshots__/test-cli.test.js.snap b/__test__/__snapshots__/test-cli.test.js.snap index e8241af..e88bbe3 100644 --- a/__test__/__snapshots__/test-cli.test.js.snap +++ b/__test__/__snapshots__/test-cli.test.js.snap @@ -1,13 +1,13 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Validate index.js Validate cli output messages Should show file not found error if collection doesnt exists 1`] = `""`; - -exports[`Validate index.js Validate cli output messages Should show file not found error if collection doesnt exists 2`] = ` +exports[`Validate index.js system test Validate cli output messages Should show file not found error if collection doesnt exists 1`] = ` "ENOENT: no such file or directory, open 'test/collection/collection.json' " `; -exports[`Validate index.js Validate cli output messages Should show help if -c argument is missing 1`] = ` +exports[`Validate index.js system test Validate cli output messages Should show file not found error if collection doesnt exists 2`] = `""`; + +exports[`Validate index.js system test Validate cli output messages Should show help if -c argument is missing 1`] = ` "Usage: -c \\"root/collection_name.json\\" -r \\"{{Baseurl}}/path1/path2\\" -w \\"{{Baseurl}}/{{path}}\\" -s \\"root/new_collection_name.json\\" @@ -22,13 +22,13 @@ Options: -s, --save_as path to save new collection [string] [default: \\"root/new_.json\\"] -Missing required argument: r +Missing required argument: c " `; -exports[`Validate index.js Validate cli output messages Should show help if -c argument is missing 2`] = `""`; +exports[`Validate index.js system test Validate cli output messages Should show help if -c argument is missing 2`] = `""`; -exports[`Validate index.js Validate cli output messages Should show help if -r argument is missing 1`] = ` +exports[`Validate index.js system test Validate cli output messages Should show help if -r argument is missing 1`] = ` "Usage: -c \\"root/collection_name.json\\" -r \\"{{Baseurl}}/path1/path2\\" -w \\"{{Baseurl}}/{{path}}\\" -s \\"root/new_collection_name.json\\" @@ -47,9 +47,9 @@ Missing required argument: r " `; -exports[`Validate index.js Validate cli output messages Should show help if -r argument is missing 2`] = `""`; +exports[`Validate index.js system test Validate cli output messages Should show help if -r argument is missing 2`] = `""`; -exports[`Validate index.js Validate cli output messages Should show help if -w argument is missing 1`] = ` +exports[`Validate index.js system test Validate cli output messages Should show help if -w argument is missing 1`] = ` "Usage: -c \\"root/collection_name.json\\" -r \\"{{Baseurl}}/path1/path2\\" -w \\"{{Baseurl}}/{{path}}\\" -s \\"root/new_collection_name.json\\" @@ -68,9 +68,9 @@ Missing required argument: w " `; -exports[`Validate index.js Validate cli output messages Should show help if -w argument is missing 2`] = `""`; +exports[`Validate index.js system test Validate cli output messages Should show help if -w argument is missing 2`] = `""`; -exports[`Validate index.js Validate cli output messages Should show help if arguments are missing 1`] = ` +exports[`Validate index.js system test Validate cli output messages Should show help if arguments are missing 1`] = ` "Usage: -c \\"root/collection_name.json\\" -r \\"{{Baseurl}}/path1/path2\\" -w \\"{{Baseurl}}/{{path}}\\" -s \\"root/new_collection_name.json\\" diff --git a/__test__/test-cli-unit.test.js b/__test__/test-cli-unit.test.js new file mode 100644 index 0000000..fcf5ce4 --- /dev/null +++ b/__test__/test-cli-unit.test.js @@ -0,0 +1,302 @@ +const path = require('path'); + +const exec = require('shelljs').exec, + sdk = require('postman-collection'), + fs = require('fs'), + { resetAndReimportUrlUpdator, CustomError } = require('./utils/helperMethods.js'); + + +let postman_url_updater, + mockProcessExit = jest.spyOn(process, 'exit').mockImplementation(() => { throw new Error("exit"); }), + mockConsoleError = jest.spyOn(console, 'error').mockImplementation(() => { }), + mockConsoleLog = jest.spyOn(console, 'log').mockImplementation(() => { }); + +describe('Validate index.js unit tests', () => { + describe('Validate cli output messages', () => { + + afterEach(() => { + jest.clearAllMocks(); + }); + + afterAll(() => { + jest.restoreAllMocks(); + }) + + it('Should show help if arguments are missing', async () => { + resetAndReimportUrlUpdator({ c: undefined, r: undefined, w: undefined, s: undefined, p: undefined }); + expect(() => { require('../index.js') }).toThrowErrorMatchingSnapshot() + expect(mockProcessExit).toBeCalled(); + expect(mockConsoleError).toBeCalled(); + expect(mockProcessExit).toMatchSnapshot(); + expect(mockConsoleError).toMatchSnapshot(); + expect(mockConsoleLog).not.toBeCalled(); + expect(mockConsoleLog).toMatchSnapshot(); + }); + + it('Should show help if -c argument is missing', async () => { + resetAndReimportUrlUpdator({ c: undefined, r: "{{baseURL}}/{{path}}", w: "new_collection.json", s: undefined, p: undefined }); + expect(() => { require('../index.js') }).toThrowErrorMatchingSnapshot() + expect(mockProcessExit).toBeCalled(); + expect(mockConsoleError).toBeCalled(); + expect(mockProcessExit).toMatchSnapshot(); + expect(mockConsoleError).toMatchSnapshot(); + expect(mockConsoleLog).not.toBeCalled(); + expect(mockConsoleLog).toMatchSnapshot(); + }); + + it('Should show help if -r argument is missing', async () => { + resetAndReimportUrlUpdator({ c: "test/collection/collection.json", r: undefined, w: "new_collection.json", s: undefined, p: undefined }); + expect(() => { require('../index.js') }).toThrowErrorMatchingSnapshot() + expect(mockProcessExit).toBeCalled(); + expect(mockConsoleError).toBeCalled(); + expect(mockProcessExit).toMatchSnapshot(); + expect(mockConsoleError).toMatchSnapshot(); + expect(mockConsoleLog).not.toBeCalled(); + expect(mockConsoleLog).toMatchSnapshot(); + }); + + it('Should show help if -w argument is missing', async () => { + resetAndReimportUrlUpdator({ c: "test/collection/collection.json", r: "{{baseURL}}/{{path}}", w: undefined, s: "new_collection.json", p: undefined }); + expect(() => { require('../index.js') }).toThrowErrorMatchingSnapshot() + expect(mockProcessExit).toBeCalled(); + expect(mockConsoleError).toBeCalled(); + expect(mockProcessExit).toMatchSnapshot(); + expect(mockConsoleError).toMatchSnapshot(); + expect(mockConsoleLog).not.toBeCalled(); + expect(mockConsoleLog).toMatchSnapshot(); + }); + + it('Should show file not found error if collection doesnt exists', async () => { + resetAndReimportUrlUpdator({ c: "test/collection/collection.json", r: "{{baseURL}}/{{path}}", w: "{{baseURL}}/{{path}}", s: "new_collection.json", p: undefined }); + postman_url_updater = require('../index.js') + expect(mockProcessExit).not.toBeCalled(); + expect(mockConsoleError).not.toBeCalled(); + expect(mockProcessExit).toMatchSnapshot(); + expect(mockConsoleError).toMatchSnapshot(); + expect(mockConsoleLog).not.toBeCalled(); + expect(mockConsoleLog).toMatchSnapshot(); + jest.clearAllMocks() + expect(postman_url_updater.startConvert).toThrowErrorMatchingSnapshot(); + expect(mockProcessExit).toBeCalled(); + expect(mockConsoleError).toBeCalled(); + expect(mockProcessExit).toMatchSnapshot(); + expect(mockConsoleError).toMatchSnapshot(); + expect(mockConsoleLog).not.toBeCalled(); + expect(mockConsoleLog).toMatchSnapshot(); + }); + + it('Should show file saved message correctly with default path', async () => { + resetAndReimportUrlUpdator({ c: "__test__/collection/collection.json", r: "{{baseURL}}/{{path}}", w: "{{baseURL}}/{{path}}", s: undefined, p: undefined }); + postman_url_updater = require('../index.js') + expect(mockProcessExit).not.toBeCalled(); + expect(mockConsoleError).not.toBeCalled(); + expect(mockProcessExit).toMatchSnapshot(); + expect(mockConsoleError).toMatchSnapshot(); + expect(mockConsoleLog).not.toBeCalled(); + expect(mockConsoleLog).toMatchSnapshot(); + jest.clearAllMocks() + postman_url_updater.startConvert(); + expect(mockProcessExit).not.toBeCalled(); + expect(mockConsoleError).not.toBeCalled(); + expect(mockProcessExit).toMatchSnapshot(); + expect(mockConsoleError).toMatchSnapshot(); + expect(mockConsoleLog).toBeCalledWith(`File saved to: ${path.resolve('./__test__/collection/new_collection.json')}`); + }); + + it('Should show file saved message correctly with custom path', async () => { + resetAndReimportUrlUpdator({ c: "__test__/collection/collection.json", r: "{{baseURL}}/{{path}}", w: "{{baseURL}}/{{path}}", s: "__test__/collection/output/new_collection.json", p: undefined }); + postman_url_updater = require('../index.js') + expect(mockProcessExit).not.toBeCalled(); + expect(mockConsoleError).not.toBeCalled(); + expect(mockProcessExit).toMatchSnapshot(); + expect(mockConsoleError).toMatchSnapshot(); + expect(mockConsoleLog).not.toBeCalled(); + expect(mockConsoleLog).toMatchSnapshot(); + jest.clearAllMocks() + postman_url_updater.startConvert() + expect(mockProcessExit).not.toBeCalled(); + expect(mockConsoleError).not.toBeCalled(); + expect(mockProcessExit).toMatchSnapshot(); + expect(mockConsoleError).toMatchSnapshot(); + expect(mockConsoleLog).toBeCalledWith(`File saved to: ${path.resolve('./__test__/collection/output/new_collection.json')}`); + }); + + it('Should throw error if exception thrown doesnt contain error code ENOENT', async () => { + resetAndReimportUrlUpdator({ c: "__test__/collection/collection.json", r: "{{baseURL}}/{{path}}", w: "{{baseURL}}/{{path}}", s: "new_collection.json", p: undefined }); + postman_url_updater = require('../index.js') + jest.clearAllMocks() + mockConsoleLog.mockImplementation(() => { throw new CustomError(256) }); + expect(postman_url_updater.startConvert).toThrowErrorMatchingSnapshot() + }); + }) + + describe('Validate collection changes', () => { + let collectionPath = '__test__/collection/collection.json', + outputCollectionPath = '__test__/collection/output/new_unit.json'; + + it('validate no changes happens when there is no match', async () => { + const sourceCollection = new sdk.Collection(JSON.parse(fs.readFileSync(collectionPath).toString())).toJSON(); + resetAndReimportUrlUpdator({ c: collectionPath, r: "https://localhost:23456/api/v1/{{path}}", w: "{{baseURL}}/{{path}}", s: outputCollectionPath, p: undefined }); + require('../index.js').startConvert(); + const outputCollection = new sdk.Collection(JSON.parse(fs.readFileSync(outputCollectionPath).toString())).toJSON(); + expect(outputCollection.item[0].item[0].request).toStrictEqual(sourceCollection.item[0].item[0].request); + expect(outputCollection.item[1].item[0].item[0].item[0].item[0].item[0].item[0].item[0].request) + .toStrictEqual(sourceCollection.item[1].item[0].item[0].item[0].item[0].item[0].item[0].item[0].request); + expect(outputCollection.item[2].request).toStrictEqual(sourceCollection.item[2].request); + expect(outputCollection.item[3].request).toStrictEqual(sourceCollection.item[3].request); + }); + + it('validate change happens only for urls other properties remains the same', async () => { + function updatedRequestObject(source, depthID, postionID) { + source.request.url.host = ["{{baseURL}}"]; + source.request.url.path = [ + "{{path}}", + "testpath", + `:pathvariable${depthID}-${postionID}`, + "path", + `request${depthID}-${postionID}`, + ]; + delete source.request.url.protocol + } + + const sourceCollection = new sdk.Collection(JSON.parse(fs.readFileSync(collectionPath).toString())).toJSON(); + resetAndReimportUrlUpdator({ c: collectionPath, r: "https://www.testdomain0.ie", w: "{{baseURL}}/{{path}}", s: outputCollectionPath, p: undefined }); + require('../index.js').startConvert(); + const outputCollection = new sdk.Collection(JSON.parse(fs.readFileSync(outputCollectionPath).toString())).toJSON(); + + updatedRequestObject(sourceCollection.item[0].item[0], 1, 1); + updatedRequestObject(sourceCollection.item[1].item[0].item[0].item[0].item[0].item[0].item[0].item[0], 'n', 1); + updatedRequestObject(sourceCollection.item[2], 0, 1); + + expect(outputCollection.item[0].item[0].request).toStrictEqual(sourceCollection.item[0].item[0].request); + expect(outputCollection.item[1].item[0].item[0].item[0].item[0].item[0].item[0].item[0].request) + .toStrictEqual(sourceCollection.item[1].item[0].item[0].item[0].item[0].item[0].item[0].item[0].request); + expect(outputCollection.item[2].request).toStrictEqual(sourceCollection.item[2].request); + expect(outputCollection.item[3].request).toStrictEqual(sourceCollection.item[3].request); + }); + + it('validate change protocol is shown if not removed', async () => { + + function updatedRequestObject(source, depthID, postionID) { + source.request.url.host = ["{{baseURL}}"]; + source.request.url.path = [ + "{{path}}", + "testpath", + `:pathvariable${depthID}-${postionID}`, + "path", + `request${depthID}-${postionID}`, + ]; + } + + const sourceCollection = new sdk.Collection(JSON.parse(fs.readFileSync(collectionPath).toString())).toJSON(); + resetAndReimportUrlUpdator({ c: collectionPath, r: "www.testdomain0.ie", w: "{{baseURL}}/{{path}}", s: outputCollectionPath, p: undefined }); + require('../index.js').startConvert(); + const outputCollection = new sdk.Collection(JSON.parse(fs.readFileSync(outputCollectionPath).toString())).toJSON(); + + updatedRequestObject(sourceCollection.item[0].item[0], 1, 1); + updatedRequestObject(sourceCollection.item[1].item[0].item[0].item[0].item[0].item[0].item[0].item[0], 'n', 1); + updatedRequestObject(sourceCollection.item[2], 0, 1); + + expect(outputCollection.item[0].item[0].request).toStrictEqual(sourceCollection.item[0].item[0].request); + expect(outputCollection.item[1].item[0].item[0].item[0].item[0].item[0].item[0].item[0].request) + .toStrictEqual(sourceCollection.item[1].item[0].item[0].item[0].item[0].item[0].item[0].item[0].request); + expect(outputCollection.item[2].request).toStrictEqual(sourceCollection.item[2].request); + expect(outputCollection.item[3].request).toStrictEqual(sourceCollection.item[3].request); + }); + + + it('validate path varaible is removed if replaced', async () => { + + function updatedRequestObject(source, depthID, postionID) { + source.request.url.host = ["{{baseURL}}"]; + source.request.url.path = [ + "{{path}}", + "path", + `request${depthID}-${postionID}`, + ]; + source.request.url.variable = [] + } + + const sourceCollection = new sdk.Collection(JSON.parse(fs.readFileSync(collectionPath).toString())).toJSON(); + resetAndReimportUrlUpdator({ c: collectionPath, r: "www.testdomain0.ie/testpath/:pathvariable1-1", w: "{{baseURL}}/{{path}}", s: outputCollectionPath, p: undefined }); + require('../index.js').startConvert(); + const outputCollection = new sdk.Collection(JSON.parse(fs.readFileSync(outputCollectionPath).toString())).toJSON(); + + updatedRequestObject(sourceCollection.item[0].item[0], 1, 1); + + expect(outputCollection.item[0].item[0].request).toStrictEqual(sourceCollection.item[0].item[0].request); + expect(outputCollection.item[1].item[0].item[0].item[0].item[0].item[0].item[0].item[0].request) + .toStrictEqual(sourceCollection.item[1].item[0].item[0].item[0].item[0].item[0].item[0].item[0].request); + expect(outputCollection.item[2].request).toStrictEqual(sourceCollection.item[2].request); + expect(outputCollection.item[3].request).toStrictEqual(sourceCollection.item[3].request); + }); + + + it('validate query parameters are updated', async () => { + + function updatedRequestObject(source, depthID, postionID) { + source.request.url.path = [ + "testpath", + `:pathvariable${depthID}-${postionID}`, + "path", + `request${depthID}-${postionID}`, + ]; + source.request.url.query = [ + { key: 'query1-1-0', value: 'queryvalue1-1-0-0' }, + { key: 'test', value: 'queryvalue1-1-0' }, + { key: 'query1-1-1', value: 'queryvalue1-1-1' } + ] + + } + + const sourceCollection = new sdk.Collection(JSON.parse(fs.readFileSync(collectionPath).toString())).toJSON(); + resetAndReimportUrlUpdator({ c: collectionPath, r: "/:pathvariable1-1/path/request1-1?query1-1-0", w: "/:pathvariable1-1/path/request1-1?query1-1-0=queryvalue1-1-0-0&test", s: outputCollectionPath, p: undefined }); + require('../index.js').startConvert(); + const outputCollection = new sdk.Collection(JSON.parse(fs.readFileSync(outputCollectionPath).toString())).toJSON(); + + updatedRequestObject(sourceCollection.item[0].item[0], 1, 1); + + expect(outputCollection.item[0].item[0].request).toStrictEqual(sourceCollection.item[0].item[0].request); + expect(outputCollection.item[1].item[0].item[0].item[0].item[0].item[0].item[0].item[0].request) + .toStrictEqual(sourceCollection.item[1].item[0].item[0].item[0].item[0].item[0].item[0].item[0].request); + expect(outputCollection.item[2].request).toStrictEqual(sourceCollection.item[2].request); + expect(outputCollection.item[3].request).toStrictEqual(sourceCollection.item[3].request); + }); + + + it('validate query and path variables are removed if replaced completely', async () => { + + function updatedRequestObject(source, depthID, postionID) { + source.request.url.path = [ + 'v1', + '{{path}}' + ]; + source.request.url.variable = []; + source.request.url.query = []; + source.request.url.host = ["{{baseURL}}"]; + source.request.url.protocol = "{{protocol}}"; + + } + + const sourceCollection = new sdk.Collection(JSON.parse(fs.readFileSync(collectionPath).toString())).toJSON(); + resetAndReimportUrlUpdator({ + c: collectionPath, + r: "https://www.testdomain0.ie/testpath/:pathvariable1-1/path/request1-1?query1-1-0=queryvalue1-1-0&query1-1-1=queryvalue1-1-1", + w: "{{protocol}}://{{baseURL}}/v1/{{path}}", s: outputCollectionPath, p: undefined + }); + require('../index.js').startConvert(); + + const outputCollection = new sdk.Collection(JSON.parse(fs.readFileSync(outputCollectionPath).toString())).toJSON(); + + updatedRequestObject(sourceCollection.item[0].item[0], 1, 1); + + expect(outputCollection.item[0].item[0].request).toStrictEqual(sourceCollection.item[0].item[0].request); + expect(outputCollection.item[1].item[0].item[0].item[0].item[0].item[0].item[0].item[0].request) + .toStrictEqual(sourceCollection.item[1].item[0].item[0].item[0].item[0].item[0].item[0].item[0].request); + expect(outputCollection.item[2].request).toStrictEqual(sourceCollection.item[2].request); + expect(outputCollection.item[3].request).toStrictEqual(sourceCollection.item[3].request); + }); + + }) +}) + diff --git a/__test__/test-cli.test.js b/__test__/test-cli.test.js index f76536f..8bd4dc0 100644 --- a/__test__/test-cli.test.js +++ b/__test__/test-cli.test.js @@ -2,45 +2,45 @@ const exec = require('shelljs').exec, SDK = require('postman-collection'), FS = require('fs'); -describe('Validate index.js', () => { +describe('Validate index.js system test', () => { describe('Validate cli output messages', () => { it('Should show help if arguments are missing', async () => { - const commandResponse = exec('node "index.js"', { silent: true }); + const commandResponse = exec('node "bin/main.js"', { silent: true }); expect(commandResponse.stderr).toMatchSnapshot(); }); it('Should show help if -c argument is missing', async () => { - const commandResponse = exec('node "index.js" -c "test/collection/collection.json" -w "{{baseURL}}/{{path}}" -s "new_collection.json"', { silent: true }); + const commandResponse = exec('node "bin/main.js" -r "test" -w "{{baseURL}}/{{path}}" -s "new_collection.json"', { silent: true }); expect(commandResponse.stderr).toMatchSnapshot(); expect(commandResponse.stdout).toMatchSnapshot(); }); it('Should show help if -r argument is missing', async () => { - const commandResponse = exec('node "index.js" -c "test/collection/collection.json" -w "{{baseURL}}/{{path}}" -s "new_collection.json"', { silent: true }); + const commandResponse = exec('node "bin/main.js" -c "test/collection/collection.json" -w "{{baseURL}}/{{path}}" -s "new_collection.json"', { silent: true }); expect(commandResponse.stderr).toMatchSnapshot(); expect(commandResponse.stdout).toMatchSnapshot(); }); it('Should show help if -w argument is missing', async () => { - const commandResponse = exec('node "index.js" -c "test/collection/collection.json" -r "{{baseURL}}/{{path}}" -s "new_collection.json"', { silent: true }); + const commandResponse = exec('node "bin/main.js" -c "test/collection/collection.json" -r "{{baseURL}}/{{path}}" -s "new_collection.json"', { silent: true }); expect(commandResponse.stderr).toMatchSnapshot(); expect(commandResponse.stdout).toMatchSnapshot(); }); it('Should show file not found error if collection doesnt exists', async () => { - const commandResponse = exec('node "index.js" -c "test/collection/collection.json" -r "https://localhost:23456/api/v1/{{path}}" -w "{{baseURL}}/{{path}}" -s "new_collection.json"', { silent: true }); + const commandResponse = exec('node "bin/main.js" -c "test/collection/collection.json" -r "https://localhost:23456/api/v1/{{path}}" -w "{{baseURL}}/{{path}}" -s "new_collection.json"', { silent: true }); expect(commandResponse.stderr).toMatchSnapshot(); expect(commandResponse.stdout).toMatchSnapshot(); }); it('Should show file saved message correctly with default path', async () => { - const commandResponse = exec('node "index.js" -c "__test__/collection/collection.json" -r "https://localhost:23456/api/v1/{{path}}" -w "{{baseURL}}/{{path}}"', { silent: true }); + const commandResponse = exec('node "bin/main.js" -c "__test__/collection/collection.json" -r "https://localhost:23456/api/v1/{{path}}" -w "{{baseURL}}/{{path}}"', { silent: true }); expect(commandResponse.stderr).toMatch(''); expect(commandResponse.stdout).toMatch(/File saved to: .*[\\|\/]__test__[\\|\/]collection[\\|\/]new_collection.json/g); }); it('Should show file saved message correctly with custom path', async () => { - const commandResponse = exec('node "index.js" -c "__test__/collection/collection.json" -r "https://localhost:23456/api/v1/{{path}}" -w "{{baseURL}}/{{path}}" -s "__test__/collection/output/new.json"', { silent: true }); + const commandResponse = exec('node "bin/main.js" -c "__test__/collection/collection.json" -r "https://localhost:23456/api/v1/{{path}}" -w "{{baseURL}}/{{path}}" -s "__test__/collection/output/new.json"', { silent: true }); expect(commandResponse.stderr).toMatch(''); expect(commandResponse.stdout).toMatch(/File saved to: .*[\\|\/]__test__[\\|\/]collection[\\|\/]output[\\|\/]new\.json/g); }); @@ -53,7 +53,7 @@ describe('Validate index.js', () => { it('validate no changes happens when there is no match', async () => { const sourceCollection = new SDK.Collection(JSON.parse(FS.readFileSync(collectionPath).toString())).toJSON(); - const commandResponse = exec(`node "index.js" -c "${collectionPath}" -r "https://localhost:23456/api/v1/{{path}}" -w "{{baseURL}}/{{path}}" -s "${outputCollectionPath}"`, { silent: true }); + const commandResponse = exec(`node "bin/main.js" -c "${collectionPath}" -r "https://localhost:23456/api/v1/{{path}}" -w "{{baseURL}}/{{path}}" -s "${outputCollectionPath}"`, { silent: true }); const outputCollection = new SDK.Collection(JSON.parse(FS.readFileSync(outputCollectionPath).toString())).toJSON(); expect(outputCollection.item[0].item[0].request).toStrictEqual(sourceCollection.item[0].item[0].request); expect(outputCollection.item[1].item[0].item[0].item[0].item[0].item[0].item[0].item[0].request) @@ -77,7 +77,7 @@ describe('Validate index.js', () => { } const sourceCollection = new SDK.Collection(JSON.parse(FS.readFileSync(collectionPath).toString())).toJSON(); - const commandResponse = exec(`node "index.js" -c "${collectionPath}" -r "https://www.testdomain0.ie" -w "{{baseURL}}/{{path}}" -s "${outputCollectionPath}"`, { silent: true }); + const commandResponse = exec(`node "bin/main.js" -c "${collectionPath}" -r "https://www.testdomain0.ie" -w "{{baseURL}}/{{path}}" -s "${outputCollectionPath}"`, { silent: true }); const outputCollection = new SDK.Collection(JSON.parse(FS.readFileSync(outputCollectionPath).toString())).toJSON(); updatedRequestObject(sourceCollection.item[0].item[0], 1, 1); @@ -105,7 +105,7 @@ describe('Validate index.js', () => { } const sourceCollection = new SDK.Collection(JSON.parse(FS.readFileSync(collectionPath).toString())).toJSON(); - const commandResponse = exec(`node "index.js" -c "${collectionPath}" -r "www.testdomain0.ie" -w "{{baseURL}}/{{path}}" -s "${outputCollectionPath}"`, { silent: true }); + const commandResponse = exec(`node "bin/main.js" -c "${collectionPath}" -r "www.testdomain0.ie" -w "{{baseURL}}/{{path}}" -s "${outputCollectionPath}"`, { silent: true }); const outputCollection = new SDK.Collection(JSON.parse(FS.readFileSync(outputCollectionPath).toString())).toJSON(); updatedRequestObject(sourceCollection.item[0].item[0], 1, 1); @@ -133,7 +133,7 @@ describe('Validate index.js', () => { } const sourceCollection = new SDK.Collection(JSON.parse(FS.readFileSync(collectionPath).toString())).toJSON(); - const commandResponse = exec(`node "index.js" -c "${collectionPath}" -r "www.testdomain0.ie/testpath/:pathvariable1-1" -w "{{baseURL}}/{{path}}" -s "${outputCollectionPath}"`, { silent: true }); + const commandResponse = exec(`node "bin/main.js" -c "${collectionPath}" -r "www.testdomain0.ie/testpath/:pathvariable1-1" -w "{{baseURL}}/{{path}}" -s "${outputCollectionPath}"`, { silent: true }); const outputCollection = new SDK.Collection(JSON.parse(FS.readFileSync(outputCollectionPath).toString())).toJSON(); updatedRequestObject(sourceCollection.item[0].item[0], 1, 1); @@ -164,7 +164,7 @@ describe('Validate index.js', () => { } const sourceCollection = new SDK.Collection(JSON.parse(FS.readFileSync(collectionPath).toString())).toJSON(); - const commandResponse = exec(`node "index.js" -c "${collectionPath}" -r "/:pathvariable1-1/path/request1-1?query1-1-0" -w "/:pathvariable1-1/path/request1-1?query1-1-0=queryvalue1-1-0-0&test" -s "${outputCollectionPath}"`, { silent: true }); + const commandResponse = exec(`node "bin/main.js" -c "${collectionPath}" -r "/:pathvariable1-1/path/request1-1?query1-1-0" -w "/:pathvariable1-1/path/request1-1?query1-1-0=queryvalue1-1-0-0&test" -s "${outputCollectionPath}"`, { silent: true }); const outputCollection = new SDK.Collection(JSON.parse(FS.readFileSync(outputCollectionPath).toString())).toJSON(); updatedRequestObject(sourceCollection.item[0].item[0], 1, 1); @@ -192,7 +192,7 @@ describe('Validate index.js', () => { } const sourceCollection = new SDK.Collection(JSON.parse(FS.readFileSync(collectionPath).toString())).toJSON(); - const commandResponse = exec(`node "index.js" -c "${collectionPath}" -r "https://www.testdomain0.ie/testpath/:pathvariable1-1/path/request1-1?query1-1-0=queryvalue1-1-0&query1-1-1=queryvalue1-1-1" -w "{{protocol}}://{{baseURL}}/v1/{{path}}" -s "${outputCollectionPath}"`, { silent: true }); + const commandResponse = exec(`node "bin/main.js" -c "${collectionPath}" -r "https://www.testdomain0.ie/testpath/:pathvariable1-1/path/request1-1?query1-1-0=queryvalue1-1-0&query1-1-1=queryvalue1-1-1" -w "{{protocol}}://{{baseURL}}/v1/{{path}}" -s "${outputCollectionPath}"`, { silent: true }); const outputCollection = new SDK.Collection(JSON.parse(FS.readFileSync(outputCollectionPath).toString())).toJSON(); updatedRequestObject(sourceCollection.item[0].item[0], 1, 1); diff --git a/__test__/utils/helperMethods.js b/__test__/utils/helperMethods.js new file mode 100644 index 0000000..fb6414b --- /dev/null +++ b/__test__/utils/helperMethods.js @@ -0,0 +1,23 @@ +function resetAndReimportUrlUpdator({ c, r, w, s, p }) { + jest.resetModules() + while (process.argv.length > 3) { + process.argv.pop(); + } + if (c) process.argv.push('-c', c); + if (r) process.argv.push('-r', r); + if (w) process.argv.push('-w', w); + if (s) process.argv.push('-s', s); + if (p) process.argv.push('-p', p); +} + + +class CustomError extends Error { + constructor(errno) { + super(); + this.errno = errno; + this.message = 'Custom error'; + } +}; + + +module.exports = { resetAndReimportUrlUpdator, CustomError }; \ No newline at end of file diff --git a/bin/main.js b/bin/main.js new file mode 100644 index 0000000..0d15a78 --- /dev/null +++ b/bin/main.js @@ -0,0 +1,3 @@ +#! /usr/bin/env node +let { startConvert } = require('../index.js') +startConvert() diff --git a/index.js b/index.js index 5ce4fb2..7e869e1 100644 --- a/index.js +++ b/index.js @@ -1,4 +1,3 @@ -#! /usr/bin/env node let sourceCollection; const YARGS = require('yargs'), @@ -19,29 +18,34 @@ const YARGS = require('yargs'), COLLECTIONFILE = PATH.parse(OPTIONS.collection_path).base, COLLECTIONDIR = PATH.resolve(PATH.parse(OPTIONS.collection_path).dir); -try { - sourceCollection = new SDK.Collection(JSON.parse(FS.readFileSync(OPTIONS.collection_path).toString())); - //forEachItem has all request details irrespective of folder structure - sourceCollection.forEachItem((requestItem) => { - //stops path variable from resolving - let variables_ = requestItem.request.url.variables.all() - requestItem.request.url.variables.clear() - let currentURL_ = requestItem.request.url.toString() - const newURL = urlReplacer(currentURL_, OPTIONS.replace_url_part, OPTIONS.with_url_part) +function startConvert() { + try { + sourceCollection = new SDK.Collection(JSON.parse(FS.readFileSync(OPTIONS.collection_path).toString())); + //forEachItem has all request details irrespective of folder structure + sourceCollection.forEachItem((requestItem) => { + //stops path variable from resolving + let variables_ = requestItem.request.url.variables.all() + requestItem.request.url.variables.clear() + let currentURL_ = requestItem.request.url.toString() - //add varaibles back if required and update the collection - updateCollection(requestItem, variables_, newURL) - }) + const newURL = urlReplacer(currentURL_, OPTIONS.replace_url_part, OPTIONS.with_url_part) + + //add varaibles back if required and update the collection + updateCollection(requestItem, variables_, newURL) + }) - const destination_ = PATH.resolve(OPTIONS.save_as === DEFAULTS.save_as ? `${COLLECTIONDIR}/new_${COLLECTIONFILE}` : OPTIONS.save_as) - FS.outputFileSync(destination_, JSON.stringify(sourceCollection.toJSON(), null, 2)) - console.log(`File saved to: ${destination_}`) -} catch (e) { - if (!e.errno === 4058) throw Error(e) - console.log(e.message) + const destination_ = PATH.resolve(OPTIONS.save_as === DEFAULTS.save_as ? `${COLLECTIONDIR}/new_${COLLECTIONFILE}` : OPTIONS.save_as) + FS.outputFileSync(destination_, JSON.stringify(sourceCollection.toJSON(), null, 2)) + console.log(`File saved to: ${destination_}`) + } catch (e) { + if (!(e.code === 'ENOENT')) throw Error(e) + console.error(e.message) + process.exit() + } } + function urlReplacer(currentUrl, urlToReplace, urlToReplaceWith) { return currentUrl.replaceAll(urlToReplace, urlToReplaceWith) } @@ -54,3 +58,5 @@ function updateCollection(requestItem, variables, newURL) { }) requestItem.request.url.variables.repopulate(variables) } + +module.exports = {startConvert} \ No newline at end of file diff --git a/package.json b/package.json index 08e3d09..2f3239a 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "yargs": "^17.3.1" }, "bin": { - "postman-collection-url-updater": "./index.js" + "postman-collection-url-updater": "./bin/main.js" }, "files": [ "index.js", @@ -37,5 +37,21 @@ "@types/postman-collection": "^3.5.7", "jest": "^27.4.7", "shelljs": "^0.8.5" + }, + "jest": { + "coverageThreshold": { + "global": { + "branches": 80, + "functions": 80, + "lines": 80, + "statements": -10 + } + }, + "rootDir": "./", + "verbose": true, + "maxWorkers": 1, + "collectCoverageFrom": [ + "index.js" + ] } -} +} \ No newline at end of file