From fd5db6c8c9556ebad1f78d08ccca87ae2399a8bd Mon Sep 17 00:00:00 2001 From: Jason Casareno Date: Tue, 19 Jul 2022 15:56:42 -0700 Subject: [PATCH 01/55] Duplicated and disconnected parameter UI for reuse --- .../components/http/Parameters.vue | 5 + .../components/http/Variables.vue | 175 ++++++++++++++++++ 2 files changed, 180 insertions(+) create mode 100644 packages/hoppscotch-app/components/http/Variables.vue diff --git a/packages/hoppscotch-app/components/http/Parameters.vue b/packages/hoppscotch-app/components/http/Parameters.vue index b070ce125..6b5911ba1 100644 --- a/packages/hoppscotch-app/components/http/Parameters.vue +++ b/packages/hoppscotch-app/components/http/Parameters.vue @@ -148,6 +148,10 @@ /> +
+ + + @@ -167,6 +171,7 @@ import { import isEqual from "lodash/isEqual" import cloneDeep from "lodash/cloneDeep" import draggable from "vuedraggable" +import Variables from "./Variables.vue" import linter from "~/helpers/editor/linting/rawKeyValue" import { useCodemirror } from "~/helpers/editor/codemirror" import { useI18n, useToast, useStream } from "~/helpers/utils/composables" diff --git a/packages/hoppscotch-app/components/http/Variables.vue b/packages/hoppscotch-app/components/http/Variables.vue new file mode 100644 index 000000000..bff82ac42 --- /dev/null +++ b/packages/hoppscotch-app/components/http/Variables.vue @@ -0,0 +1,175 @@ + + + From 21021a3cd971c3fa6a0dd66f70663333cb7c768f Mon Sep 17 00:00:00 2001 From: Jason Casareno Date: Wed, 20 Jul 2022 16:50:34 -0700 Subject: [PATCH 02/55] Removed reference to 'bulk params' --- packages/hoppscotch-app/components/http/Variables.vue | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/hoppscotch-app/components/http/Variables.vue b/packages/hoppscotch-app/components/http/Variables.vue index bff82ac42..d50081542 100644 --- a/packages/hoppscotch-app/components/http/Variables.vue +++ b/packages/hoppscotch-app/components/http/Variables.vue @@ -9,13 +9,11 @@ v-tippy="{ theme: 'tooltip' }" :title="t('add.new')" svg="plus" - :disabled="bulkMode" @click.native="addParamV" /> -
-
+
void } | null>(null) -// The UI representation of the parameters list (has the empty end param) const workingParamsV = ref>([ { id: idTickerV.value++, @@ -107,7 +104,6 @@ const workingParamsV = ref>([ }, ]) -// Rule: Working Params always have last element is always an empty param watch(workingParamsV, (paramsList) => { if (paramsList.length > 0 && paramsList[paramsList.length - 1].key !== "") { workingParamsV.value.push({ From 9b60dc5f2de8ac23dc7042935e0b6db763f0ae0b Mon Sep 17 00:00:00 2001 From: Jason Casareno Date: Thu, 21 Jul 2022 14:21:45 -0700 Subject: [PATCH 03/55] Modified HoppRESTRequest data structure --- .../newstore/localpersistence.ts | 2 ++ packages/hoppscotch-data/src/rest/index.ts | 29 ++++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/packages/hoppscotch-app/newstore/localpersistence.ts b/packages/hoppscotch-app/newstore/localpersistence.ts index a6f7a033a..83c654fb9 100644 --- a/packages/hoppscotch-app/newstore/localpersistence.ts +++ b/packages/hoppscotch-app/newstore/localpersistence.ts @@ -321,6 +321,8 @@ function setupRequestPersistence() { } window.localStorage.setItem("restRequest", JSON.stringify(reqClone)) }) + + console.log("localRequest", localRequest) } export function setupLocalPersistence() { diff --git a/packages/hoppscotch-data/src/rest/index.ts b/packages/hoppscotch-data/src/rest/index.ts index c4fa6d9c0..08993887e 100644 --- a/packages/hoppscotch-data/src/rest/index.ts +++ b/packages/hoppscotch-data/src/rest/index.ts @@ -8,7 +8,7 @@ import { lodashIsEqualEq, mapThenEq, undefinedEq } from "../utils/eq" export * from "./content-types" export * from "./HoppRESTAuth" -export const RESTReqSchemaVersion = "1" +export const RESTReqSchemaVersion = "2" export type HoppRESTParam = { key: string @@ -16,6 +16,11 @@ export type HoppRESTParam = { active: boolean } +export type HoppRESTVar = { + key: string + value: string +} + export type HoppRESTHeader = { key: string value: string @@ -51,6 +56,7 @@ export interface HoppRESTRequest { method: string endpoint: string params: HoppRESTParam[] + vars: HoppRESTVar[] headers: HoppRESTHeader[] preRequestScript: string testScript: string @@ -74,6 +80,10 @@ export const HoppRESTRequestEq = Eq.struct({ (arr) => arr.filter((p) => p.key !== "" && p.value !== ""), lodashIsEqualEq ), + vars: mapThenEq( + (arr) => arr.filter((p) => p.key !== "" && p.value !== ""), + lodashIsEqualEq + ), method: S.Eq, name: S.Eq, preRequestScript: S.Eq, @@ -126,6 +136,9 @@ export function safelyExtractRESTRequest( if (x.hasOwnProperty("params") && Array.isArray(x.params)) req.params = x.params // TODO: Deep nested checks + if (x.hasOwnProperty("vars") && Array.isArray(x.vars)) + req.vars = x.vars // TODO: Deep nested checks + if (x.hasOwnProperty("headers") && Array.isArray(x.headers)) req.headers = x.headers // TODO: Deep nested checks } @@ -186,6 +199,19 @@ export function translateToNewRequest(x: any): HoppRESTRequest { }) ) + const vars: HoppRESTVar[] = (x?.vars ?? []).map( + ({ + key, + value, + }: { + key: string + value: string + }) => ({ + key, + value, + }) + ) + const name = x?.name ?? "Untitled request" const method = x?.method ?? "" @@ -201,6 +227,7 @@ export function translateToNewRequest(x: any): HoppRESTRequest { endpoint, headers, params, + vars, method, preRequestScript, testScript, From 1a629a1219eef544053013e3da5eef4a2cec2e11 Mon Sep 17 00:00:00 2001 From: isaiM6 <98564922+isaiM6@users.noreply.github.com> Date: Thu, 21 Jul 2022 17:25:25 -0700 Subject: [PATCH 04/55] localy stored variable data --- .../components/http/Variables.vue | 98 +++++++++++-------- .../hoppscotch-app/newstore/RESTSession.ts | 67 +++++++++++++ packages/hoppscotch-data/src/rest/index.ts | 2 +- 3 files changed, 123 insertions(+), 44 deletions(-) diff --git a/packages/hoppscotch-app/components/http/Variables.vue b/packages/hoppscotch-app/components/http/Variables.vue index d50081542..f768f4302 100644 --- a/packages/hoppscotch-app/components/http/Variables.vue +++ b/packages/hoppscotch-app/components/http/Variables.vue @@ -9,37 +9,35 @@ v-tippy="{ theme: 'tooltip' }" :title="t('add.new')" svg="plus" - @click.native="addParamV" + @click.native="addVar" />
@@ -49,12 +47,12 @@ :title="t('action.remove')" svg="trash" color="red" - @click.native="deleteParamV(index)" + @click.native="deleteVar(index)" />
@@ -77,14 +75,17 @@ + diff --git a/packages/hoppscotch-app/components/http/QueryParams.vue b/packages/hoppscotch-app/components/http/QueryParams.vue new file mode 100644 index 000000000..b070ce125 --- /dev/null +++ b/packages/hoppscotch-app/components/http/QueryParams.vue @@ -0,0 +1,363 @@ + + + diff --git a/packages/hoppscotch-app/components/http/Variables.vue b/packages/hoppscotch-app/components/http/Variables.vue index 6f57e62f7..16abdde22 100644 --- a/packages/hoppscotch-app/components/http/Variables.vue +++ b/packages/hoppscotch-app/components/http/Variables.vue @@ -5,6 +5,19 @@ >
+ + { O.getOrElseW(() => throwError("Working Params Deletion Out of Bounds")) ) } + +const clearContent = () => { + // set params list to the initial state + workingVars.value = [ + { + id: idTicker.value++, + key: "", + value: "", + }, + ] +} From 775bf9a9c347fee83cafdc74e6359a8616586f98 Mon Sep 17 00:00:00 2001 From: isaiM6 <98564922+isaiM6@users.noreply.github.com> Date: Wed, 3 Aug 2022 16:01:19 -0700 Subject: [PATCH 37/55] Merged environment.ts and variables.ts --- .../components/smart/EnvInput.vue | 1 - .../helpers/utils/EffectiveURL.ts | 3 +- packages/hoppscotch-data/src/environment.ts | 29 +++++++++++++++---- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/packages/hoppscotch-app/components/smart/EnvInput.vue b/packages/hoppscotch-app/components/smart/EnvInput.vue index 1062780fa..81bc6bbdf 100644 --- a/packages/hoppscotch-app/components/smart/EnvInput.vue +++ b/packages/hoppscotch-app/components/smart/EnvInput.vue @@ -229,7 +229,6 @@ onMounted(() => { if (editor.value) { if (!view.value) initView(editor.value) } - console.log("editor.value", editor.value) }) watch(editor, () => { diff --git a/packages/hoppscotch-app/helpers/utils/EffectiveURL.ts b/packages/hoppscotch-app/helpers/utils/EffectiveURL.ts index d2ede9952..276f9d08b 100644 --- a/packages/hoppscotch-app/helpers/utils/EffectiveURL.ts +++ b/packages/hoppscotch-app/helpers/utils/EffectiveURL.ts @@ -14,7 +14,6 @@ import { HoppRESTHeader, HoppRESTParam, } from "@hoppscotch/data" -import { parseTemplateStringV } from "@hoppscotch/data/src/variables" import { arrayFlatMap, arraySort } from "../functional/array" import { toFormData } from "../functional/formData" import { tupleToRecord } from "../functional/record" @@ -306,7 +305,7 @@ export function getEffectiveRESTRequest( return { ...request, - effectiveFinalURL: parseTemplateStringV( + effectiveFinalURL: parseTemplateString( request.endpoint, envVariables, request.vars diff --git a/packages/hoppscotch-data/src/environment.ts b/packages/hoppscotch-data/src/environment.ts index d8db48a3a..424a971a6 100644 --- a/packages/hoppscotch-data/src/environment.ts +++ b/packages/hoppscotch-data/src/environment.ts @@ -16,7 +16,7 @@ export type Variables = { const REGEX_ENV_VAR = /<<([^>]*)>>/g // "<>" -const REGEX_PATH_VAR = /{{([^}]*)}}/g // "{{myVariable}}" +const REGEX_MY_VAR = /{{([^}]*)}}/g // "{{myVariable}}" /** * How much times can we expand environment variables @@ -67,13 +67,20 @@ export const parseBodyEnvVariables = ( export function parseTemplateStringE( str: string, variables: Environment["variables"], + myVariables?: Variables ) { + /* if (!variables || !str ) { return E.right(str) } + */ + if (!variables || !str || !myVariables) { + return E.right(str) + } let result = str let depth = 0 + let errorBound = 0 while (result.match(REGEX_ENV_VAR) != null && depth <= ENV_MAX_EXPAND_LIMIT) { result = decodeURI(encodeURI(result)).replace( @@ -83,9 +90,18 @@ export function parseTemplateStringE( depth++ } - return depth > ENV_MAX_EXPAND_LIMIT - ? E.left(ENV_EXPAND_LOOP) - : E.right(result) + while (result.match(REGEX_MY_VAR) != null && errorBound <= ENV_MAX_EXPAND_LIMIT) { + result = decodeURI(encodeURI(result)).replace( + REGEX_MY_VAR, + (_, p1) => myVariables.find((x) => x.key === p1)?.value || "" + ) + errorBound++ + } + if(depth > ENV_MAX_EXPAND_LIMIT && errorBound <= ENV_MAX_EXPAND_LIMIT) { + return E.right(result) + }else{ + return E.left(ENV_EXPAND_LOOP) + } } /** @@ -93,9 +109,10 @@ export function parseTemplateStringE( */ export const parseTemplateString = ( str: string, - variables: Environment["variables"] + variables: Environment["variables"], + myVariables?: Variables ) => pipe( - parseTemplateStringE(str, variables), + parseTemplateStringE(str, variables, myVariables), E.getOrElse(() => str) ) From 4f71b163eac2cddf91d6cc04008248140fe4f2ef Mon Sep 17 00:00:00 2001 From: Jason Casareno Date: Wed, 3 Aug 2022 16:18:15 -0700 Subject: [PATCH 38/55] Minor changes --- packages/hoppscotch-data/src/environment.ts | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/packages/hoppscotch-data/src/environment.ts b/packages/hoppscotch-data/src/environment.ts index 424a971a6..8124959f9 100644 --- a/packages/hoppscotch-data/src/environment.ts +++ b/packages/hoppscotch-data/src/environment.ts @@ -69,15 +69,10 @@ export function parseTemplateStringE( variables: Environment["variables"], myVariables?: Variables ) { - /* - if (!variables || !str ) { - return E.right(str) - } - */ - if (!variables || !str || !myVariables) { return E.right(str) } + let result = str let depth = 0 let errorBound = 0 @@ -97,11 +92,8 @@ export function parseTemplateStringE( ) errorBound++ } - if(depth > ENV_MAX_EXPAND_LIMIT && errorBound <= ENV_MAX_EXPAND_LIMIT) { - return E.right(result) - }else{ - return E.left(ENV_EXPAND_LOOP) - } + + return depth <= ENV_MAX_EXPAND_LIMIT && errorBound <= ENV_MAX_EXPAND_LIMIT ? E.right(result) : E.left(ENV_EXPAND_LOOP); } /** From d1e6ffda493efba74fe9fa1289581f919942720e Mon Sep 17 00:00:00 2001 From: isaiM6 <98564922+isaiM6@users.noreply.github.com> Date: Wed, 3 Aug 2022 16:21:33 -0700 Subject: [PATCH 39/55] fixed return statement --- packages/hoppscotch-data/src/environment.ts | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/packages/hoppscotch-data/src/environment.ts b/packages/hoppscotch-data/src/environment.ts index 424a971a6..5f854d91b 100644 --- a/packages/hoppscotch-data/src/environment.ts +++ b/packages/hoppscotch-data/src/environment.ts @@ -69,11 +69,6 @@ export function parseTemplateStringE( variables: Environment["variables"], myVariables?: Variables ) { - /* - if (!variables || !str ) { - return E.right(str) - } - */ if (!variables || !str || !myVariables) { return E.right(str) @@ -97,11 +92,8 @@ export function parseTemplateStringE( ) errorBound++ } - if(depth > ENV_MAX_EXPAND_LIMIT && errorBound <= ENV_MAX_EXPAND_LIMIT) { - return E.right(result) - }else{ - return E.left(ENV_EXPAND_LOOP) - } + + return depth <= ENV_MAX_EXPAND_LIMIT && errorBound <= ENV_MAX_EXPAND_LIMIT ? E.right(result) : E.left(ENV_EXPAND_LOOP); } /** From 10615ca1a187c1c1905ae0479bc793d4ac24dcd1 Mon Sep 17 00:00:00 2001 From: isaiM6 <98564922+isaiM6@users.noreply.github.com> Date: Wed, 3 Aug 2022 16:49:31 -0700 Subject: [PATCH 40/55] merge commit --- packages/hoppscotch-data/src/environment.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/hoppscotch-data/src/environment.ts b/packages/hoppscotch-data/src/environment.ts index 157c59525..15804de3b 100644 --- a/packages/hoppscotch-data/src/environment.ts +++ b/packages/hoppscotch-data/src/environment.ts @@ -9,6 +9,11 @@ export type Environment = { }[] } +export type Variables = { + key: string + value: string +}[] + const REGEX_ENV_VAR = /<<([^>]*)>>/g // "<>" const REGEX_MY_VAR = /{{([^}]*)}}/g // "{{myVariable}}" From 21d8b8fb2e272bc2e1a97b233c1eeb24e5d96434 Mon Sep 17 00:00:00 2001 From: Jason Casareno Date: Wed, 3 Aug 2022 17:04:13 -0700 Subject: [PATCH 41/55] Added TODO Comments + File Deletion --- .../components/http/Parameters.vue | 6 +- packages/hoppscotch-data/src/environment.ts | 3 + packages/hoppscotch-data/src/variables.ts | 78 ------------------- 3 files changed, 8 insertions(+), 79 deletions(-) delete mode 100644 packages/hoppscotch-data/src/variables.ts diff --git a/packages/hoppscotch-app/components/http/Parameters.vue b/packages/hoppscotch-app/components/http/Parameters.vue index 31c887c92..6a0be351c 100644 --- a/packages/hoppscotch-app/components/http/Parameters.vue +++ b/packages/hoppscotch-app/components/http/Parameters.vue @@ -6,4 +6,8 @@
- + diff --git a/packages/hoppscotch-data/src/environment.ts b/packages/hoppscotch-data/src/environment.ts index 15804de3b..c3cc2242c 100644 --- a/packages/hoppscotch-data/src/environment.ts +++ b/packages/hoppscotch-data/src/environment.ts @@ -85,6 +85,9 @@ export function parseTemplateStringE( depth++ } + /** + * TODO: Create an error statement for variables + */ while (result.match(REGEX_MY_VAR) != null && errorBound <= ENV_MAX_EXPAND_LIMIT) { result = decodeURI(encodeURI(result)).replace( REGEX_MY_VAR, diff --git a/packages/hoppscotch-data/src/variables.ts b/packages/hoppscotch-data/src/variables.ts deleted file mode 100644 index 8b217d300..000000000 --- a/packages/hoppscotch-data/src/variables.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { pipe } from "fp-ts/function" -import * as E from "fp-ts/Either" -import {parseTemplateStringE} from "./environment"; - -export type Environment = { - name: string - variables: { - key: string - value: string - }[] -} - -export type Variables = { - key: string - value: string -}[] - -const REGEX_ENV_VAR = /<<([^>]*)>>/g // "<>" -const REGEX_MY_VAR = /{{([^}]*)}}/g // "{{myVariable}}" - -/** - * How much times can we expand environment variables - */ -const ENV_MAX_EXPAND_LIMIT = 10 - -/** - * Error state when there is a suspected loop while - * recursively expanding variables - */ -const ENV_EXPAND_LOOP = "ENV_EXPAND_LOOP" as const - -export function parseTemplateStringEV( - str: string, - variables: Environment["variables"], - myVariables: Variables -) { - if (!variables || !str || !myVariables) { - return E.right(str) - } - - let result = str - let depth = 0 - let errorBound = 0 - - while (result.match(REGEX_ENV_VAR) != null && depth <= ENV_MAX_EXPAND_LIMIT) { - result = decodeURI(encodeURI(result)).replace( - REGEX_ENV_VAR, - (_, p1) => variables.find((x) => x.key === p1)?.value || "" - ) - depth++ - } - - /** - * TODO: Create an error statement for variables - */ - while (result.match(REGEX_MY_VAR) != null && errorBound <= ENV_MAX_EXPAND_LIMIT) { - result = decodeURI(encodeURI(result)).replace( - REGEX_MY_VAR, - (_, p1) => myVariables.find((x) => x.key === p1)?.value || "" - ) - errorBound++ - } - - return depth <= ENV_MAX_EXPAND_LIMIT && errorBound <= ENV_MAX_EXPAND_LIMIT ? E.right(result) : E.left(ENV_EXPAND_LOOP); -} - -/** - * @deprecated Use `parseTemplateStringEV` instead - */ -export const parseTemplateStringV = ( - str: string, - variables: Environment["variables"], - myVariables: Variables -) => - pipe( - parseTemplateStringEV(str, variables, myVariables), - E.getOrElse(() => str) - ) From 0c31d9201f9d64c7e94788aee72d56bf8636c051 Mon Sep 17 00:00:00 2001 From: Patrick Prakash Date: Thu, 4 Aug 2022 18:41:19 +0530 Subject: [PATCH 42/55] docs: fix PWA broken link (#2558) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d1ff7e7ae..937a64238 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,7 @@ _Customized themes are synced with cloud / local session_ -🔥 **PWA:** Install as a [PWA](https://developers.google.com/web/progressive-web-apps) on your device. +🔥 **PWA:** Install as a [PWA](https://web.dev/what-are-pwas/) on your device. - Instant loading with Service Workers - Offline support From 73fdfbd2c82b56326cedb8a61dc24fe8dcd4f66a Mon Sep 17 00:00:00 2001 From: Deepanshu Dhruw Date: Thu, 4 Aug 2022 19:19:14 +0530 Subject: [PATCH 43/55] feat: added delay flag in @hoppscotch/cli and related tests (#2527) Co-authored-by: Andrew Bastin --- packages/hoppscotch-cli/package.json | 2 +- .../src/__tests__/commands/test.spec.ts | 43 ++++++++++++++++--- .../request/delayPromiseFunction.spec.ts | 30 +++++++++++++ .../functions/request/processRequest.spec.ts | 21 +++++++-- packages/hoppscotch-cli/src/commands/test.ts | 2 + packages/hoppscotch-cli/src/index.ts | 4 ++ .../hoppscotch-cli/src/options/test/delay.ts | 20 +++++++++ .../hoppscotch-cli/src/types/collections.ts | 1 + packages/hoppscotch-cli/src/types/commands.ts | 1 + packages/hoppscotch-cli/src/types/request.ts | 7 +++ .../hoppscotch-cli/src/utils/collections.ts | 16 ++++++- packages/hoppscotch-cli/src/utils/getters.ts | 5 +++ packages/hoppscotch-cli/src/utils/request.ts | 28 +++++++++--- 13 files changed, 162 insertions(+), 18 deletions(-) create mode 100644 packages/hoppscotch-cli/src/__tests__/functions/request/delayPromiseFunction.spec.ts create mode 100644 packages/hoppscotch-cli/src/options/test/delay.ts diff --git a/packages/hoppscotch-cli/package.json b/packages/hoppscotch-cli/package.json index b7eb100ce..9da4cd233 100644 --- a/packages/hoppscotch-cli/package.json +++ b/packages/hoppscotch-cli/package.json @@ -1,6 +1,6 @@ { "name": "@hoppscotch/cli", - "version": "0.2.1", + "version": "0.3.0", "description": "A CLI to run Hoppscotch test scripts in CI environments.", "homepage": "https://hoppscotch.io", "main": "dist/index.js", diff --git a/packages/hoppscotch-cli/src/__tests__/commands/test.spec.ts b/packages/hoppscotch-cli/src/__tests__/commands/test.spec.ts index 0b69f443b..a1e6861a5 100644 --- a/packages/hoppscotch-cli/src/__tests__/commands/test.spec.ts +++ b/packages/hoppscotch-cli/src/__tests__/commands/test.spec.ts @@ -92,12 +92,41 @@ describe("Test 'hopp test --env ' command:", () => { expect(out).toBe("FILE_NOT_FOUND"); }); - // test("No errors occured (exit code 0).", async () => { - // const TESTS_PATH = getTestJsonFilePath("env-flag-tests.json"); - // const ENV_PATH = getTestJsonFilePath("env-flag-envs.json"); - // const cmd = `node ./bin/hopp test ${TESTS_PATH} --env ${ENV_PATH}`; - // const { error } = await execAsync(cmd); + test("No errors occured (exit code 0).", async () => { + const TESTS_PATH = getTestJsonFilePath("env-flag-tests.json"); + const ENV_PATH = getTestJsonFilePath("env-flag-envs.json"); + const cmd = `node ./bin/hopp test ${TESTS_PATH} --env ${ENV_PATH}`; + const { error } = await execAsync(cmd); - // expect(error).toBeNull(); - // }); + expect(error).toBeNull(); + }); +}); + +describe("Test 'hopp test --delay ' command:", () => { + const VALID_TEST_CMD = `node ./bin/hopp test ${getTestJsonFilePath( + "passes.json" + )}`; + + test("No value passed to delay flag.", async () => { + const cmd = `${VALID_TEST_CMD} --delay`; + const { stdout } = await execAsync(cmd); + const out = getErrorCode(stdout); + + expect(out).toBe("INVALID_ARGUMENT"); + }); + + test("Invalid value passed to delay flag.", async () => { + const cmd = `${VALID_TEST_CMD} --delay 'NaN'`; + const { stdout } = await execAsync(cmd); + const out = getErrorCode(stdout); + + expect(out).toBe("INVALID_ARGUMENT"); + }); + + test("Valid value passed to delay flag.", async () => { + const cmd = `${VALID_TEST_CMD} --delay 1`; + const { error } = await execAsync(cmd); + + expect(error).toBeNull(); + }); }); diff --git a/packages/hoppscotch-cli/src/__tests__/functions/request/delayPromiseFunction.spec.ts b/packages/hoppscotch-cli/src/__tests__/functions/request/delayPromiseFunction.spec.ts new file mode 100644 index 000000000..5f6dd8493 --- /dev/null +++ b/packages/hoppscotch-cli/src/__tests__/functions/request/delayPromiseFunction.spec.ts @@ -0,0 +1,30 @@ +import { hrtime } from "process"; +import { getDurationInSeconds } from "../../../utils/getters"; +import { delayPromiseFunction } from "../../../utils/request"; + +describe("describePromiseFunction", () => { + let promiseFunc = (): Promise => new Promise((resolve) => resolve(2)); + beforeEach(() => { + promiseFunc = (): Promise => new Promise((resolve) => resolve(2)); + }); + + it("Should resolve the promise after 2 seconds.", async () => { + const start = hrtime(); + const res = await delayPromiseFunction(promiseFunc, 2000); + const end = hrtime(start); + const duration = getDurationInSeconds(end); + + expect(Math.floor(duration)).toEqual(2); + expect(typeof res).toBe("number"); + }); + + it("Should resolve the promise after 4 seconds.", async () => { + const start = hrtime(); + const res = await delayPromiseFunction(promiseFunc, 4000); + const end = hrtime(start); + const duration = getDurationInSeconds(end); + + expect(Math.floor(duration)).toEqual(4); + expect(typeof res).toBe("number"); + }); +}); diff --git a/packages/hoppscotch-cli/src/__tests__/functions/request/processRequest.spec.ts b/packages/hoppscotch-cli/src/__tests__/functions/request/processRequest.spec.ts index 2cc73c6cd..b2c9027a0 100644 --- a/packages/hoppscotch-cli/src/__tests__/functions/request/processRequest.spec.ts +++ b/packages/hoppscotch-cli/src/__tests__/functions/request/processRequest.spec.ts @@ -58,7 +58,12 @@ describe("processRequest", () => { (axios as unknown as jest.Mock).mockResolvedValue(DEFAULT_RESPONSE); return expect( - processRequest(SAMPLE_REQUEST, DEFAULT_ENVS, "fake/collection/path")() + processRequest({ + request: SAMPLE_REQUEST, + envs: DEFAULT_ENVS, + path: "fake/collection/path", + delay: 0, + })() ).resolves.toMatchObject({ report: { result: true, @@ -79,7 +84,12 @@ describe("processRequest", () => { (axios as unknown as jest.Mock).mockResolvedValue(DEFAULT_RESPONSE); return expect( - processRequest(SAMPLE_REQUEST, DEFAULT_ENVS, "fake/collection/path")() + processRequest({ + request: SAMPLE_REQUEST, + envs: DEFAULT_ENVS, + path: "fake/collection/path", + delay: 0, + })() ).resolves.toMatchObject({ envs: { selected: [{ key: "ENDPOINT", value: "https://example.com" }], @@ -96,7 +106,12 @@ describe("processRequest", () => { (axios as unknown as jest.Mock).mockResolvedValue(DEFAULT_RESPONSE); return expect( - processRequest(SAMPLE_REQUEST, DEFAULT_ENVS, "fake/request/path")() + processRequest({ + request: SAMPLE_REQUEST, + envs: DEFAULT_ENVS, + path: "fake/request/path", + delay: 0, + })() ).resolves.toMatchObject({ report: { result: false }, }); diff --git a/packages/hoppscotch-cli/src/commands/test.ts b/packages/hoppscotch-cli/src/commands/test.ts index 7159f4632..2f8d6500c 100644 --- a/packages/hoppscotch-cli/src/commands/test.ts +++ b/packages/hoppscotch-cli/src/commands/test.ts @@ -9,12 +9,14 @@ import { handleError } from "../handlers/error"; import { parseCollectionData } from "../utils/mutators"; import { parseEnvsData } from "../options/test/env"; import { TestCmdOptions } from "../types/commands"; +import { parseDelayOption } from "../options/test/delay"; export const test = (path: string, options: TestCmdOptions) => async () => { await pipe( TE.Do, TE.bind("envs", () => parseEnvsData(options.env)), TE.bind("collections", () => parseCollectionData(path)), + TE.bind("delay", () => parseDelayOption(options.delay)), TE.chainTaskK(collectionsRunner), TE.chainW(flow(collectionsRunnerResult, collectionsRunnerExit, TE.of)), TE.mapLeft((e) => { diff --git a/packages/hoppscotch-cli/src/index.ts b/packages/hoppscotch-cli/src/index.ts index d93248f68..aa6b0269f 100644 --- a/packages/hoppscotch-cli/src/index.ts +++ b/packages/hoppscotch-cli/src/index.ts @@ -50,6 +50,10 @@ program "path to a hoppscotch collection.json file for CI testing" ) .option("-e, --env ", "path to an environment variables json file") + .option( + "-d, --delay ", + "delay in milliseconds(ms) between consecutive requests within a collection" + ) .allowExcessArguments(false) .allowUnknownOption(false) .description("running hoppscotch collection.json file") diff --git a/packages/hoppscotch-cli/src/options/test/delay.ts b/packages/hoppscotch-cli/src/options/test/delay.ts new file mode 100644 index 000000000..939d0857d --- /dev/null +++ b/packages/hoppscotch-cli/src/options/test/delay.ts @@ -0,0 +1,20 @@ +import * as TE from "fp-ts/TaskEither"; +import * as S from "fp-ts/string"; +import { pipe } from "fp-ts/function"; +import { error, HoppCLIError } from "../../types/errors"; + +export const parseDelayOption = ( + delay: unknown +): TE.TaskEither => + !S.isString(delay) + ? TE.right(0) + : pipe( + delay, + Number, + TE.fromPredicate(Number.isSafeInteger, () => + error({ + code: "INVALID_ARGUMENT", + data: "Expected '-d, --delay' value to be number", + }) + ) + ); diff --git a/packages/hoppscotch-cli/src/types/collections.ts b/packages/hoppscotch-cli/src/types/collections.ts index 57794954f..0b341fc4b 100644 --- a/packages/hoppscotch-cli/src/types/collections.ts +++ b/packages/hoppscotch-cli/src/types/collections.ts @@ -4,6 +4,7 @@ import { HoppEnvs } from "./request"; export type CollectionRunnerParam = { collections: HoppCollection[]; envs: HoppEnvs; + delay?: number; }; export type HoppCollectionFileExt = "json"; diff --git a/packages/hoppscotch-cli/src/types/commands.ts b/packages/hoppscotch-cli/src/types/commands.ts index 59de3536c..459576bf0 100644 --- a/packages/hoppscotch-cli/src/types/commands.ts +++ b/packages/hoppscotch-cli/src/types/commands.ts @@ -1,5 +1,6 @@ export type TestCmdOptions = { env: string; + delay: number; }; export type HoppEnvFileExt = "json"; diff --git a/packages/hoppscotch-cli/src/types/request.ts b/packages/hoppscotch-cli/src/types/request.ts index 10b53a146..b969de8c8 100644 --- a/packages/hoppscotch-cli/src/types/request.ts +++ b/packages/hoppscotch-cli/src/types/request.ts @@ -26,3 +26,10 @@ export type RequestReport = { result: boolean; duration: { test: number; request: number; preRequest: number }; }; + +export type ProcessRequestParams = { + request: HoppRESTRequest; + envs: HoppEnvs; + path: string; + delay: number; +}; diff --git a/packages/hoppscotch-cli/src/utils/collections.ts b/packages/hoppscotch-cli/src/utils/collections.ts index 3bd8cd1f8..84e3806c5 100644 --- a/packages/hoppscotch-cli/src/utils/collections.ts +++ b/packages/hoppscotch-cli/src/utils/collections.ts @@ -5,7 +5,12 @@ import { bold } from "chalk"; import { log } from "console"; import round from "lodash/round"; import { HoppCollection, HoppRESTRequest } from "@hoppscotch/data"; -import { HoppEnvs, CollectionStack, RequestReport } from "../types/request"; +import { + HoppEnvs, + CollectionStack, + RequestReport, + ProcessRequestParams, +} from "../types/request"; import { getRequestMetrics, preProcessRequest, @@ -41,6 +46,7 @@ export const collectionsRunner = (param: CollectionRunnerParam): T.Task => async () => { const envs: HoppEnvs = param.envs; + const delay = param.delay ?? 0; const requestsReport: RequestReport[] = []; const collectionStack: CollectionStack[] = getCollectionStack( param.collections @@ -54,12 +60,18 @@ export const collectionsRunner = for (const request of collection.requests) { const _request = preProcessRequest(request); const requestPath = `${path}/${_request.name}`; + const processRequestParams: ProcessRequestParams = { + path: requestPath, + request: _request, + envs, + delay, + }; // Request processing initiated message. log(WARN(`\nRunning: ${bold(requestPath)}`)); // Processing current request. - const result = await processRequest(_request, envs, requestPath)(); + const result = await processRequest(processRequestParams)(); // Updating global & selected envs with new envs from processed-request output. const { global, selected } = result.envs; diff --git a/packages/hoppscotch-cli/src/utils/getters.ts b/packages/hoppscotch-cli/src/utils/getters.ts index a60a93af7..fe9c0f919 100644 --- a/packages/hoppscotch-cli/src/utils/getters.ts +++ b/packages/hoppscotch-cli/src/utils/getters.ts @@ -129,3 +129,8 @@ export const getDurationInSeconds = ( const durationInSeconds = (end[0] * 1e9 + end[1]) / 1e9; return round(durationInSeconds, precision); }; + +export const roundDuration = ( + duration: number, + precision: number = DEFAULT_DURATION_PRECISION +) => round(duration, precision); diff --git a/packages/hoppscotch-cli/src/utils/request.ts b/packages/hoppscotch-cli/src/utils/request.ts index 0a332521b..82f002dff 100644 --- a/packages/hoppscotch-cli/src/utils/request.ts +++ b/packages/hoppscotch-cli/src/utils/request.ts @@ -12,7 +12,11 @@ import { testRunner, getTestScriptParams, hasFailedTestCases } from "./test"; import { RequestConfig, EffectiveHoppRESTRequest } from "../interfaces/request"; import { RequestRunnerResponse } from "../interfaces/response"; import { preRequestScriptRunner } from "./pre-request"; -import { HoppEnvs, RequestReport } from "../types/request"; +import { + HoppEnvs, + ProcessRequestParams, + RequestReport, +} from "../types/request"; import { printPreRequestRunner, printRequestRunner, @@ -189,11 +193,11 @@ const getRequest = { */ export const processRequest = ( - request: HoppRESTRequest, - envs: HoppEnvs, - path: string + params: ProcessRequestParams ): T.Task<{ envs: HoppEnvs; report: RequestReport }> => async () => { + const { envs, path, request, delay } = params; + // Initialising updatedEnvs with given parameter envs, will eventually get updated. const result = { envs: envs, @@ -247,7 +251,9 @@ export const processRequest = duration: 0, }; // Executing request-runner. - const requestRunnerRes = await requestRunner(requestConfig)(); + const requestRunnerRes = await delayPromiseFunction< + E.Either + >(requestRunner(requestConfig), delay); if (E.isLeft(requestRunnerRes)) { // Updating report for errors & current result report.errors.push(requestRunnerRes.left); @@ -358,3 +364,15 @@ export const getRequestMetrics = ( hasReqErrors ? { failed: 1, passed: 0 } : { failed: 0, passed: 1 }, (requests) => { requests, duration } ); + +/** + * A function to execute promises with specific delay in milliseconds. + * @param func Function with promise with return type T. + * @param delay TIme in milliseconds to delay function. + * @returns Promise of type same as func. + */ +export const delayPromiseFunction = ( + func: () => Promise, + delay: number +): Promise => + new Promise((resolve) => setTimeout(() => resolve(func()), delay)); From a9e1a3002ea90e7b7a5a1f1c8154aca8bf56a99a Mon Sep 17 00:00:00 2001 From: Anwarul Islam Date: Mon, 8 Aug 2022 17:53:16 +0600 Subject: [PATCH 44/55] Hightlight environment variable with a dash '-' in its name (#2560) --- .../helpers/editor/extensions/HoppEnvironment.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/hoppscotch-app/helpers/editor/extensions/HoppEnvironment.ts b/packages/hoppscotch-app/helpers/editor/extensions/HoppEnvironment.ts index 6111a560f..020b3f18f 100644 --- a/packages/hoppscotch-app/helpers/editor/extensions/HoppEnvironment.ts +++ b/packages/hoppscotch-app/helpers/editor/extensions/HoppEnvironment.ts @@ -16,7 +16,7 @@ import { getAggregateEnvs, } from "~/newstore/environments" -const HOPP_ENVIRONMENT_REGEX = /(<<\w+>>)/g +const HOPP_ENVIRONMENT_REGEX = /(<<[a-zA-Z0-9-_]+>>)/g const HOPP_ENV_HIGHLIGHT = "cursor-help transition rounded px-1 focus:outline-none mx-0.5 env-highlight" @@ -44,8 +44,9 @@ const cursorTooltipField = (aggregateEnvs: AggregateEnvironment[]) => let start = pos let end = pos - while (start > from && /\w/.test(text[start - from - 1])) start-- - while (end < to && /\w/.test(text[end - from])) end++ + while (start > from && /[a-zA-Z0-9-_]+/.test(text[start - from - 1])) + start-- + while (end < to && /[a-zA-Z0-9-_]+/.test(text[end - from])) end++ if ( (start === pos && side < 0) || From 2e1ca0cbb0ee77d459d22e2abd0b6a3fce669ece Mon Sep 17 00:00:00 2001 From: Sagar Date: Wed, 10 Aug 2022 05:41:03 +0600 Subject: [PATCH 45/55] feat: remember pane sizes (#2556) Co-authored-by: Sagar --- .../components/app/PaneLayout.vue | 74 +++++++++++++++++-- .../hoppscotch-app/pages/documentation.vue | 2 +- packages/hoppscotch-app/pages/graphql.vue | 2 +- packages/hoppscotch-app/pages/index.vue | 2 +- .../hoppscotch-app/pages/realtime/mqtt.vue | 2 +- .../pages/realtime/socketio.vue | 2 +- .../hoppscotch-app/pages/realtime/sse.vue | 2 +- .../pages/realtime/websocket.vue | 2 +- 8 files changed, 75 insertions(+), 13 deletions(-) diff --git a/packages/hoppscotch-app/components/app/PaneLayout.vue b/packages/hoppscotch-app/components/app/PaneLayout.vue index e5b0f7079..7064db7f3 100644 --- a/packages/hoppscotch-app/components/app/PaneLayout.vue +++ b/packages/hoppscotch-app/components/app/PaneLayout.vue @@ -6,21 +6,26 @@ '!flex-row-reverse': SIDEBAR_ON_LEFT && mdAndLarger, }" :horizontal="!mdAndLarger" + @resize="setPaneEvent($event, 'vertical')" > - + @@ -29,7 +34,7 @@ @@ -42,8 +47,9 @@ import { Splitpanes, Pane } from "splitpanes" import "splitpanes/dist/splitpanes.css" import { breakpointsTailwind, useBreakpoints } from "@vueuse/core" -import { computed, useSlots } from "@nuxtjs/composition-api" +import { computed, useSlots, ref } from "@nuxtjs/composition-api" import { useSetting } from "~/newstore/settings" +import { setLocalConfig, getLocalConfig } from "~/newstore/localpersistence" const SIDEBAR_ON_LEFT = useSetting("SIDEBAR_ON_LEFT") @@ -57,4 +63,60 @@ const SIDEBAR = useSetting("SIDEBAR") const slots = useSlots() const hasSidebar = computed(() => !!slots.sidebar) + +const props = defineProps({ + layoutId: { + type: String, + default: null, + }, +}) + +type PaneEvent = { + max: number + min: number + size: number +} + +const PANE_SIDEBAR_SIZE = ref(25) +const PANE_MAIN_SIZE = ref(75) +const PANE_MAIN_TOP_SIZE = ref(45) +const PANE_MAIN_BOTTOM_SIZE = ref(65) + +if (!COLUMN_LAYOUT.value) { + PANE_MAIN_TOP_SIZE.value = 50 + PANE_MAIN_BOTTOM_SIZE.value = 50 +} + +function setPaneEvent(event: PaneEvent[], type: "vertical" | "horizontal") { + if (!props.layoutId) return + const storageKey = `${props.layoutId}-pane-config-${type}` + setLocalConfig(storageKey, JSON.stringify(event)) +} + +function populatePaneEvent() { + if (!props.layoutId) return + + const verticalPaneData = getPaneData("vertical") + if (verticalPaneData) { + const [mainPane, sidebarPane] = verticalPaneData + PANE_MAIN_SIZE.value = mainPane?.size + PANE_SIDEBAR_SIZE.value = sidebarPane?.size + } + + const horizontalPaneData = getPaneData("horizontal") + if (horizontalPaneData) { + const [mainTopPane, mainBottomPane] = horizontalPaneData + PANE_MAIN_TOP_SIZE.value = mainTopPane?.size + PANE_MAIN_BOTTOM_SIZE.value = mainBottomPane?.size + } +} + +function getPaneData(type: "vertical" | "horizontal"): PaneEvent[] | null { + const storageKey = `${props.layoutId}-pane-config-${type}` + const paneEvent = getLocalConfig(storageKey) + if (!paneEvent) return null + return JSON.parse(paneEvent) +} + +populatePaneEvent() diff --git a/packages/hoppscotch-app/pages/documentation.vue b/packages/hoppscotch-app/pages/documentation.vue index 8143c3bb5..a5b807a13 100644 --- a/packages/hoppscotch-app/pages/documentation.vue +++ b/packages/hoppscotch-app/pages/documentation.vue @@ -1,5 +1,5 @@