From 9cc1e47b394ca4764f2eaac45205876c24389cd8 Mon Sep 17 00:00:00 2001 From: Akash K <57758277+amk-dev@users.noreply.github.com> Date: Wed, 27 Nov 2024 15:05:35 +0530 Subject: [PATCH] fix: show file chip for the selected file in binary body (#4562) Co-authored-by: jamesgeorge007 <25279263+jamesgeorge007@users.noreply.github.com> --- .../unit/fixtures/workspace-access.mock.ts | 706 +++++++++++++++++- .../__tests__/unit/workspace-access.spec.ts | 34 +- .../hoppscotch-cli/src/options/test/env.ts | 24 +- .../src/utils/workspace-access.ts | 18 +- packages/hoppscotch-common/package.json | 2 +- .../src/components/http/BodyBinary.vue | 8 +- .../inspectors/interceptors.inspector.ts | 4 + .../persistence/__tests__/__mocks__/index.ts | 25 +- packages/hoppscotch-data/package.json | 2 +- .../hoppscotch-selfhost-desktop/package.json | 2 +- pnpm-lock.yaml | 24 +- 11 files changed, 781 insertions(+), 68 deletions(-) diff --git a/packages/hoppscotch-cli/src/__tests__/unit/fixtures/workspace-access.mock.ts b/packages/hoppscotch-cli/src/__tests__/unit/fixtures/workspace-access.mock.ts index 6c79deae3..5c52c1c8e 100644 --- a/packages/hoppscotch-cli/src/__tests__/unit/fixtures/workspace-access.mock.ts +++ b/packages/hoppscotch-cli/src/__tests__/unit/fixtures/workspace-access.mock.ts @@ -178,6 +178,7 @@ export const TRANSFORMED_DEEPLY_NESTED_COLLECTIONS_WITH_AUTH_HEADERS_MOCK: HoppC key: "X-Test-Header", value: "Overriden at FolderB", active: true, + description: "", }, ], }, @@ -475,8 +476,707 @@ export const WORKSPACE_MULTIPLE_CHILD_COLLECTIONS_WITH_AUTH_HEADERS_MOCK: Worksp collectionID: "clx1f86hv000010f8szcfya0t", teamID: "clws3hg58000011o8h07glsb1", title: "root-collection-request", - request: - '{"v":"4","auth":{"authType":"inherit","authActive":true},"body":{"body":null,"contentType":null},"name":"root-collection-request","method":"GET","params":[],"headers":[],"endpoint":"https://httpbin.org/get","testScript":"// Check status code is 200\\npw.test(\\"Status code is 200\\", ()=> {\\n pw.expect(pw.response.status).toBe(200);\\n});\\n\\npw.test(\\"Successfully inherits authorization/header set at the parent collection level\\", () => {\\n pw.expect(pw.response.body.headers[\\"Authorization\\"]).toBe(\\"Basic dGVzdHVzZXI6dGVzdHBhc3M=\\")\\n \\n pw.expect(pw.response.body.headers[\\"Custom-Header\\"]).toBe(\\"Custom header value set at the root collection\\")\\n pw.expect(pw.response.body.headers[\\"Inherited-Header\\"]).toBe(\\"Inherited header at all levels\\")\\n})","preRequestScript":"","requestVariables":[]}', + request: `{"v":"${RESTReqSchemaVersion}","auth":{"authType":"inherit","authActive":true},"body":{"body":null,"contentType":null},"name":"root-collection-request","method":"GET","params":[],"headers":[],"endpoint":"https://httpbin.org/get","testScript":"// Check status code is 200\\npw.test(\\"Status code is 200\\", ()=> {\\n pw.expect(pw.response.status).toBe(200);\\n});\\n\\npw.test(\\"Successfully inherits authorization/header set at the parent collection level\\", () => {\\n pw.expect(pw.response.body.headers[\\"Authorization\\"]).toBe(\\"Basic dGVzdHVzZXI6dGVzdHBhc3M=\\")\\n \\n pw.expect(pw.response.body.headers[\\"Custom-Header\\"]).toBe(\\"Custom header value set at the root collection\\")\\n pw.expect(pw.response.body.headers[\\"Inherited-Header\\"]).toBe(\\"Inherited header at all levels\\")\\n})","preRequestScript":"","requestVariables":[],"responses":{}}`, + }, + ], + }, + ]; + +export const TRANSFORMED_MULTIPLE_CHILD_COLLECTIONS_WITH_AUTH_HEADERS_MOCK: HoppCollection[] = + [ + { + v: 5, + id: "clx1f86hv000010f8szcfya0t", + name: "Multiple child collections with authorization & headers set at each level", + folders: [ + { + v: 5, + id: "clx1fjgah000110f8a5bs68gd", + name: "folder-1", + folders: [ + { + v: 5, + id: "clx1fjwmm000410f8l1gkkr1a", + name: "folder-11", + folders: [], + requests: [ + { + v: "4", + auth: { + authType: "inherit", + password: "testpass", + username: "testuser", + authActive: true, + }, + body: { + body: null, + contentType: null, + }, + name: "folder-11-request", + method: "GET", + params: [], + headers: [], + endpoint: "https://httpbin.org/get", + testScript: + '// Check status code is 200\npw.test("Status code is 200", ()=> {\n pw.expect(pw.response.status).toBe(200);\n});\n\npw.test("Successfully inherits authorization/header set at the parent collection level", () => {\n pw.expect(pw.response.body.headers["Authorization"]).toBe("Basic dGVzdHVzZXI6dGVzdHBhc3M=")\n \n pw.expect(pw.response.body.headers["Custom-Header"]).toBe("Custom header value overriden at folder-1")\n pw.expect(pw.response.body.headers["Inherited-Header"]).toBe("Inherited header at all levels")\n})', + preRequestScript: "", + requestVariables: [], + }, + ], + auth: { + authType: "inherit", + authActive: true, + }, + headers: [ + { + key: "key", + value: "Set at folder-11", + active: true, + description: "", + }, + ], + }, + { + v: 5, + id: "clx1fjyxm000510f8pv90dt43", + name: "folder-12", + folders: [], + requests: [ + { + v: "4", + auth: { + authType: "none", + authActive: true, + }, + body: { + body: null, + contentType: null, + }, + name: "folder-12-request", + method: "GET", + params: [], + headers: [ + { + key: "Custom-Header", + value: + "Custom header value overriden at folder-12-request", + active: true, + }, + { + key: "key", + value: "Overriden at folder-12-request", + active: true, + }, + ], + endpoint: "https://httpbin.org/get", + testScript: + '// Check status code is 200\npw.test("Status code is 200", ()=> {\n pw.expect(pw.response.status).toBe(200);\n});\n\npw.test("Successfully inherits/overrides authorization/header set at the parent collection level", () => {\n pw.expect(pw.response.body.headers["Authorization"]).toBe(undefined)\n \n pw.expect(pw.response.body.headers["Custom-Header"]).toBe("Custom header value overriden at folder-12-request")\n pw.expect(pw.response.body.headers["Inherited-Header"]).toBe("Inherited header at all levels")\n pw.expect(pw.response.body.headers["Key"]).toBe("Overriden at folder-12-request")\n})', + preRequestScript: "", + requestVariables: [], + }, + ], + auth: { + authType: "none", + authActive: true, + }, + headers: [ + { + key: "Custom-Header", + value: "Custom header value overriden at folder-12", + active: true, + description: "", + }, + { + key: "key", + value: "Set at folder-12", + active: true, + description: "", + }, + ], + }, + { + v: 5, + id: "clx1fk1cv000610f88kc3aupy", + name: "folder-13", + folders: [], + requests: [ + { + v: "4", + auth: { + key: "api-key", + addTo: "HEADERS", + value: "api-key-value", + authType: "basic", + password: "testpass", + username: "testuser", + authActive: true, + grantTypeInfo: { + token: "", + isPKCE: true, + clientID: "sfasfa", + password: "", + username: "", + grantType: "AUTHORIZATION_CODE", + authEndpoint: "asfafs", + clientSecret: "sfasfasf", + tokenEndpoint: "asfa", + codeVerifierMethod: "S256", + }, + }, + body: { + body: null, + contentType: null, + }, + name: "folder-13-request", + method: "GET", + params: [], + headers: [ + { + key: "Custom-Header-Request-Level", + value: + "New custom header added at the folder-13-request level", + active: true, + }, + { + key: "key", + value: "Overriden at folder-13-request", + active: true, + }, + ], + endpoint: "https://httpbin.org/get", + testScript: + '// Check status code is 200\npw.test("Status code is 200", ()=> {\n pw.expect(pw.response.status).toBe(200);\n});\n\npw.test("Successfully inherits/overrides authorization/header set at the parent collection level with new header addition", () => {\n pw.expect(pw.response.body.headers["Authorization"]).toBe("Basic dGVzdHVzZXI6dGVzdHBhc3M=")\n \n pw.expect(pw.response.body.headers["Custom-Header"]).toBe("Custom header value overriden at folder-13")\n pw.expect(pw.response.body.headers["Inherited-Header"]).toBe("Inherited header at all levels")\n pw.expect(pw.response.body.headers["Key"]).toBe("Overriden at folder-13-request")\n pw.expect(pw.response.body.headers["Custom-Header-Request-Level"]).toBe("New custom header added at the folder-13-request level")\n})', + preRequestScript: "", + requestVariables: [], + }, + ], + auth: { + token: "test-token", + authType: "bearer", + authActive: true, + }, + headers: [ + { + key: "Custom-Header", + value: "Custom header value overriden at folder-13", + active: true, + description: "", + }, + { + key: "key", + value: "Set at folder-13", + active: true, + description: "", + }, + ], + }, + ], + requests: [ + { + v: "4", + auth: { + authType: "inherit", + authActive: true, + }, + body: { + body: null, + contentType: null, + }, + name: "folder-1-request", + method: "GET", + params: [], + headers: [], + endpoint: "https://httpbin.org/get", + testScript: + '// Check status code is 200\npw.test("Status code is 200", ()=> {\n pw.expect(pw.response.status).toBe(200);\n});\n\npw.test("Successfully inherits authorization/header set at the parent collection level", () => {\n pw.expect(pw.response.body.headers["Authorization"]).toBe("Basic dGVzdHVzZXI6dGVzdHBhc3M=")\n \n pw.expect(pw.response.body.headers["Custom-Header"]).toBe("Custom header value overriden at folder-1")\n pw.expect(pw.response.body.headers["Inherited-Header"]).toBe("Inherited header at all levels")\n})', + preRequestScript: "", + requestVariables: [], + }, + ], + auth: { + authType: "inherit", + authActive: true, + }, + headers: [ + { + key: "Custom-Header", + value: "Custom header value overriden at folder-1", + active: true, + description: "", + }, + ], + }, + { + v: 5, + id: "clx1fjk9o000210f8j0573pls", + name: "folder-2", + folders: [ + { + v: 5, + id: "clx1fk516000710f87sfpw6bo", + name: "folder-21", + folders: [], + requests: [ + { + v: "4", + auth: { + authType: "inherit", + authActive: true, + }, + body: { + body: null, + contentType: null, + }, + name: "folder-21-request", + method: "GET", + params: [], + headers: [], + endpoint: "https://httpbin.org/get", + testScript: + '// Check status code is 200\npw.test("Status code is 200", ()=> {\n pw.expect(pw.response.status).toBe(200);\n});\n\npw.test("Successfully inherits authorization/header set at the parent collection level", () => {\n pw.expect(pw.response.body.headers["Authorization"]).toBe(undefined)\n \n pw.expect(pw.response.body.headers["Custom-Header"]).toBe("Custom header value overriden at folder-2")\n pw.expect(pw.response.body.headers["Inherited-Header"]).toBe("Inherited header at all levels")\n})', + preRequestScript: "", + requestVariables: [], + }, + ], + auth: { + authType: "inherit", + authActive: true, + }, + headers: [ + { + key: "key", + value: "Set at folder-21", + active: true, + description: "", + }, + ], + }, + { + v: 5, + id: "clx1fk72t000810f8gfwkpi5y", + name: "folder-22", + folders: [], + requests: [ + { + v: "4", + auth: { + authType: "none", + authActive: true, + }, + body: { + body: null, + contentType: null, + }, + name: "folder-22-request", + method: "GET", + params: [], + headers: [ + { + key: "Custom-Header", + value: + "Custom header value overriden at folder-22-request", + active: true, + }, + { + key: "key", + value: "Overriden at folder-22-request", + active: true, + }, + ], + endpoint: "https://httpbin.org/get", + testScript: + '// Check status code is 200\npw.test("Status code is 200", ()=> {\n pw.expect(pw.response.status).toBe(200);\n});\n\npw.test("Successfully inherits/overrides authorization/header set at the parent collection level", () => {\n pw.expect(pw.response.body.headers["Authorization"]).toBe(undefined)\n \n pw.expect(pw.response.body.headers["Custom-Header"]).toBe("Custom header value overriden at folder-22-request")\n pw.expect(pw.response.body.headers["Inherited-Header"]).toBe("Inherited header at all levels")\n pw.expect(pw.response.body.headers["Key"]).toBe("Overriden at folder-22-request")\n})', + preRequestScript: "", + requestVariables: [], + }, + ], + auth: { + authType: "none", + authActive: true, + }, + headers: [ + { + key: "Custom-Header", + value: "Custom header value overriden at folder-22", + active: true, + description: "", + }, + { + key: "key", + value: "Set at folder-22", + active: true, + description: "", + }, + ], + }, + { + v: 5, + id: "clx1fk95g000910f8bunhaoo8", + name: "folder-23", + folders: [], + requests: [ + { + v: "4", + auth: { + authType: "basic", + password: "testpass", + username: "testuser", + authActive: true, + }, + body: { + body: null, + contentType: null, + }, + name: "folder-23-request", + method: "GET", + params: [], + headers: [ + { + key: "Custom-Header-Request-Level", + value: + "New custom header added at the folder-23-request level", + active: true, + }, + { + key: "key", + value: "Overriden at folder-23-request", + active: true, + }, + ], + endpoint: "https://httpbin.org/get", + testScript: + '// Check status code is 200\npw.test("Status code is 200", ()=> {\n pw.expect(pw.response.status).toBe(200);\n});\n\npw.test("Successfully inherits/overrides authorization/header set at the parent collection level with new header addition", () => {\n pw.expect(pw.response.body.headers["Authorization"]).toBe("Basic dGVzdHVzZXI6dGVzdHBhc3M=")\n \n pw.expect(pw.response.body.headers["Custom-Header"]).toBe("Custom header value overriden at folder-23")\n pw.expect(pw.response.body.headers["Inherited-Header"]).toBe("Inherited header at all levels")\n pw.expect(pw.response.body.headers["Key"]).toBe("Overriden at folder-23-request")\n pw.expect(pw.response.body.headers["Custom-Header-Request-Level"]).toBe("New custom header added at the folder-23-request level")\n})', + preRequestScript: "", + requestVariables: [], + }, + ], + auth: { + token: "test-token", + authType: "bearer", + password: "testpass", + username: "testuser", + authActive: true, + }, + headers: [ + { + key: "Custom-Header", + value: "Custom header value overriden at folder-23", + active: true, + description: "", + }, + { + key: "key", + value: "Set at folder-23", + active: true, + description: "", + }, + ], + }, + ], + requests: [ + { + v: "4", + auth: { + authType: "none", + authActive: true, + }, + body: { + body: null, + contentType: null, + }, + name: "folder-2-request", + method: "GET", + params: [], + headers: [ + { + key: "Custom-Header", + value: "Custom header value overriden at folder-2-request", + active: true, + }, + ], + endpoint: "https://httpbin.org/get", + testScript: + '// Check status code is 200\npw.test("Status code is 200", ()=> {\n pw.expect(pw.response.status).toBe(200);\n});\n\npw.test("Successfully inherits/overrides authorization/header set at the parent collection level", () => {\n pw.expect(pw.response.body.headers["Authorization"]).toBe(undefined)\n \n pw.expect(pw.response.body.headers["Custom-Header"]).toBe("Custom header value overriden at folder-2-request")\n pw.expect(pw.response.body.headers["Inherited-Header"]).toBe("Inherited header at all levels")\n})', + preRequestScript: "", + requestVariables: [], + }, + ], + auth: { + authType: "none", + authActive: true, + }, + headers: [ + { + key: "Custom-Header", + value: "Custom header value overriden at folder-2", + active: true, + description: "", + }, + ], + }, + { + v: 5, + id: "clx1fjmlq000310f86o4d3w2o", + name: "folder-3", + folders: [ + { + v: 5, + id: "clx1iwq0p003e10f8u8zg0p85", + name: "folder-31", + folders: [], + requests: [ + { + v: "4", + auth: { + authType: "inherit", + authActive: true, + }, + body: { + body: null, + contentType: null, + }, + name: "folder-31-request", + method: "GET", + params: [], + headers: [], + endpoint: "https://httpbin.org/get", + testScript: + '// Check status code is 200\npw.test("Status code is 200", ()=> {\n pw.expect(pw.response.status).toBe(200);\n});\n\npw.test("Successfully inherits authorization/header set at the parent collection level", () => {\n pw.expect(pw.response.body.headers["Authorization"]).toBe("Basic dGVzdHVzZXI6dGVzdHBhc3M=")\n \n pw.expect(pw.response.body.headers["Custom-Header"]).toBe("Custom header value overriden at folder-3")\n pw.expect(pw.response.body.headers["Inherited-Header"]).toBe("Inherited header at all levels")\n})', + preRequestScript: "", + requestVariables: [], + }, + ], + auth: { + authType: "inherit", + authActive: true, + }, + headers: [ + { + key: "key", + value: "Set at folder-31", + active: true, + description: "", + }, + ], + }, + { + v: 5, + id: "clx1izut7003m10f894ip59zg", + name: "folder-32", + folders: [], + requests: [ + { + v: "4", + auth: { + authType: "none", + authActive: true, + }, + body: { + body: null, + contentType: null, + }, + name: "folder-32-request", + method: "GET", + params: [], + headers: [ + { + key: "Custom-Header", + value: + "Custom header value overriden at folder-32-request", + active: true, + }, + { + key: "key", + value: "Overriden at folder-32-request", + active: true, + }, + ], + endpoint: "https://httpbin.org/get", + testScript: + '// Check status code is 200\npw.test("Status code is 200", ()=> {\n pw.expect(pw.response.status).toBe(200);\n});\n\npw.test("Successfully inherits/overrides authorization/header set at the parent collection level", () => {\n pw.expect(pw.response.body.headers["Authorization"]).toBe(undefined)\n \n pw.expect(pw.response.body.headers["Custom-Header"]).toBe("Custom header value overriden at folder-32-request")\n pw.expect(pw.response.body.headers["Inherited-Header"]).toBe("Inherited header at all levels")\n pw.expect(pw.response.body.headers["Key"]).toBe("Overriden at folder-32-request")\n})', + preRequestScript: "", + requestVariables: [], + }, + ], + auth: { + authType: "none", + authActive: true, + }, + headers: [ + { + key: "Custom-Header", + value: "Custom header value overriden at folder-32", + active: true, + description: "", + }, + { + key: "key", + value: "Set at folder-32", + active: true, + description: "", + }, + ], + }, + { + v: 5, + id: "clx1j2ka9003q10f8cdbzpgpg", + name: "folder-33", + folders: [], + requests: [ + { + v: "4", + auth: { + authType: "basic", + password: "testpass", + username: "testuser", + authActive: true, + }, + body: { + body: null, + contentType: null, + }, + name: "folder-33-request", + method: "GET", + params: [], + headers: [ + { + key: "Custom-Header-Request-Level", + value: + "New custom header added at the folder-33-request level", + active: true, + }, + { + key: "key", + value: "Overriden at folder-33-request", + active: true, + }, + ], + endpoint: "https://httpbin.org/get", + testScript: + '// Check status code is 200\npw.test("Status code is 200", ()=> {\n pw.expect(pw.response.status).toBe(200);\n});\n\npw.test("Successfully inherits/overrides authorization/header set at the parent collection level with new header addition", () => {\n pw.expect(pw.response.body.headers["Authorization"]).toBe("Basic dGVzdHVzZXI6dGVzdHBhc3M=")\n \n pw.expect(pw.response.body.headers["Custom-Header"]).toBe("Custom header value overriden at folder-33")\n pw.expect(pw.response.body.headers["Inherited-Header"]).toBe("Inherited header at all levels")\n pw.expect(pw.response.body.headers["Key"]).toBe("Overriden at folder-33-request")\n pw.expect(pw.response.body.headers["Custom-Header-Request-Level"]).toBe("New custom header added at the folder-33-request level")\n})', + preRequestScript: "", + requestVariables: [], + }, + ], + auth: { + token: "test-token", + authType: "bearer", + password: "testpass", + username: "testuser", + authActive: true, + }, + headers: [ + { + key: "Custom-Header", + value: "Custom header value overriden at folder-33", + active: true, + description: "", + }, + { + key: "key", + value: "Set at folder-33", + active: true, + description: "", + }, + ], + }, + ], + requests: [ + { + v: "4", + auth: { + authType: "basic", + password: "testpass", + username: "testuser", + authActive: true, + }, + body: { + body: null, + contentType: null, + }, + name: "folder-3-request", + method: "GET", + params: [], + headers: [ + { + key: "Custom-Header-Request-Level", + value: + "New custom header added at the folder-3-request level", + active: true, + }, + { + key: "key", + value: "Set at folder-3-request", + active: true, + }, + ], + endpoint: "https://httpbin.org/get", + testScript: + '// Check status code is 200\npw.test("Status code is 200", ()=> {\n pw.expect(pw.response.status).toBe(200);\n});\n\npw.test("Successfully inherits/overrides authorization/header set at the parent collection level with new header addition", () => {\n pw.expect(pw.response.body.headers["Authorization"]).toBe("Basic dGVzdHVzZXI6dGVzdHBhc3M=")\n \n pw.expect(pw.response.body.headers["Custom-Header"]).toBe("Custom header value overriden at folder-3")\n pw.expect(pw.response.body.headers["Inherited-Header"]).toBe("Inherited header at all levels")\n pw.expect(pw.response.body.headers["Key"]).toBe("Set at folder-3-request")\n pw.expect(pw.response.body.headers["Custom-Header-Request-Level"]).toBe("New custom header added at the folder-3-request level")\n})', + preRequestScript: "", + requestVariables: [], + }, + ], + auth: { + key: "testuser", + addTo: "HEADERS", + value: "testpass", + authType: "basic", + password: "testpass", + username: "testuser", + authActive: true, + }, + headers: [ + { + key: "Custom-Header", + value: "Custom header value overriden at folder-3", + active: true, + description: "", + }, + ], + }, + ], + requests: [ + { + v: RESTReqSchemaVersion, + auth: { + authType: "inherit", + authActive: true, + }, + body: { + body: null, + contentType: null, + }, + name: "root-collection-request", + method: "GET", + params: [], + headers: [], + endpoint: "https://httpbin.org/get", + testScript: + '// Check status code is 200\npw.test("Status code is 200", ()=> {\n pw.expect(pw.response.status).toBe(200);\n});\n\npw.test("Successfully inherits authorization/header set at the parent collection level", () => {\n pw.expect(pw.response.body.headers["Authorization"]).toBe("Basic dGVzdHVzZXI6dGVzdHBhc3M=")\n \n pw.expect(pw.response.body.headers["Custom-Header"]).toBe("Custom header value set at the root collection")\n pw.expect(pw.response.body.headers["Inherited-Header"]).toBe("Inherited header at all levels")\n})', + preRequestScript: "", + requestVariables: [], + responses: {}, + }, + ], + auth: { + authType: "basic", + password: "testpass", + username: "testuser", + authActive: true, + }, + headers: [ + { + key: "Custom-Header", + value: "Custom header value set at the root collection", + active: true, + description: "", + }, + { + key: "Inherited-Header", + value: "Inherited header at all levels", + active: true, + description: "", }, ], }, @@ -620,6 +1320,7 @@ export const TRANSFORMED_COLLECTIONS_WITHOUT_AUTH_HEADERS_AT_CERTAIN_LEVELS_MOCK key: "Custom-Header", value: "Set at folder-2", active: true, + description: "", }, ], }, @@ -650,6 +1351,7 @@ export const TRANSFORMED_COLLECTIONS_WITHOUT_AUTH_HEADERS_AT_CERTAIN_LEVELS_MOCK key: "Custom-Header", value: "Set at folder-4", active: true, + description: "", }, ], }, diff --git a/packages/hoppscotch-cli/src/__tests__/unit/workspace-access.spec.ts b/packages/hoppscotch-cli/src/__tests__/unit/workspace-access.spec.ts index c119a1c55..51e5dbf2e 100644 --- a/packages/hoppscotch-cli/src/__tests__/unit/workspace-access.spec.ts +++ b/packages/hoppscotch-cli/src/__tests__/unit/workspace-access.spec.ts @@ -1,7 +1,4 @@ -import { HoppCollection } from "@hoppscotch/data"; -import { entityReference } from "verzod"; import { describe, expect, test } from "vitest"; -import { z } from "zod"; import { transformWorkspaceCollections, @@ -11,36 +8,13 @@ import { TRANSFORMED_COLLECTIONS_WITHOUT_AUTH_HEADERS_AT_CERTAIN_LEVELS_MOCK, TRANSFORMED_DEEPLY_NESTED_COLLECTIONS_WITH_AUTH_HEADERS_MOCK, TRANSFORMED_ENVIRONMENT_MOCK, + TRANSFORMED_MULTIPLE_CHILD_COLLECTIONS_WITH_AUTH_HEADERS_MOCK, WORKSPACE_COLLECTIONS_WITHOUT_AUTH_HEADERS_AT_CERTAIN_LEVELS_MOCK, WORKSPACE_DEEPLY_NESTED_COLLECTIONS_WITH_AUTH_HEADERS_MOCK, WORKSPACE_ENVIRONMENT_MOCK, WORKSPACE_MULTIPLE_CHILD_COLLECTIONS_WITH_AUTH_HEADERS_MOCK, } from "./fixtures/workspace-access.mock"; -import TRANSFORMED_MULTIPLE_CHILD_COLLECTIONS_WITH_AUTH_HEADERS_MOCK from "../e2e/fixtures/collections/multiple-child-collections-auth-headers-coll.json"; - -// Helper function to validate against `HoppCollection` schema and apply relevant migrations -const migrateCollections = (collections: unknown[]): HoppCollection[] => { - const collectionSchemaParsedResult = z - .array(entityReference(HoppCollection)) - .safeParse(collections); - - if (!collectionSchemaParsedResult.success) { - throw new Error( - `Incoming collections failed schema validation: ${JSON.stringify(collections, null, 2)}` - ); - } - - return collectionSchemaParsedResult.data.map( - ({ _ref_id, folders, ...rest }) => { - return { - ...rest, - folders: migrateCollections(folders), - }; - } - ); -}; - describe("workspace-access", () => { describe("transformWorkspaceCollection", () => { test("Successfully transforms collection data with deeply nested collections and authorization/headers set at each level to the `HoppCollection` format", () => { @@ -52,15 +26,11 @@ describe("workspace-access", () => { }); test("Successfully transforms collection data with multiple child collections and authorization/headers set at each level to the `HoppCollection` format", () => { - const migratedCollections = migrateCollections([ - TRANSFORMED_MULTIPLE_CHILD_COLLECTIONS_WITH_AUTH_HEADERS_MOCK, - ]); - expect( transformWorkspaceCollections( WORKSPACE_MULTIPLE_CHILD_COLLECTIONS_WITH_AUTH_HEADERS_MOCK ) - ).toEqual(migratedCollections); + ).toEqual(TRANSFORMED_MULTIPLE_CHILD_COLLECTIONS_WITH_AUTH_HEADERS_MOCK); }); test("Adds the default value for `auth` & `header` fields while transforming collections without authorization/headers set at certain levels", () => { diff --git a/packages/hoppscotch-cli/src/options/test/env.ts b/packages/hoppscotch-cli/src/options/test/env.ts index d42450344..cc6746525 100644 --- a/packages/hoppscotch-cli/src/options/test/env.ts +++ b/packages/hoppscotch-cli/src/options/test/env.ts @@ -1,4 +1,4 @@ -import { Environment } from "@hoppscotch/data"; +import { Environment, NonSecretEnvironment } from "@hoppscotch/data"; import { entityReference } from "verzod"; import { z } from "zod"; @@ -63,7 +63,27 @@ export async function parseEnvsData(options: TestCmdEnvironmentOptions) { envPairs.push({ key, value, secret: false }); } } else if (HoppEnvExportObjectResult.type === "ok") { - envPairs.push(...HoppEnvExportObjectResult.value.variables); + // Original environment variables from the supplied export file + const originalEnvVariables = (contents as NonSecretEnvironment).variables; + + // Above environment variables conforming to the latest schema + // `value` fields if specified will be omitted for secret environment variables + const migratedEnvVariables = HoppEnvExportObjectResult.value.variables; + + // The values supplied for secret environment variables have to be considered in the CLI + // For each secret environment variable, include the value in case supplied + const resolvedEnvVariables = migratedEnvVariables.map((variable, idx) => { + if (variable.secret && originalEnvVariables[idx].value) { + return { + ...variable, + value: originalEnvVariables[idx].value, + }; + } + + return variable; + }); + + envPairs.push(...resolvedEnvVariables); } return { global: [], selected: envPairs }; diff --git a/packages/hoppscotch-cli/src/utils/workspace-access.ts b/packages/hoppscotch-cli/src/utils/workspace-access.ts index 063907596..901021c99 100644 --- a/packages/hoppscotch-cli/src/utils/workspace-access.ts +++ b/packages/hoppscotch-cli/src/utils/workspace-access.ts @@ -3,6 +3,8 @@ import { Environment, EnvironmentSchemaVersion, HoppCollection, + HoppRESTAuth, + HoppRESTHeaders, HoppRESTRequest, } from "@hoppscotch/data"; @@ -34,6 +36,7 @@ interface WorkspaceRequest { /** * Transforms the incoming list of workspace requests by applying `JSON.parse` to the `request` field. + * It includes the `v` field indicating the schema version, but migration is handled already at the `parseCollectionData()` helper function. * * @param {WorkspaceRequest[]} requests - An array of workspace request objects to be transformed. * @returns {HoppRESTRequest[]} The transformed array of requests conforming to the `HoppRESTRequest` type. @@ -65,6 +68,8 @@ export const transformWorkspaceEnvironment = ( return variable; }); + // The response doesn't include a way to infer the schema version, so it's set to the latest version + // Any relevant migrations have to be accounted here return { v: EnvironmentSchemaVersion, variables: transformedEnvVars, @@ -84,10 +89,19 @@ export const transformWorkspaceCollections = ( return collections.map((collection) => { const { id, title, data, requests, folders } = collection; - const parsedData = data ? JSON.parse(data) : {}; + const parsedData: { auth?: HoppRESTAuth; headers?: HoppRESTHeaders } = data + ? JSON.parse(data) + : {}; + const { auth = { authType: "inherit", authActive: true }, headers = [] } = parsedData; + const migratedHeaders = headers.map((header) => + header.description ? header : { ...header, description: "" } + ); + + // The response doesn't include a way to infer the schema version, so it's set to the latest version + // Any relevant migrations have to be accounted here return { v: CollectionSchemaVersion, id, @@ -95,7 +109,7 @@ export const transformWorkspaceCollections = ( folders: transformWorkspaceCollections(folders), requests: transformWorkspaceRequests(requests), auth, - headers, + headers: migratedHeaders, }; }); }; diff --git a/packages/hoppscotch-common/package.json b/packages/hoppscotch-common/package.json index b1454e649..2d352dd75 100644 --- a/packages/hoppscotch-common/package.json +++ b/packages/hoppscotch-common/package.json @@ -94,7 +94,7 @@ "url": "0.11.4", "util": "0.12.5", "uuid": "10.0.0", - "verzod": "0.2.2", + "verzod": "0.2.3", "vue": "3.5.12", "vue-i18n": "10.0.4", "vue-pdf-embed": "2.1.0", diff --git a/packages/hoppscotch-common/src/components/http/BodyBinary.vue b/packages/hoppscotch-common/src/components/http/BodyBinary.vue index e8f013f3c..ff0dfdc59 100644 --- a/packages/hoppscotch-common/src/components/http/BodyBinary.vue +++ b/packages/hoppscotch-common/src/components/http/BodyBinary.vue @@ -56,7 +56,11 @@ const handleFileChange = (e: Event) => { } diff --git a/packages/hoppscotch-common/src/services/inspection/inspectors/interceptors.inspector.ts b/packages/hoppscotch-common/src/services/inspection/inspectors/interceptors.inspector.ts index c5d5faaf6..b3cf0fe5f 100644 --- a/packages/hoppscotch-common/src/services/inspection/inspectors/interceptors.inspector.ts +++ b/packages/hoppscotch-common/src/services/inspection/inspectors/interceptors.inspector.ts @@ -33,6 +33,10 @@ export class InterceptorsInspectorService extends Service implements Inspector { req: Readonly> ) { return computed((): InspectorResult[] => { + if (!req.value) { + return [] + } + const isBinaryBody = req.value.body.contentType === "application/octet-stream" diff --git a/packages/hoppscotch-common/src/services/persistence/__tests__/__mocks__/index.ts b/packages/hoppscotch-common/src/services/persistence/__tests__/__mocks__/index.ts index 77f1d9a15..c75f84e7e 100644 --- a/packages/hoppscotch-common/src/services/persistence/__tests__/__mocks__/index.ts +++ b/packages/hoppscotch-common/src/services/persistence/__tests__/__mocks__/index.ts @@ -27,25 +27,31 @@ export const REST_COLLECTIONS_MOCK: HoppCollection[] = [ { v: 5, name: "Echo", - folders: [], requests: [ { v: RESTReqSchemaVersion, - endpoint: "https://echo.hoppscotch.io", name: "Echo test", + method: "GET", + endpoint: "https://echo.hoppscotch.io", params: [], headers: [], - method: "GET", - auth: { authType: "none", authActive: true }, preRequestScript: "", testScript: "", - body: { contentType: null, body: null }, + auth: { + authType: "none", + authActive: true, + }, + body: { + contentType: null, + body: null, + }, requestVariables: [], responses: {}, }, ], auth: { authType: "none", authActive: true }, headers: [], + folders: [], }, ] @@ -53,20 +59,23 @@ export const GQL_COLLECTIONS_MOCK: HoppCollection[] = [ { v: 5, name: "Echo", - folders: [], requests: [ { v: 7, name: "Echo test", url: "https://echo.hoppscotch.io/graphql", headers: [], - variables: '{\n "id": "1"\n}', query: "query Request { url }", - auth: { authType: "none", authActive: true }, + variables: '{\n "id": "1"\n}', + auth: { + authType: "none", + authActive: true, + }, }, ], auth: { authType: "none", authActive: true }, headers: [], + folders: [], }, ] diff --git a/packages/hoppscotch-data/package.json b/packages/hoppscotch-data/package.json index 7349f99c7..08b607ec6 100644 --- a/packages/hoppscotch-data/package.json +++ b/packages/hoppscotch-data/package.json @@ -46,7 +46,7 @@ "lodash": "4.17.21", "parser-ts": "0.7.0", "uuid": "10.0.0", - "verzod": "0.2.2", + "verzod": "0.2.3", "zod": "3.23.8" } } diff --git a/packages/hoppscotch-selfhost-desktop/package.json b/packages/hoppscotch-selfhost-desktop/package.json index 2d2dfd821..9d4d0aadb 100644 --- a/packages/hoppscotch-selfhost-desktop/package.json +++ b/packages/hoppscotch-selfhost-desktop/package.json @@ -36,7 +36,7 @@ "tauri": "link:@tauri-apps/api/tauri", "tauri-plugin-store-api": "0.0.0", "util": "0.12.5", - "verzod": "0.2.2", + "verzod": "0.2.3", "vue": "3.3.9", "workbox-window": "6.6.0", "zod": "3.22.4" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4cdda24c1..f703b2c1a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -667,8 +667,8 @@ importers: specifier: 10.0.0 version: 10.0.0 verzod: - specifier: 0.2.2 - version: 0.2.2(zod@3.23.8) + specifier: 0.2.3 + version: 0.2.3(zod@3.23.8) vue: specifier: 3.5.12 version: 3.5.12(typescript@5.3.3) @@ -908,8 +908,8 @@ importers: specifier: 10.0.0 version: 10.0.0 verzod: - specifier: 0.2.2 - version: 0.2.2(zod@3.23.8) + specifier: 0.2.3 + version: 0.2.3(zod@3.23.8) zod: specifier: 3.23.8 version: 3.23.8 @@ -1066,8 +1066,8 @@ importers: specifier: 0.12.5 version: 0.12.5 verzod: - specifier: 0.2.2 - version: 0.2.2(zod@3.22.4) + specifier: 0.2.3 + version: 0.2.3(zod@3.22.4) vue: specifier: 3.5.12 version: 3.5.12(typescript@4.9.5) @@ -11824,12 +11824,6 @@ packages: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} - verzod@0.2.2: - resolution: {integrity: sha512-TnM0O2SUcXuY63qQ+W+W4/5bDaIhyV9ZDWwL0ztDOawX7q7ar+jHNdYKUR43rf8ku23p2ROgrfoKABjl2IiiZQ==} - engines: {node: '>=16'} - peerDependencies: - zod: ^3.22.0 - verzod@0.2.3: resolution: {integrity: sha512-fARgs0c/TNNtbo83/5LjriJEb3QMwBN8Ju2+BcVdiI7Y2NOa5Yhq+CrQ8UH43h0BRXcgb2JQABjkgrRCWybEtQ==} engines: {node: '>=16'} @@ -25942,14 +25936,10 @@ snapshots: vary@1.1.2: {} - verzod@0.2.2(zod@3.22.4): + verzod@0.2.3(zod@3.22.4): dependencies: zod: 3.22.4 - verzod@0.2.2(zod@3.23.8): - dependencies: - zod: 3.23.8 - verzod@0.2.3(zod@3.23.8): dependencies: zod: 3.23.8