Merge branch 'feat/test-env-updates'
This commit is contained in:
@@ -38,12 +38,18 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from "@nuxtjs/composition-api"
|
import { defineComponent } from "@nuxtjs/composition-api"
|
||||||
import { createEnvironment } from "~/newstore/environments"
|
import { useReadonlyStream } from "~/helpers/utils/composables"
|
||||||
|
import { createEnvironment, environments$ } from "~/newstore/environments"
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
show: Boolean,
|
show: Boolean,
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
return {
|
||||||
|
envList: useReadonlyStream(environments$, []),
|
||||||
|
}
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
name: null as string | null,
|
name: null as string | null,
|
||||||
@@ -56,6 +62,11 @@ export default defineComponent({
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
createEnvironment(this.name)
|
createEnvironment(this.name)
|
||||||
|
// TODO: find better way to get index of new environment
|
||||||
|
this.$emit("environment-added", {
|
||||||
|
name: this.name,
|
||||||
|
index: this.envList.length - 1,
|
||||||
|
})
|
||||||
this.hideModal()
|
this.hideModal()
|
||||||
},
|
},
|
||||||
hideModal() {
|
hideModal() {
|
||||||
|
|||||||
@@ -3,7 +3,9 @@
|
|||||||
<div
|
<div
|
||||||
v-if="
|
v-if="
|
||||||
testResults &&
|
testResults &&
|
||||||
(testResults.expectResults.length || testResults.tests.length)
|
(testResults.expectResults.length ||
|
||||||
|
testResults.tests.length ||
|
||||||
|
haveEnvVariables)
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@@ -20,6 +22,78 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="border-b divide-y-4 divide-dividerLight border-dividerLight">
|
<div class="border-b divide-y-4 divide-dividerLight border-dividerLight">
|
||||||
|
<div v-if="haveEnvVariables" class="flex flex-col">
|
||||||
|
<details class="flex flex-col divide-y divide-dividerLight" open>
|
||||||
|
<summary
|
||||||
|
class="flex items-center justify-between flex-1 min-w-0 cursor-pointer transition focus:outline-none text-secondaryLight text-tiny group"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="px-4 py-2 truncate transition group-hover:text-secondary capitalize-first"
|
||||||
|
>
|
||||||
|
{{ t("environment.title") }}
|
||||||
|
</span>
|
||||||
|
</summary>
|
||||||
|
<div class="divide-y divide-dividerLight">
|
||||||
|
<div
|
||||||
|
v-if="noEnvSelected && !globalHasAdditions"
|
||||||
|
class="flex bg-error p-4 text-secondaryDark"
|
||||||
|
>
|
||||||
|
<i class="mr-4 material-icons"> warning </i>
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<p>
|
||||||
|
{{ t("environment.no_environment_description") }}
|
||||||
|
</p>
|
||||||
|
<p class="space-x-2 flex mt-3">
|
||||||
|
<ButtonSecondary
|
||||||
|
:label="t('environment.add_to_global')"
|
||||||
|
class="text-tiny !bg-primary"
|
||||||
|
filled
|
||||||
|
@click.native="addEnvToGlobal()"
|
||||||
|
/>
|
||||||
|
<ButtonSecondary
|
||||||
|
:label="t('environment.create_new')"
|
||||||
|
class="text-tiny !bg-primary"
|
||||||
|
filled
|
||||||
|
@click.native="displayModalAdd(true)"
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<HttpTestResultEnv
|
||||||
|
v-for="(env, index) in testResults.envDiff.global.additions"
|
||||||
|
:key="`env-${env.key}-${index}`"
|
||||||
|
:env="env"
|
||||||
|
status="additions"
|
||||||
|
global
|
||||||
|
/>
|
||||||
|
<HttpTestResultEnv
|
||||||
|
v-for="(env, index) in testResults.envDiff.global.updations"
|
||||||
|
:key="`env-${env.key}-${index}`"
|
||||||
|
:env="env"
|
||||||
|
status="updations"
|
||||||
|
global
|
||||||
|
/>
|
||||||
|
<HttpTestResultEnv
|
||||||
|
v-for="(env, index) in testResults.envDiff.selected.additions"
|
||||||
|
:key="`env-${env.key}-${index}`"
|
||||||
|
:env="env"
|
||||||
|
status="additions"
|
||||||
|
/>
|
||||||
|
<HttpTestResultEnv
|
||||||
|
v-for="(env, index) in testResults.envDiff.selected.updations"
|
||||||
|
:key="`env-${env.key}-${index}`"
|
||||||
|
:env="env"
|
||||||
|
status="updations"
|
||||||
|
/>
|
||||||
|
<HttpTestResultEnv
|
||||||
|
v-for="(env, index) in testResults.envDiff.selected.deletions"
|
||||||
|
:key="`env-${env.key}-${index}`"
|
||||||
|
:env="env"
|
||||||
|
status="deletions"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
</div>
|
||||||
<div v-if="testResults.tests" class="divide-y-4 divide-dividerLight">
|
<div v-if="testResults.tests" class="divide-y-4 divide-dividerLight">
|
||||||
<HttpTestResultEntry
|
<HttpTestResultEntry
|
||||||
v-for="(result, index) in testResults.tests"
|
v-for="(result, index) in testResults.tests"
|
||||||
@@ -107,16 +181,97 @@
|
|||||||
class="my-4"
|
class="my-4"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<EnvironmentsAdd
|
||||||
|
:show="showModalAdd"
|
||||||
|
@hide-modal="displayModalAdd(false)"
|
||||||
|
@environment-added="createNewEnv($event)"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useReadonlyStream, useI18n } from "~/helpers/utils/composables"
|
import { computed, Ref, ref } from "@nuxtjs/composition-api"
|
||||||
|
import isEqual from "lodash/isEqual"
|
||||||
|
import {
|
||||||
|
useReadonlyStream,
|
||||||
|
useI18n,
|
||||||
|
useStream,
|
||||||
|
} from "~/helpers/utils/composables"
|
||||||
|
import {
|
||||||
|
globalEnv$,
|
||||||
|
selectedEnvIndex$,
|
||||||
|
setCurrentEnvironment,
|
||||||
|
setGlobalEnvVariables,
|
||||||
|
updateEnvironment,
|
||||||
|
} from "~/newstore/environments"
|
||||||
import { restTestResults$, setRESTTestResults } from "~/newstore/RESTSession"
|
import { restTestResults$, setRESTTestResults } from "~/newstore/RESTSession"
|
||||||
|
import { HoppTestResult } from "~/helpers/types/HoppTestResult"
|
||||||
|
|
||||||
const t = useI18n()
|
const t = useI18n()
|
||||||
|
|
||||||
const testResults = useReadonlyStream(restTestResults$, null)
|
const showModalAdd = ref(false)
|
||||||
|
|
||||||
|
const displayModalAdd = (shouldDisplay: boolean) => {
|
||||||
|
showModalAdd.value = shouldDisplay
|
||||||
|
}
|
||||||
|
|
||||||
|
const testResults = useReadonlyStream(
|
||||||
|
restTestResults$,
|
||||||
|
null
|
||||||
|
) as Ref<HoppTestResult | null>
|
||||||
|
|
||||||
const clearContent = () => setRESTTestResults(null)
|
const clearContent = () => setRESTTestResults(null)
|
||||||
|
|
||||||
|
const haveEnvVariables = computed(() => {
|
||||||
|
if (!testResults.value) return false
|
||||||
|
return (
|
||||||
|
testResults.value.envDiff.global.additions.length ||
|
||||||
|
testResults.value.envDiff.global.updations.length ||
|
||||||
|
testResults.value.envDiff.global.deletions.length ||
|
||||||
|
testResults.value.envDiff.selected.additions.length ||
|
||||||
|
testResults.value.envDiff.selected.updations.length ||
|
||||||
|
testResults.value.envDiff.selected.deletions.length
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
const selectedEnvironmentIndex = useStream(
|
||||||
|
selectedEnvIndex$,
|
||||||
|
-1,
|
||||||
|
setCurrentEnvironment
|
||||||
|
)
|
||||||
|
|
||||||
|
const globalEnvVars = useReadonlyStream(globalEnv$, []) as Ref<
|
||||||
|
Array<{
|
||||||
|
key: string
|
||||||
|
value: string
|
||||||
|
}>
|
||||||
|
>
|
||||||
|
|
||||||
|
const noEnvSelected = computed(() => selectedEnvironmentIndex.value === -1)
|
||||||
|
|
||||||
|
const globalHasAdditions = computed(() => {
|
||||||
|
if (!testResults.value?.envDiff.selected.additions) return false
|
||||||
|
return (
|
||||||
|
testResults.value.envDiff.selected.additions.every(
|
||||||
|
(x) => globalEnvVars.value.findIndex((y) => isEqual(x, y)) !== -1
|
||||||
|
) ?? false
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
const addEnvToGlobal = () => {
|
||||||
|
if (!testResults.value?.envDiff.selected.additions) return
|
||||||
|
setGlobalEnvVariables([
|
||||||
|
...globalEnvVars.value,
|
||||||
|
...testResults.value.envDiff.selected.additions,
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
const createNewEnv = ({ name, index }: { name: string; index: number }) => {
|
||||||
|
if (!testResults.value?.envDiff.selected.additions) return
|
||||||
|
updateEnvironment(index, {
|
||||||
|
name,
|
||||||
|
variables: testResults.value.envDiff.selected.additions,
|
||||||
|
})
|
||||||
|
setCurrentEnvironment(index)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
83
packages/hoppscotch-app/components/http/TestResultEnv.vue
Normal file
83
packages/hoppscotch-app/components/http/TestResultEnv.vue
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
<template>
|
||||||
|
<div class="flex items-center justify-between px-4 py-2">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<i
|
||||||
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
|
class="mr-4 material-icons cursor-help"
|
||||||
|
:class="getStyle(status)"
|
||||||
|
:title="`${t(getTooltip(status))}`"
|
||||||
|
>
|
||||||
|
{{ getIcon(status) }}
|
||||||
|
</i>
|
||||||
|
<span class="text-secondaryDark">
|
||||||
|
{{ env.key }}
|
||||||
|
</span>
|
||||||
|
<span class="text-secondaryDark">
|
||||||
|
{{ ` \xA0 — \xA0 ${env.value}` }}
|
||||||
|
</span>
|
||||||
|
<span v-if="status === 'updations'" class="text-secondaryLight">
|
||||||
|
{{ ` \xA0 ← \xA0 ${env.previousValue}` }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
v-if="global"
|
||||||
|
class="bg-accentLight px-1 rounded text-accentContrast text-tiny"
|
||||||
|
>
|
||||||
|
Global
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { useI18n } from "~/helpers/utils/composables"
|
||||||
|
|
||||||
|
type Status = "updations" | "additions" | "deletions"
|
||||||
|
type Props = {
|
||||||
|
env: {
|
||||||
|
key: string
|
||||||
|
value: string
|
||||||
|
previousValue?: string
|
||||||
|
}
|
||||||
|
status: Status
|
||||||
|
global: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
withDefaults(defineProps<Props>(), {
|
||||||
|
global: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
const t = useI18n()
|
||||||
|
|
||||||
|
const getIcon = (status: Status) => {
|
||||||
|
switch (status) {
|
||||||
|
case "additions":
|
||||||
|
return "add_circle"
|
||||||
|
case "updations":
|
||||||
|
return "check_circle"
|
||||||
|
case "deletions":
|
||||||
|
return "remove_circle"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getStyle = (status: Status) => {
|
||||||
|
switch (status) {
|
||||||
|
case "additions":
|
||||||
|
return "text-green-500"
|
||||||
|
case "updations":
|
||||||
|
return "text-yellow-500"
|
||||||
|
case "deletions":
|
||||||
|
return "text-red-500"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getTooltip = (status: Status) => {
|
||||||
|
switch (status) {
|
||||||
|
case "additions":
|
||||||
|
return "environment.added"
|
||||||
|
case "updations":
|
||||||
|
return "environment.updated"
|
||||||
|
case "deletions":
|
||||||
|
return "environment.deleted"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -24,7 +24,11 @@
|
|||||||
:label="$t('test.results')"
|
:label="$t('test.results')"
|
||||||
:indicator="
|
:indicator="
|
||||||
testResults &&
|
testResults &&
|
||||||
(testResults.expectResults.length || testResults.tests.length)
|
(testResults.expectResults.length ||
|
||||||
|
testResults.tests.length ||
|
||||||
|
testResults.envDiff.selected.additions.length ||
|
||||||
|
testResults.envDiff.selected.updations.length ||
|
||||||
|
testResults.envDiff.global.updations.length)
|
||||||
? true
|
? true
|
||||||
: false
|
: false
|
||||||
"
|
"
|
||||||
|
|||||||
@@ -1,10 +1,17 @@
|
|||||||
import { Observable } from "rxjs"
|
import { Observable } from "rxjs"
|
||||||
import { filter } from "rxjs/operators"
|
import { filter } from "rxjs/operators"
|
||||||
import { chain, right, TaskEither } from "fp-ts/lib/TaskEither"
|
import { chain, right, TaskEither } from "fp-ts/lib/TaskEither"
|
||||||
import { pipe } from "fp-ts/function"
|
import { flow, pipe } from "fp-ts/function"
|
||||||
import * as O from "fp-ts/Option"
|
import * as O from "fp-ts/Option"
|
||||||
import { runTestScript, TestDescriptor } from "@hoppscotch/js-sandbox"
|
import * as A from "fp-ts/Array"
|
||||||
|
import { Environment } from "@hoppscotch/data"
|
||||||
|
import {
|
||||||
|
SandboxTestResult,
|
||||||
|
runTestScript,
|
||||||
|
TestDescriptor,
|
||||||
|
} from "@hoppscotch/js-sandbox"
|
||||||
import { isRight } from "fp-ts/Either"
|
import { isRight } from "fp-ts/Either"
|
||||||
|
import cloneDeep from "lodash/cloneDeep"
|
||||||
import {
|
import {
|
||||||
getCombinedEnvVariables,
|
getCombinedEnvVariables,
|
||||||
getFinalEnvsFromPreRequest,
|
getFinalEnvsFromPreRequest,
|
||||||
@@ -15,6 +22,14 @@ import { createRESTNetworkRequestStream } from "./network"
|
|||||||
import { HoppTestData, HoppTestResult } from "./types/HoppTestResult"
|
import { HoppTestData, HoppTestResult } from "./types/HoppTestResult"
|
||||||
import { isJSONContentType } from "./utils/contenttypes"
|
import { isJSONContentType } from "./utils/contenttypes"
|
||||||
import { getRESTRequest, setRESTTestResults } from "~/newstore/RESTSession"
|
import { getRESTRequest, setRESTTestResults } from "~/newstore/RESTSession"
|
||||||
|
import {
|
||||||
|
environmentsStore,
|
||||||
|
getCurrentEnvironment,
|
||||||
|
getEnviroment,
|
||||||
|
getGlobalVariables,
|
||||||
|
setGlobalEnvVariables,
|
||||||
|
updateEnvironment,
|
||||||
|
} from "~/newstore/environments"
|
||||||
|
|
||||||
const getTestableBody = (
|
const getTestableBody = (
|
||||||
res: HoppRESTResponse & { type: "success" | "fail" }
|
res: HoppRESTResponse & { type: "success" | "fail" }
|
||||||
@@ -43,6 +58,11 @@ const getTestableBody = (
|
|||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const combineEnvVariables = (env: {
|
||||||
|
global: Environment["variables"]
|
||||||
|
selected: Environment["variables"]
|
||||||
|
}) => [...env.selected, ...env.global]
|
||||||
|
|
||||||
export const runRESTRequest$ = (): TaskEither<
|
export const runRESTRequest$ = (): TaskEither<
|
||||||
string | Error,
|
string | Error,
|
||||||
Observable<HoppRESTResponse>
|
Observable<HoppRESTResponse>
|
||||||
@@ -55,7 +75,7 @@ export const runRESTRequest$ = (): TaskEither<
|
|||||||
chain((envs) => {
|
chain((envs) => {
|
||||||
const effectiveRequest = getEffectiveRESTRequest(getRESTRequest(), {
|
const effectiveRequest = getEffectiveRESTRequest(getRESTRequest(), {
|
||||||
name: "Env",
|
name: "Env",
|
||||||
variables: envs,
|
variables: combineEnvVariables(envs),
|
||||||
})
|
})
|
||||||
|
|
||||||
const stream = createRESTNetworkRequestStream(effectiveRequest)
|
const stream = createRESTNetworkRequestStream(effectiveRequest)
|
||||||
@@ -65,7 +85,7 @@ export const runRESTRequest$ = (): TaskEither<
|
|||||||
.pipe(filter((res) => res.type === "success" || res.type === "fail"))
|
.pipe(filter((res) => res.type === "success" || res.type === "fail"))
|
||||||
.subscribe(async (res) => {
|
.subscribe(async (res) => {
|
||||||
if (res.type === "success" || res.type === "fail") {
|
if (res.type === "success" || res.type === "fail") {
|
||||||
const runResult = await runTestScript(res.req.testScript, {
|
const runResult = await runTestScript(res.req.testScript, envs, {
|
||||||
status: res.statusCode,
|
status: res.statusCode,
|
||||||
body: getTestableBody(res),
|
body: getTestableBody(res),
|
||||||
headers: res.headers,
|
headers: res.headers,
|
||||||
@@ -73,11 +93,38 @@ export const runRESTRequest$ = (): TaskEither<
|
|||||||
|
|
||||||
if (isRight(runResult)) {
|
if (isRight(runResult)) {
|
||||||
setRESTTestResults(translateToSandboxTestResults(runResult.right))
|
setRESTTestResults(translateToSandboxTestResults(runResult.right))
|
||||||
|
|
||||||
|
setGlobalEnvVariables(runResult.right.envs.global)
|
||||||
|
|
||||||
|
if (environmentsStore.value.currentEnvironmentIndex !== -1) {
|
||||||
|
const env = getEnviroment(
|
||||||
|
environmentsStore.value.currentEnvironmentIndex
|
||||||
|
)
|
||||||
|
updateEnvironment(
|
||||||
|
environmentsStore.value.currentEnvironmentIndex,
|
||||||
|
{
|
||||||
|
name: env.name,
|
||||||
|
variables: runResult.right.envs.selected,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
setRESTTestResults({
|
setRESTTestResults({
|
||||||
description: "",
|
description: "",
|
||||||
expectResults: [],
|
expectResults: [],
|
||||||
tests: [],
|
tests: [],
|
||||||
|
envDiff: {
|
||||||
|
global: {
|
||||||
|
additions: [],
|
||||||
|
deletions: [],
|
||||||
|
updations: [],
|
||||||
|
},
|
||||||
|
selected: {
|
||||||
|
additions: [],
|
||||||
|
deletions: [],
|
||||||
|
updations: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
scriptError: true,
|
scriptError: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -90,8 +137,47 @@ export const runRESTRequest$ = (): TaskEither<
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const getAddedEnvVariables = (
|
||||||
|
current: Environment["variables"],
|
||||||
|
updated: Environment["variables"]
|
||||||
|
) => updated.filter((x) => current.findIndex((y) => y.key === x.key) === -1)
|
||||||
|
|
||||||
|
const getRemovedEnvVariables = (
|
||||||
|
current: Environment["variables"],
|
||||||
|
updated: Environment["variables"]
|
||||||
|
) => current.filter((x) => updated.findIndex((y) => y.key === x.key) === -1)
|
||||||
|
|
||||||
|
const getUpdatedEnvVariables = (
|
||||||
|
current: Environment["variables"],
|
||||||
|
updated: Environment["variables"]
|
||||||
|
) =>
|
||||||
|
pipe(
|
||||||
|
updated,
|
||||||
|
A.filterMap(
|
||||||
|
flow(
|
||||||
|
O.of,
|
||||||
|
O.bindTo("env"),
|
||||||
|
O.bind("index", ({ env }) =>
|
||||||
|
pipe(
|
||||||
|
current.findIndex((x) => x.key === env.key),
|
||||||
|
O.fromPredicate((x) => x !== -1)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
O.chain(
|
||||||
|
O.fromPredicate(
|
||||||
|
({ env, index }) => env.value !== current[index].value
|
||||||
|
)
|
||||||
|
),
|
||||||
|
O.map(({ env, index }) => ({
|
||||||
|
...env,
|
||||||
|
previousValue: current[index].value,
|
||||||
|
}))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
function translateToSandboxTestResults(
|
function translateToSandboxTestResults(
|
||||||
testDesc: TestDescriptor
|
testDesc: SandboxTestResult
|
||||||
): HoppTestResult {
|
): HoppTestResult {
|
||||||
const translateChildTests = (child: TestDescriptor): HoppTestData => {
|
const translateChildTests = (child: TestDescriptor): HoppTestData => {
|
||||||
return {
|
return {
|
||||||
@@ -100,10 +186,32 @@ function translateToSandboxTestResults(
|
|||||||
tests: child.children.map(translateChildTests),
|
tests: child.children.map(translateChildTests),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const globals = cloneDeep(getGlobalVariables())
|
||||||
|
const env = cloneDeep(getCurrentEnvironment())
|
||||||
|
|
||||||
return {
|
return {
|
||||||
description: "",
|
description: "",
|
||||||
expectResults: testDesc.expectResults,
|
expectResults: testDesc.tests.expectResults,
|
||||||
tests: testDesc.children.map(translateChildTests),
|
tests: testDesc.tests.children.map(translateChildTests),
|
||||||
scriptError: false,
|
scriptError: false,
|
||||||
|
envDiff: {
|
||||||
|
global: {
|
||||||
|
additions: getAddedEnvVariables(globals, testDesc.envs.global),
|
||||||
|
deletions: getRemovedEnvVariables(globals, testDesc.envs.global),
|
||||||
|
updations: getUpdatedEnvVariables(globals, testDesc.envs.global),
|
||||||
|
},
|
||||||
|
selected: {
|
||||||
|
additions: getAddedEnvVariables(env.variables, testDesc.envs.selected),
|
||||||
|
deletions: getRemovedEnvVariables(
|
||||||
|
env.variables,
|
||||||
|
testDesc.envs.selected
|
||||||
|
),
|
||||||
|
updations: getUpdatedEnvVariables(
|
||||||
|
env.variables,
|
||||||
|
testDesc.envs.selected
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,29 +1,20 @@
|
|||||||
import { runPreRequestScript } from "@hoppscotch/js-sandbox"
|
import { runPreRequestScript } from "@hoppscotch/js-sandbox"
|
||||||
|
import { Environment } from "@hoppscotch/data"
|
||||||
|
import cloneDeep from "lodash/cloneDeep"
|
||||||
import {
|
import {
|
||||||
getCurrentEnvironment,
|
getCurrentEnvironment,
|
||||||
getGlobalVariables,
|
getGlobalVariables,
|
||||||
} from "~/newstore/environments"
|
} from "~/newstore/environments"
|
||||||
|
|
||||||
export const getCombinedEnvVariables = () => {
|
export const getCombinedEnvVariables = () => ({
|
||||||
const variables: { key: string; value: string }[] = [...getGlobalVariables()]
|
global: cloneDeep(getGlobalVariables()),
|
||||||
|
selected: cloneDeep(getCurrentEnvironment().variables),
|
||||||
for (const variable of getCurrentEnvironment().variables) {
|
})
|
||||||
const index = variables.findIndex((v) => variable.key === v.key)
|
|
||||||
|
|
||||||
if (index === -1) {
|
|
||||||
variables.push({
|
|
||||||
key: variable.key,
|
|
||||||
value: variable.value,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
variables[index].value = variable.value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return variables
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getFinalEnvsFromPreRequest = (
|
export const getFinalEnvsFromPreRequest = (
|
||||||
script: string,
|
script: string,
|
||||||
envs: { key: string; value: string }[]
|
envs: {
|
||||||
|
global: Environment["variables"]
|
||||||
|
selected: Environment["variables"]
|
||||||
|
}
|
||||||
) => runPreRequestScript(script, envs)
|
) => runPreRequestScript(script, envs)
|
||||||
|
|||||||
@@ -2,7 +2,10 @@
|
|||||||
"!name": "pw-pre",
|
"!name": "pw-pre",
|
||||||
"pw": {
|
"pw": {
|
||||||
"env": {
|
"env": {
|
||||||
"set": "fn(key: string, value: string)"
|
"set": "fn(key: string, value: string)",
|
||||||
|
"get": "fn(key: string) -> string",
|
||||||
|
"getResolve": "fn(key: string) -> string",
|
||||||
|
"resolve": "fn(value: string) -> string"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,12 @@
|
|||||||
"headers": "?",
|
"headers": "?",
|
||||||
"body": "?"
|
"body": "?"
|
||||||
},
|
},
|
||||||
|
"env": {
|
||||||
|
"set": "fn(key: string, value: string)",
|
||||||
|
"get": "fn(key: string) -> string",
|
||||||
|
"getResolve": "fn(key: string) -> string",
|
||||||
|
"resolve": "fn(value: string) -> string"
|
||||||
|
},
|
||||||
"test": "fn(name: string, func: fn())"
|
"test": "fn(name: string, func: fn())"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
export default [
|
export default [
|
||||||
|
{
|
||||||
|
name: "Environment: Set an environment variable",
|
||||||
|
script: `\n\n// Set an environment variable
|
||||||
|
pw.env.set("variable", "value");`,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "Response: Status code is 200",
|
name: "Response: Status code is 200",
|
||||||
script: `\n\n// Check status code is 200
|
script: `\n\n// Check status code is 200
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { Environment } from "@hoppscotch/data"
|
||||||
|
|
||||||
export type HoppTestExpectResult = {
|
export type HoppTestExpectResult = {
|
||||||
status: "fail" | "pass" | "error"
|
status: "fail" | "pass" | "error"
|
||||||
message: string
|
message: string
|
||||||
@@ -14,4 +16,21 @@ export type HoppTestResult = {
|
|||||||
expectResults: HoppTestExpectResult[]
|
expectResults: HoppTestExpectResult[]
|
||||||
description: string
|
description: string
|
||||||
scriptError: boolean
|
scriptError: boolean
|
||||||
|
|
||||||
|
envDiff: {
|
||||||
|
global: {
|
||||||
|
additions: Environment["variables"]
|
||||||
|
updations: Array<
|
||||||
|
Environment["variables"][number] & { previousValue: string }
|
||||||
|
>
|
||||||
|
deletions: Environment["variables"]
|
||||||
|
}
|
||||||
|
selected: {
|
||||||
|
additions: Environment["variables"]
|
||||||
|
updations: Array<
|
||||||
|
Environment["variables"][number] & { previousValue: string }
|
||||||
|
>
|
||||||
|
deletions: Environment["variables"]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -159,14 +159,19 @@
|
|||||||
"tests": "There are no tests for this request"
|
"tests": "There are no tests for this request"
|
||||||
},
|
},
|
||||||
"environment": {
|
"environment": {
|
||||||
|
"added": "Environment addition",
|
||||||
|
"add_to_global": "Add to Global",
|
||||||
"create_new": "Create new environment",
|
"create_new": "Create new environment",
|
||||||
|
"deleted": "Environment deletion",
|
||||||
"edit": "Edit Environment",
|
"edit": "Edit Environment",
|
||||||
"invalid_name": "Please provide a name for the environment",
|
"invalid_name": "Please provide a name for the environment",
|
||||||
"nested_overflow": "nested environment variables are limited to 10 levels",
|
"nested_overflow": "nested environment variables are limited to 10 levels",
|
||||||
"new": "New Environment",
|
"new": "New Environment",
|
||||||
"no_environment": "No environment",
|
"no_environment": "No environment",
|
||||||
|
"no_environment_description": "No environments were selected. Choose what to do with the following variables.",
|
||||||
"select": "Select environment",
|
"select": "Select environment",
|
||||||
"title": "Environments",
|
"title": "Environments",
|
||||||
|
"updated": "Environment updation",
|
||||||
"variable_list": "Variable List"
|
"variable_list": "Variable List"
|
||||||
},
|
},
|
||||||
"error": {
|
"error": {
|
||||||
@@ -468,7 +473,7 @@
|
|||||||
},
|
},
|
||||||
"state": {
|
"state": {
|
||||||
"bulk_mode": "Bulk edit",
|
"bulk_mode": "Bulk edit",
|
||||||
"bulk_mode_placeholder": "Entries are separated by newline\nKeys and values are separated by :\nPrepend # to any row you want to add but keep disabled",
|
"bulk_mode_placeholder": "Entries are separated by newline Keys and values are separated by : Prepend # to any row you want to add but keep disabled",
|
||||||
"cleared": "Cleared",
|
"cleared": "Cleared",
|
||||||
"connected": "Connected",
|
"connected": "Connected",
|
||||||
"connected_to": "Connected to {name}",
|
"connected_to": "Connected to {name}",
|
||||||
|
|||||||
@@ -57,7 +57,7 @@
|
|||||||
"@codemirror/view": "^0.19.0",
|
"@codemirror/view": "^0.19.0",
|
||||||
"@hoppscotch/codemirror-lang-graphql": "workspace:^0.1.0",
|
"@hoppscotch/codemirror-lang-graphql": "workspace:^0.1.0",
|
||||||
"@hoppscotch/data": "workspace:^0.4.0",
|
"@hoppscotch/data": "workspace:^0.4.0",
|
||||||
"@hoppscotch/js-sandbox": "workspace:^1.0.0",
|
"@hoppscotch/js-sandbox": "workspace:^2.0.0",
|
||||||
"@nuxtjs/axios": "^5.13.6",
|
"@nuxtjs/axios": "^5.13.6",
|
||||||
"@nuxtjs/composition-api": "^0.31.0",
|
"@nuxtjs/composition-api": "^0.31.0",
|
||||||
"@nuxtjs/gtm": "^2.4.0",
|
"@nuxtjs/gtm": "^2.4.0",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@hoppscotch/js-sandbox",
|
"name": "@hoppscotch/js-sandbox",
|
||||||
"version": "1.0.0",
|
"version": "2.0.0",
|
||||||
"description": "JavaScript sandboxes for running external scripts used by Hoppscotch clients",
|
"description": "JavaScript sandboxes for running external scripts used by Hoppscotch clients",
|
||||||
"main": "./lib/index.js",
|
"main": "./lib/index.js",
|
||||||
"types": "./lib/",
|
"types": "./lib/",
|
||||||
@@ -35,7 +35,8 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fp-ts": "^2.11.8",
|
"fp-ts": "^2.11.8",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"quickjs-emscripten": "^0.15.0"
|
"quickjs-emscripten": "^0.15.0",
|
||||||
|
"@hoppscotch/data": "workspace:^0.4.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@digitak/esrun": "^3.1.2",
|
"@digitak/esrun": "^3.1.2",
|
||||||
|
|||||||
@@ -8,15 +8,21 @@ describe("execPreRequestScript", () => {
|
|||||||
`
|
`
|
||||||
pw.env.set("bob", "newbob")
|
pw.env.set("bob", "newbob")
|
||||||
`,
|
`,
|
||||||
[
|
{
|
||||||
{ key: "bob", value: "oldbob" },
|
global: [],
|
||||||
{ key: "foo", value: "bar" },
|
selected: [
|
||||||
]
|
{ key: "bob", value: "oldbob" },
|
||||||
|
{ key: "foo", value: "bar" },
|
||||||
|
],
|
||||||
|
}
|
||||||
)()
|
)()
|
||||||
).resolves.toEqualRight([
|
).resolves.toEqualRight({
|
||||||
{ key: "bob", value: "newbob" },
|
global: [],
|
||||||
{ key: "foo", value: "bar" },
|
selected: [
|
||||||
])
|
{ key: "bob", value: "newbob" },
|
||||||
|
{ key: "foo", value: "bar" },
|
||||||
|
],
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test("fails if the key is not a string", () => {
|
test("fails if the key is not a string", () => {
|
||||||
@@ -25,10 +31,13 @@ describe("execPreRequestScript", () => {
|
|||||||
`
|
`
|
||||||
pw.env.set(10, "newbob")
|
pw.env.set(10, "newbob")
|
||||||
`,
|
`,
|
||||||
[
|
{
|
||||||
{ key: "bob", value: "oldbob" },
|
global: [],
|
||||||
{ key: "foo", value: "bar" },
|
selected: [
|
||||||
]
|
{ key: "bob", value: "oldbob" },
|
||||||
|
{ key: "foo", value: "bar" },
|
||||||
|
],
|
||||||
|
}
|
||||||
)()
|
)()
|
||||||
).resolves.toBeLeft()
|
).resolves.toBeLeft()
|
||||||
})
|
})
|
||||||
@@ -39,10 +48,13 @@ describe("execPreRequestScript", () => {
|
|||||||
`
|
`
|
||||||
pw.env.set("bob", 10)
|
pw.env.set("bob", 10)
|
||||||
`,
|
`,
|
||||||
[
|
{
|
||||||
{ key: "bob", value: "oldbob" },
|
global: [],
|
||||||
{ key: "foo", value: "bar" },
|
selected: [
|
||||||
]
|
{ key: "bob", value: "oldbob" },
|
||||||
|
{ key: "foo", value: "bar" },
|
||||||
|
],
|
||||||
|
}
|
||||||
)()
|
)()
|
||||||
).resolves.toBeLeft()
|
).resolves.toBeLeft()
|
||||||
})
|
})
|
||||||
@@ -53,10 +65,13 @@ describe("execPreRequestScript", () => {
|
|||||||
`
|
`
|
||||||
pw.env.set("bob",
|
pw.env.set("bob",
|
||||||
`,
|
`,
|
||||||
[
|
{
|
||||||
{ key: "bob", value: "oldbob" },
|
global: [],
|
||||||
{ key: "foo", value: "bar" },
|
selected: [
|
||||||
]
|
{ key: "bob", value: "oldbob" },
|
||||||
|
{ key: "foo", value: "bar" },
|
||||||
|
],
|
||||||
|
}
|
||||||
)()
|
)()
|
||||||
).resolves.toBeLeft()
|
).resolves.toBeLeft()
|
||||||
})
|
})
|
||||||
@@ -67,8 +82,11 @@ describe("execPreRequestScript", () => {
|
|||||||
`
|
`
|
||||||
pw.env.set("foo", "bar")
|
pw.env.set("foo", "bar")
|
||||||
`,
|
`,
|
||||||
[]
|
{ selected: [], global: [] }
|
||||||
)()
|
)()
|
||||||
).resolves.toEqualRight([{ key: "foo", value: "bar" }])
|
).resolves.toEqualRight({
|
||||||
|
global: [],
|
||||||
|
selected: [{ key: "foo", value: "bar" }],
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -0,0 +1,178 @@
|
|||||||
|
import * as TE from "fp-ts/TaskEither"
|
||||||
|
import { pipe } from "fp-ts/function"
|
||||||
|
import { execTestScript, TestResponse, TestResult } from "../../../test-runner"
|
||||||
|
|
||||||
|
import "@relmify/jest-fp-ts"
|
||||||
|
|
||||||
|
const fakeResponse: TestResponse = {
|
||||||
|
status: 200,
|
||||||
|
body: "hoi",
|
||||||
|
headers: [],
|
||||||
|
}
|
||||||
|
|
||||||
|
const func = (script: string, envs: TestResult["envs"]) =>
|
||||||
|
pipe(
|
||||||
|
execTestScript(script, envs, fakeResponse),
|
||||||
|
TE.map((x) => x.tests)
|
||||||
|
)
|
||||||
|
|
||||||
|
describe("pw.env.get", () => {
|
||||||
|
test("returns the correct value for an existing selected environment value", () => {
|
||||||
|
return expect(
|
||||||
|
func(
|
||||||
|
`
|
||||||
|
const data = pw.env.get("a")
|
||||||
|
pw.expect(data).toBe("b")
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
global: [],
|
||||||
|
selected: [
|
||||||
|
{
|
||||||
|
key: "a",
|
||||||
|
value: "b",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
)()
|
||||||
|
).resolves.toEqualRight([
|
||||||
|
expect.objectContaining({
|
||||||
|
expectResults: [
|
||||||
|
{
|
||||||
|
status: "pass",
|
||||||
|
message: "Expected 'b' to be 'b'",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
test("returns the correct value for an existing global environment value", () => {
|
||||||
|
return expect(
|
||||||
|
func(
|
||||||
|
`
|
||||||
|
const data = pw.env.get("a")
|
||||||
|
pw.expect(data).toBe("b")
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
global: [
|
||||||
|
{
|
||||||
|
key: "a",
|
||||||
|
value: "b",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
selected: [],
|
||||||
|
}
|
||||||
|
)()
|
||||||
|
).resolves.toEqualRight([
|
||||||
|
expect.objectContaining({
|
||||||
|
expectResults: [
|
||||||
|
{
|
||||||
|
status: "pass",
|
||||||
|
message: "Expected 'b' to be 'b'",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
test("returns undefined for a key that is not present in both selected or environment", () => {
|
||||||
|
return expect(
|
||||||
|
func(
|
||||||
|
`
|
||||||
|
const data = pw.env.get("a")
|
||||||
|
pw.expect(data).toBe(undefined)
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
global: [],
|
||||||
|
selected: [],
|
||||||
|
}
|
||||||
|
)()
|
||||||
|
).resolves.toEqualRight([
|
||||||
|
expect.objectContaining({
|
||||||
|
expectResults: [
|
||||||
|
{
|
||||||
|
status: "pass",
|
||||||
|
message: "Expected 'undefined' to be 'undefined'",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
test("returns the value defined in selected environment if it is also present in global", () => {
|
||||||
|
return expect(
|
||||||
|
func(
|
||||||
|
`
|
||||||
|
const data = pw.env.get("a")
|
||||||
|
pw.expect(data).toBe("selected val")
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
global: [
|
||||||
|
{
|
||||||
|
key: "a",
|
||||||
|
value: "global val",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
selected: [
|
||||||
|
{
|
||||||
|
key: "a",
|
||||||
|
value: "selected val",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
)()
|
||||||
|
).resolves.toEqualRight([
|
||||||
|
expect.objectContaining({
|
||||||
|
expectResults: [
|
||||||
|
{
|
||||||
|
status: "pass",
|
||||||
|
message: "Expected 'selected val' to be 'selected val'",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
test("does not resolve environment values", () => {
|
||||||
|
return expect(
|
||||||
|
func(
|
||||||
|
`
|
||||||
|
const data = pw.env.get("a")
|
||||||
|
pw.expect(data).toBe("<<hello>>")
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
global: [],
|
||||||
|
selected: [
|
||||||
|
{
|
||||||
|
key: "a",
|
||||||
|
value: "<<hello>>",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
)()
|
||||||
|
).resolves.toEqualRight([
|
||||||
|
expect.objectContaining({
|
||||||
|
expectResults: [
|
||||||
|
{
|
||||||
|
status: "pass",
|
||||||
|
message: "Expected '<<hello>>' to be '<<hello>>'",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
test("errors if the key is not a string", () => {
|
||||||
|
return expect(
|
||||||
|
func(
|
||||||
|
`
|
||||||
|
const data = pw.env.get(5)
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
global: [],
|
||||||
|
selected: [],
|
||||||
|
}
|
||||||
|
)()
|
||||||
|
).resolves.toBeLeft()
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,215 @@
|
|||||||
|
import * as TE from "fp-ts/TaskEither"
|
||||||
|
import { pipe } from "fp-ts/function"
|
||||||
|
import { execTestScript, TestResponse, TestResult } from "../../../test-runner"
|
||||||
|
|
||||||
|
import "@relmify/jest-fp-ts"
|
||||||
|
|
||||||
|
const fakeResponse: TestResponse = {
|
||||||
|
status: 200,
|
||||||
|
body: "hoi",
|
||||||
|
headers: [],
|
||||||
|
}
|
||||||
|
|
||||||
|
const func = (script: string, envs: TestResult["envs"]) =>
|
||||||
|
pipe(
|
||||||
|
execTestScript(script, envs, fakeResponse),
|
||||||
|
TE.map((x) => x.tests)
|
||||||
|
)
|
||||||
|
|
||||||
|
describe("pw.env.getResolve", () => {
|
||||||
|
test("returns the correct value for an existing selected environment value", () => {
|
||||||
|
return expect(
|
||||||
|
func(
|
||||||
|
`
|
||||||
|
const data = pw.env.getResolve("a")
|
||||||
|
pw.expect(data).toBe("b")
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
global: [],
|
||||||
|
selected: [
|
||||||
|
{
|
||||||
|
key: "a",
|
||||||
|
value: "b",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
)()
|
||||||
|
).resolves.toEqualRight([
|
||||||
|
expect.objectContaining({
|
||||||
|
expectResults: [
|
||||||
|
{
|
||||||
|
status: "pass",
|
||||||
|
message: "Expected 'b' to be 'b'",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
test("returns the correct value for an existing global environment value", () => {
|
||||||
|
return expect(
|
||||||
|
func(
|
||||||
|
`
|
||||||
|
const data = pw.env.getResolve("a")
|
||||||
|
pw.expect(data).toBe("b")
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
global: [
|
||||||
|
{
|
||||||
|
key: "a",
|
||||||
|
value: "b",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
selected: [],
|
||||||
|
}
|
||||||
|
)()
|
||||||
|
).resolves.toEqualRight([
|
||||||
|
expect.objectContaining({
|
||||||
|
expectResults: [
|
||||||
|
{
|
||||||
|
status: "pass",
|
||||||
|
message: "Expected 'b' to be 'b'",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
test("returns undefined for a key that is not present in both selected or environment", () => {
|
||||||
|
return expect(
|
||||||
|
func(
|
||||||
|
`
|
||||||
|
const data = pw.env.getResolve("a")
|
||||||
|
pw.expect(data).toBe(undefined)
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
global: [],
|
||||||
|
selected: [],
|
||||||
|
}
|
||||||
|
)()
|
||||||
|
).resolves.toEqualRight([
|
||||||
|
expect.objectContaining({
|
||||||
|
expectResults: [
|
||||||
|
{
|
||||||
|
status: "pass",
|
||||||
|
message: "Expected 'undefined' to be 'undefined'",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
test("returns the value defined in selected environment if it is also present in global", () => {
|
||||||
|
return expect(
|
||||||
|
func(
|
||||||
|
`
|
||||||
|
const data = pw.env.getResolve("a")
|
||||||
|
pw.expect(data).toBe("selected val")
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
global: [
|
||||||
|
{
|
||||||
|
key: "a",
|
||||||
|
value: "global val",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
selected: [
|
||||||
|
{
|
||||||
|
key: "a",
|
||||||
|
value: "selected val",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
)()
|
||||||
|
).resolves.toEqualRight([
|
||||||
|
expect.objectContaining({
|
||||||
|
expectResults: [
|
||||||
|
{
|
||||||
|
status: "pass",
|
||||||
|
message: "Expected 'selected val' to be 'selected val'",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
test("resolve environment values", () => {
|
||||||
|
return expect(
|
||||||
|
func(
|
||||||
|
`
|
||||||
|
const data = pw.env.getResolve("a")
|
||||||
|
pw.expect(data).toBe("there")
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
global: [],
|
||||||
|
selected: [
|
||||||
|
{
|
||||||
|
key: "a",
|
||||||
|
value: "<<hello>>",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "hello",
|
||||||
|
value: "there",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
)()
|
||||||
|
).resolves.toEqualRight([
|
||||||
|
expect.objectContaining({
|
||||||
|
expectResults: [
|
||||||
|
{
|
||||||
|
status: "pass",
|
||||||
|
message: "Expected 'there' to be 'there'",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
test("returns unresolved value on infinite loop in resolution", () => {
|
||||||
|
return expect(
|
||||||
|
func(
|
||||||
|
`
|
||||||
|
const data = pw.env.getResolve("a")
|
||||||
|
pw.expect(data).toBe("<<hello>>")
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
global: [],
|
||||||
|
selected: [
|
||||||
|
{
|
||||||
|
key: "a",
|
||||||
|
value: "<<hello>>",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "hello",
|
||||||
|
value: "<<a>>",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
)()
|
||||||
|
).resolves.toEqualRight([
|
||||||
|
expect.objectContaining({
|
||||||
|
expectResults: [
|
||||||
|
{
|
||||||
|
status: "pass",
|
||||||
|
message: "Expected '<<hello>>' to be '<<hello>>'",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
test("errors if the key is not a string", () => {
|
||||||
|
return expect(
|
||||||
|
func(
|
||||||
|
`
|
||||||
|
const data = pw.env.getResolve(5)
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
global: [],
|
||||||
|
selected: [],
|
||||||
|
}
|
||||||
|
)()
|
||||||
|
).resolves.toBeLeft()
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,156 @@
|
|||||||
|
import { pipe } from "fp-ts/function"
|
||||||
|
import * as TE from "fp-ts/TaskEither"
|
||||||
|
import { execTestScript, TestResponse, TestResult } from "../../../test-runner"
|
||||||
|
|
||||||
|
const fakeResponse: TestResponse = {
|
||||||
|
status: 200,
|
||||||
|
body: "hoi",
|
||||||
|
headers: [],
|
||||||
|
}
|
||||||
|
|
||||||
|
const func = (script: string, envs: TestResult["envs"]) =>
|
||||||
|
pipe(
|
||||||
|
execTestScript(script, envs, fakeResponse),
|
||||||
|
TE.map((x) => x.tests)
|
||||||
|
)
|
||||||
|
|
||||||
|
describe("pw.env.resolve", () => {
|
||||||
|
test("value should be a string", () => {
|
||||||
|
return expect(
|
||||||
|
func(
|
||||||
|
`
|
||||||
|
pw.env.resolve(5)
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
global: [],
|
||||||
|
selected: [],
|
||||||
|
}
|
||||||
|
)()
|
||||||
|
).resolves.toBeLeft()
|
||||||
|
})
|
||||||
|
|
||||||
|
test("resolves global variables correctly", () => {
|
||||||
|
return expect(
|
||||||
|
func(
|
||||||
|
`
|
||||||
|
const data = pw.env.resolve("<<hello>>")
|
||||||
|
pw.expect(data).toBe("there")
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
global: [
|
||||||
|
{
|
||||||
|
key: "hello",
|
||||||
|
value: "there",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
selected: [],
|
||||||
|
}
|
||||||
|
)()
|
||||||
|
).resolves.toEqualRight([
|
||||||
|
expect.objectContaining({
|
||||||
|
expectResults: [
|
||||||
|
{
|
||||||
|
status: "pass",
|
||||||
|
message: "Expected 'there' to be 'there'",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
test("resolves selected env variables correctly", () => {
|
||||||
|
return expect(
|
||||||
|
func(
|
||||||
|
`
|
||||||
|
const data = pw.env.resolve("<<hello>>")
|
||||||
|
pw.expect(data).toBe("there")
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
global: [],
|
||||||
|
selected: [
|
||||||
|
{
|
||||||
|
key: "hello",
|
||||||
|
value: "there",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
)()
|
||||||
|
).resolves.toEqualRight([
|
||||||
|
expect.objectContaining({
|
||||||
|
expectResults: [
|
||||||
|
{
|
||||||
|
status: "pass",
|
||||||
|
message: "Expected 'there' to be 'there'",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
test("chooses selected env variable over global variables when both have same variable", () => {
|
||||||
|
return expect(
|
||||||
|
func(
|
||||||
|
`
|
||||||
|
const data = pw.env.resolve("<<hello>>")
|
||||||
|
pw.expect(data).toBe("there")
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
global: [
|
||||||
|
{
|
||||||
|
key: "hello",
|
||||||
|
value: "yo",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
selected: [
|
||||||
|
{
|
||||||
|
key: "hello",
|
||||||
|
value: "there",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
)()
|
||||||
|
).resolves.toEqualRight([
|
||||||
|
expect.objectContaining({
|
||||||
|
expectResults: [
|
||||||
|
{
|
||||||
|
status: "pass",
|
||||||
|
message: "Expected 'there' to be 'there'",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
test("if infinite loop in resolution, abandons resolutions altogether", () => {
|
||||||
|
return expect(
|
||||||
|
func(
|
||||||
|
`
|
||||||
|
const data = pw.env.resolve("<<hello>>")
|
||||||
|
pw.expect(data).toBe("<<hello>>")
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
global: [],
|
||||||
|
selected: [
|
||||||
|
{
|
||||||
|
key: "hello",
|
||||||
|
value: "<<there>>",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "there",
|
||||||
|
value: "<<hello>>",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
)()
|
||||||
|
).resolves.toEqualRight([
|
||||||
|
expect.objectContaining({
|
||||||
|
expectResults: [
|
||||||
|
{
|
||||||
|
status: "pass",
|
||||||
|
message: "Expected '<<hello>>' to be '<<hello>>'",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,208 @@
|
|||||||
|
import * as TE from "fp-ts/TaskEither"
|
||||||
|
import { pipe } from "fp-ts/function"
|
||||||
|
import { execTestScript, TestResponse, TestResult } from "../../../test-runner"
|
||||||
|
|
||||||
|
const fakeResponse: TestResponse = {
|
||||||
|
status: 200,
|
||||||
|
body: "hoi",
|
||||||
|
headers: [],
|
||||||
|
}
|
||||||
|
|
||||||
|
const func = (script: string, envs: TestResult["envs"]) =>
|
||||||
|
pipe(
|
||||||
|
execTestScript(script, envs, fakeResponse),
|
||||||
|
TE.map((x) => x.envs)
|
||||||
|
)
|
||||||
|
|
||||||
|
const funcTest = (script: string, envs: TestResult["envs"]) =>
|
||||||
|
pipe(
|
||||||
|
execTestScript(script, envs, fakeResponse),
|
||||||
|
TE.map((x) => x.tests)
|
||||||
|
)
|
||||||
|
|
||||||
|
describe("pw.env.set", () => {
|
||||||
|
test("updates the selected environment variable correctly", () => {
|
||||||
|
return expect(
|
||||||
|
func(
|
||||||
|
`
|
||||||
|
pw.env.set("a", "c")
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
global: [],
|
||||||
|
selected: [
|
||||||
|
{
|
||||||
|
key: "a",
|
||||||
|
value: "b",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
)()
|
||||||
|
).resolves.toEqualRight(
|
||||||
|
expect.objectContaining({
|
||||||
|
selected: [
|
||||||
|
{
|
||||||
|
key: "a",
|
||||||
|
value: "c",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("updates the global environment variable correctly", () => {
|
||||||
|
return expect(
|
||||||
|
func(
|
||||||
|
`
|
||||||
|
pw.env.set("a", "c")
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
global: [
|
||||||
|
{
|
||||||
|
key: "a",
|
||||||
|
value: "b",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
selected: [],
|
||||||
|
}
|
||||||
|
)()
|
||||||
|
).resolves.toEqualRight(
|
||||||
|
expect.objectContaining({
|
||||||
|
global: [
|
||||||
|
{
|
||||||
|
key: "a",
|
||||||
|
value: "c",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("updates the selected environment if env present in both", () => {
|
||||||
|
return expect(
|
||||||
|
func(
|
||||||
|
`
|
||||||
|
pw.env.set("a", "c")
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
global: [
|
||||||
|
{
|
||||||
|
key: "a",
|
||||||
|
value: "b",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
selected: [
|
||||||
|
{
|
||||||
|
key: "a",
|
||||||
|
value: "d",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
)()
|
||||||
|
).resolves.toEqualRight(
|
||||||
|
expect.objectContaining({
|
||||||
|
global: [
|
||||||
|
{
|
||||||
|
key: "a",
|
||||||
|
value: "b",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
selected: [
|
||||||
|
{
|
||||||
|
key: "a",
|
||||||
|
value: "c",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("non existent keys are created in the selected environment", () => {
|
||||||
|
return expect(
|
||||||
|
func(
|
||||||
|
`
|
||||||
|
pw.env.set("a", "c")
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
global: [],
|
||||||
|
selected: [],
|
||||||
|
}
|
||||||
|
)()
|
||||||
|
).resolves.toEqualRight(
|
||||||
|
expect.objectContaining({
|
||||||
|
global: [],
|
||||||
|
selected: [
|
||||||
|
{
|
||||||
|
key: "a",
|
||||||
|
value: "c",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("keys should be a string", () => {
|
||||||
|
return expect(
|
||||||
|
func(
|
||||||
|
`
|
||||||
|
pw.env.set(5, "c")
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
global: [],
|
||||||
|
selected: [],
|
||||||
|
}
|
||||||
|
)()
|
||||||
|
).resolves.toBeLeft()
|
||||||
|
})
|
||||||
|
|
||||||
|
test("values should be a string", () => {
|
||||||
|
return expect(
|
||||||
|
func(
|
||||||
|
`
|
||||||
|
pw.env.set("a", 5)
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
global: [],
|
||||||
|
selected: [],
|
||||||
|
}
|
||||||
|
)()
|
||||||
|
).resolves.toBeLeft()
|
||||||
|
})
|
||||||
|
|
||||||
|
test("both keys and values should be strings", () => {
|
||||||
|
return expect(
|
||||||
|
func(
|
||||||
|
`
|
||||||
|
pw.env.set(5, 5)
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
global: [],
|
||||||
|
selected: [],
|
||||||
|
}
|
||||||
|
)()
|
||||||
|
).resolves.toBeLeft()
|
||||||
|
})
|
||||||
|
|
||||||
|
test("set environment values are reflected in the script execution", () => {
|
||||||
|
return expect(
|
||||||
|
funcTest(
|
||||||
|
`
|
||||||
|
pw.env.set("a", "b")
|
||||||
|
pw.expect(pw.env.get("a")).toBe("b")
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
global: [],
|
||||||
|
selected: [],
|
||||||
|
}
|
||||||
|
)()
|
||||||
|
).resolves.toEqualRight([
|
||||||
|
expect.objectContaining({
|
||||||
|
expectResults: [
|
||||||
|
{
|
||||||
|
status: "pass",
|
||||||
|
message: "Expected 'b' to be 'b'",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import * as TE from "fp-ts/TaskEither"
|
||||||
|
import { pipe } from "fp-ts/function"
|
||||||
import { execTestScript, TestResponse } from "../../../test-runner"
|
import { execTestScript, TestResponse } from "../../../test-runner"
|
||||||
import "@relmify/jest-fp-ts"
|
import "@relmify/jest-fp-ts"
|
||||||
|
|
||||||
@@ -7,11 +9,17 @@ const fakeResponse: TestResponse = {
|
|||||||
headers: [],
|
headers: [],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const func = (script: string, res: TestResponse) =>
|
||||||
|
pipe(
|
||||||
|
execTestScript(script, { global: [], selected: [] }, res),
|
||||||
|
TE.map((x) => x.tests)
|
||||||
|
)
|
||||||
|
|
||||||
describe("toBe", () => {
|
describe("toBe", () => {
|
||||||
describe("general assertion (no negation)", () => {
|
describe("general assertion (no negation)", () => {
|
||||||
test("expect equals expected passes assertion", () => {
|
test("expect equals expected passes assertion", () => {
|
||||||
return expect(
|
return expect(
|
||||||
execTestScript(
|
func(
|
||||||
`
|
`
|
||||||
pw.expect(2).toBe(2)
|
pw.expect(2).toBe(2)
|
||||||
`,
|
`,
|
||||||
@@ -28,7 +36,7 @@ describe("toBe", () => {
|
|||||||
|
|
||||||
test("expect not equals expected fails assertion", () => {
|
test("expect not equals expected fails assertion", () => {
|
||||||
return expect(
|
return expect(
|
||||||
execTestScript(
|
func(
|
||||||
`
|
`
|
||||||
pw.expect(2).toBe(4)
|
pw.expect(2).toBe(4)
|
||||||
`,
|
`,
|
||||||
@@ -47,7 +55,7 @@ describe("toBe", () => {
|
|||||||
describe("general assertion (with negation)", () => {
|
describe("general assertion (with negation)", () => {
|
||||||
test("expect equals expected fails assertion", () => {
|
test("expect equals expected fails assertion", () => {
|
||||||
return expect(
|
return expect(
|
||||||
execTestScript(
|
func(
|
||||||
`
|
`
|
||||||
pw.expect(2).not.toBe(2)
|
pw.expect(2).not.toBe(2)
|
||||||
`,
|
`,
|
||||||
@@ -67,7 +75,7 @@ describe("toBe", () => {
|
|||||||
|
|
||||||
test("expect not equals expected passes assertion", () => {
|
test("expect not equals expected passes assertion", () => {
|
||||||
return expect(
|
return expect(
|
||||||
execTestScript(
|
func(
|
||||||
`
|
`
|
||||||
pw.expect(2).not.toBe(4)
|
pw.expect(2).not.toBe(4)
|
||||||
`,
|
`,
|
||||||
@@ -89,7 +97,7 @@ describe("toBe", () => {
|
|||||||
|
|
||||||
test("strict checks types", () => {
|
test("strict checks types", () => {
|
||||||
return expect(
|
return expect(
|
||||||
execTestScript(
|
func(
|
||||||
`
|
`
|
||||||
pw.expect(2).toBe("2")
|
pw.expect(2).toBe("2")
|
||||||
`,
|
`,
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import * as TE from "fp-ts/TaskEither"
|
||||||
|
import { pipe } from "fp-ts/function"
|
||||||
import { execTestScript, TestResponse } from "../../../test-runner"
|
import { execTestScript, TestResponse } from "../../../test-runner"
|
||||||
import "@relmify/jest-fp-ts"
|
import "@relmify/jest-fp-ts"
|
||||||
|
|
||||||
@@ -7,11 +9,17 @@ const fakeResponse: TestResponse = {
|
|||||||
headers: [],
|
headers: [],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const func = (script: string, res: TestResponse) =>
|
||||||
|
pipe(
|
||||||
|
execTestScript(script, { global: [], selected: [] }, res),
|
||||||
|
TE.map((x) => x.tests)
|
||||||
|
)
|
||||||
|
|
||||||
describe("toBeLevel2xx", () => {
|
describe("toBeLevel2xx", () => {
|
||||||
test("assertion passes for 200 series with no negation", async () => {
|
test("assertion passes for 200 series with no negation", async () => {
|
||||||
for (let i = 200; i < 300; i++) {
|
for (let i = 200; i < 300; i++) {
|
||||||
await expect(
|
await expect(
|
||||||
execTestScript(`pw.expect(${i}).toBeLevel2xx()`, fakeResponse)()
|
func(`pw.expect(${i}).toBeLevel2xx()`, fakeResponse)()
|
||||||
).resolves.toEqualRight([
|
).resolves.toEqualRight([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
expectResults: [
|
expectResults: [
|
||||||
@@ -28,7 +36,7 @@ describe("toBeLevel2xx", () => {
|
|||||||
test("assertion fails for non 200 series with no negation", async () => {
|
test("assertion fails for non 200 series with no negation", async () => {
|
||||||
for (let i = 300; i < 500; i++) {
|
for (let i = 300; i < 500; i++) {
|
||||||
await expect(
|
await expect(
|
||||||
execTestScript(`pw.expect(${i}).toBeLevel2xx()`, fakeResponse)()
|
func(`pw.expect(${i}).toBeLevel2xx()`, fakeResponse)()
|
||||||
).resolves.toEqualRight([
|
).resolves.toEqualRight([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
expectResults: [
|
expectResults: [
|
||||||
@@ -44,7 +52,7 @@ describe("toBeLevel2xx", () => {
|
|||||||
|
|
||||||
test("give error if the expect value was not a number with no negation", async () => {
|
test("give error if the expect value was not a number with no negation", async () => {
|
||||||
await expect(
|
await expect(
|
||||||
execTestScript(`pw.expect("foo").toBeLevel2xx()`, fakeResponse)()
|
func(`pw.expect("foo").toBeLevel2xx()`, fakeResponse)()
|
||||||
).resolves.toEqualRight([
|
).resolves.toEqualRight([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
expectResults: [
|
expectResults: [
|
||||||
@@ -61,7 +69,7 @@ describe("toBeLevel2xx", () => {
|
|||||||
test("assertion fails for 200 series with negation", async () => {
|
test("assertion fails for 200 series with negation", async () => {
|
||||||
for (let i = 200; i < 300; i++) {
|
for (let i = 200; i < 300; i++) {
|
||||||
await expect(
|
await expect(
|
||||||
execTestScript(`pw.expect(${i}).not.toBeLevel2xx()`, fakeResponse)()
|
func(`pw.expect(${i}).not.toBeLevel2xx()`, fakeResponse)()
|
||||||
).resolves.toEqualRight([
|
).resolves.toEqualRight([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
expectResults: [
|
expectResults: [
|
||||||
@@ -78,7 +86,7 @@ describe("toBeLevel2xx", () => {
|
|||||||
test("assertion passes for non 200 series with negation", async () => {
|
test("assertion passes for non 200 series with negation", async () => {
|
||||||
for (let i = 300; i < 500; i++) {
|
for (let i = 300; i < 500; i++) {
|
||||||
await expect(
|
await expect(
|
||||||
execTestScript(`pw.expect(${i}).not.toBeLevel2xx()`, fakeResponse)()
|
func(`pw.expect(${i}).not.toBeLevel2xx()`, fakeResponse)()
|
||||||
).resolves.toEqualRight([
|
).resolves.toEqualRight([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
expectResults: [
|
expectResults: [
|
||||||
@@ -94,7 +102,7 @@ describe("toBeLevel2xx", () => {
|
|||||||
|
|
||||||
test("give error if the expect value was not a number with negation", async () => {
|
test("give error if the expect value was not a number with negation", async () => {
|
||||||
await expect(
|
await expect(
|
||||||
execTestScript(`pw.expect("foo").not.toBeLevel2xx()`, fakeResponse)()
|
func(`pw.expect("foo").not.toBeLevel2xx()`, fakeResponse)()
|
||||||
).resolves.toEqualRight([
|
).resolves.toEqualRight([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
expectResults: [
|
expectResults: [
|
||||||
@@ -113,7 +121,7 @@ describe("toBeLevel3xx", () => {
|
|||||||
test("assertion passes for 300 series with no negation", async () => {
|
test("assertion passes for 300 series with no negation", async () => {
|
||||||
for (let i = 300; i < 400; i++) {
|
for (let i = 300; i < 400; i++) {
|
||||||
await expect(
|
await expect(
|
||||||
execTestScript(`pw.expect(${i}).toBeLevel3xx()`, fakeResponse)()
|
func(`pw.expect(${i}).toBeLevel3xx()`, fakeResponse)()
|
||||||
).resolves.toEqualRight([
|
).resolves.toEqualRight([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
expectResults: [
|
expectResults: [
|
||||||
@@ -130,7 +138,7 @@ describe("toBeLevel3xx", () => {
|
|||||||
test("assertion fails for non 300 series with no negation", async () => {
|
test("assertion fails for non 300 series with no negation", async () => {
|
||||||
for (let i = 400; i < 500; i++) {
|
for (let i = 400; i < 500; i++) {
|
||||||
await expect(
|
await expect(
|
||||||
execTestScript(`pw.expect(${i}).toBeLevel3xx()`, fakeResponse)()
|
func(`pw.expect(${i}).toBeLevel3xx()`, fakeResponse)()
|
||||||
).resolves.toEqualRight([
|
).resolves.toEqualRight([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
expectResults: [
|
expectResults: [
|
||||||
@@ -146,7 +154,7 @@ describe("toBeLevel3xx", () => {
|
|||||||
|
|
||||||
test("give error if the expect value is not a number without negation", () => {
|
test("give error if the expect value is not a number without negation", () => {
|
||||||
return expect(
|
return expect(
|
||||||
execTestScript(`pw.expect("foo").toBeLevel3xx()`, fakeResponse)()
|
func(`pw.expect("foo").toBeLevel3xx()`, fakeResponse)()
|
||||||
).resolves.toEqualRight([
|
).resolves.toEqualRight([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
expectResults: [
|
expectResults: [
|
||||||
@@ -163,7 +171,7 @@ describe("toBeLevel3xx", () => {
|
|||||||
test("assertion fails for 400 series with negation", async () => {
|
test("assertion fails for 400 series with negation", async () => {
|
||||||
for (let i = 300; i < 400; i++) {
|
for (let i = 300; i < 400; i++) {
|
||||||
await expect(
|
await expect(
|
||||||
execTestScript(`pw.expect(${i}).not.toBeLevel3xx()`, fakeResponse)()
|
func(`pw.expect(${i}).not.toBeLevel3xx()`, fakeResponse)()
|
||||||
).resolves.toEqualRight([
|
).resolves.toEqualRight([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
expectResults: [
|
expectResults: [
|
||||||
@@ -180,7 +188,7 @@ describe("toBeLevel3xx", () => {
|
|||||||
test("assertion passes for non 200 series with negation", async () => {
|
test("assertion passes for non 200 series with negation", async () => {
|
||||||
for (let i = 400; i < 500; i++) {
|
for (let i = 400; i < 500; i++) {
|
||||||
await expect(
|
await expect(
|
||||||
execTestScript(`pw.expect(${i}).not.toBeLevel3xx()`, fakeResponse)()
|
func(`pw.expect(${i}).not.toBeLevel3xx()`, fakeResponse)()
|
||||||
).resolves.toEqualRight([
|
).resolves.toEqualRight([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
expectResults: [
|
expectResults: [
|
||||||
@@ -196,7 +204,7 @@ describe("toBeLevel3xx", () => {
|
|||||||
|
|
||||||
test("give error if the expect value is not a number with negation", () => {
|
test("give error if the expect value is not a number with negation", () => {
|
||||||
return expect(
|
return expect(
|
||||||
execTestScript(`pw.expect("foo").not.toBeLevel3xx()`, fakeResponse)()
|
func(`pw.expect("foo").not.toBeLevel3xx()`, fakeResponse)()
|
||||||
).resolves.toEqualRight([
|
).resolves.toEqualRight([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
expectResults: [
|
expectResults: [
|
||||||
@@ -215,7 +223,7 @@ describe("toBeLevel4xx", () => {
|
|||||||
test("assertion passes for 400 series with no negation", async () => {
|
test("assertion passes for 400 series with no negation", async () => {
|
||||||
for (let i = 400; i < 500; i++) {
|
for (let i = 400; i < 500; i++) {
|
||||||
await expect(
|
await expect(
|
||||||
execTestScript(`pw.expect(${i}).toBeLevel4xx()`, fakeResponse)()
|
func(`pw.expect(${i}).toBeLevel4xx()`, fakeResponse)()
|
||||||
).resolves.toEqualRight([
|
).resolves.toEqualRight([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
expectResults: [
|
expectResults: [
|
||||||
@@ -232,7 +240,7 @@ describe("toBeLevel4xx", () => {
|
|||||||
test("assertion fails for non 400 series with no negation", async () => {
|
test("assertion fails for non 400 series with no negation", async () => {
|
||||||
for (let i = 500; i < 600; i++) {
|
for (let i = 500; i < 600; i++) {
|
||||||
await expect(
|
await expect(
|
||||||
execTestScript(`pw.expect(${i}).toBeLevel4xx()`, fakeResponse)()
|
func(`pw.expect(${i}).toBeLevel4xx()`, fakeResponse)()
|
||||||
).resolves.toEqualRight([
|
).resolves.toEqualRight([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
expectResults: [
|
expectResults: [
|
||||||
@@ -248,7 +256,7 @@ describe("toBeLevel4xx", () => {
|
|||||||
|
|
||||||
test("give error if the expected value is not a number without negation", () => {
|
test("give error if the expected value is not a number without negation", () => {
|
||||||
return expect(
|
return expect(
|
||||||
execTestScript(`pw.expect("foo").toBeLevel4xx()`, fakeResponse)()
|
func(`pw.expect("foo").toBeLevel4xx()`, fakeResponse)()
|
||||||
).resolves.toEqualRight([
|
).resolves.toEqualRight([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
expectResults: [
|
expectResults: [
|
||||||
@@ -265,7 +273,7 @@ describe("toBeLevel4xx", () => {
|
|||||||
test("assertion fails for 400 series with negation", async () => {
|
test("assertion fails for 400 series with negation", async () => {
|
||||||
for (let i = 400; i < 500; i++) {
|
for (let i = 400; i < 500; i++) {
|
||||||
await expect(
|
await expect(
|
||||||
execTestScript(`pw.expect(${i}).not.toBeLevel4xx()`, fakeResponse)()
|
func(`pw.expect(${i}).not.toBeLevel4xx()`, fakeResponse)()
|
||||||
).resolves.toEqualRight([
|
).resolves.toEqualRight([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
expectResults: [
|
expectResults: [
|
||||||
@@ -282,7 +290,7 @@ describe("toBeLevel4xx", () => {
|
|||||||
test("assertion passes for non 400 series with negation", async () => {
|
test("assertion passes for non 400 series with negation", async () => {
|
||||||
for (let i = 500; i < 600; i++) {
|
for (let i = 500; i < 600; i++) {
|
||||||
await expect(
|
await expect(
|
||||||
execTestScript(`pw.expect(${i}).not.toBeLevel4xx()`, fakeResponse)()
|
func(`pw.expect(${i}).not.toBeLevel4xx()`, fakeResponse)()
|
||||||
).resolves.toEqualRight([
|
).resolves.toEqualRight([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
expectResults: [
|
expectResults: [
|
||||||
@@ -298,7 +306,7 @@ describe("toBeLevel4xx", () => {
|
|||||||
|
|
||||||
test("give error if the expected value is not a number with negation", () => {
|
test("give error if the expected value is not a number with negation", () => {
|
||||||
return expect(
|
return expect(
|
||||||
execTestScript(`pw.expect("foo").not.toBeLevel4xx()`, fakeResponse)()
|
func(`pw.expect("foo").not.toBeLevel4xx()`, fakeResponse)()
|
||||||
).resolves.toEqualRight([
|
).resolves.toEqualRight([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
expectResults: [
|
expectResults: [
|
||||||
@@ -317,7 +325,7 @@ describe("toBeLevel5xx", () => {
|
|||||||
test("assertion passes for 500 series with no negation", async () => {
|
test("assertion passes for 500 series with no negation", async () => {
|
||||||
for (let i = 500; i < 600; i++) {
|
for (let i = 500; i < 600; i++) {
|
||||||
await expect(
|
await expect(
|
||||||
execTestScript(`pw.expect(${i}).toBeLevel5xx()`, fakeResponse)()
|
func(`pw.expect(${i}).toBeLevel5xx()`, fakeResponse)()
|
||||||
).resolves.toEqualRight([
|
).resolves.toEqualRight([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
expectResults: [
|
expectResults: [
|
||||||
@@ -334,7 +342,7 @@ describe("toBeLevel5xx", () => {
|
|||||||
test("assertion fails for non 500 series with no negation", async () => {
|
test("assertion fails for non 500 series with no negation", async () => {
|
||||||
for (let i = 200; i < 500; i++) {
|
for (let i = 200; i < 500; i++) {
|
||||||
await expect(
|
await expect(
|
||||||
execTestScript(`pw.expect(${i}).toBeLevel5xx()`, fakeResponse)()
|
func(`pw.expect(${i}).toBeLevel5xx()`, fakeResponse)()
|
||||||
).resolves.toEqualRight([
|
).resolves.toEqualRight([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
expectResults: [
|
expectResults: [
|
||||||
@@ -350,7 +358,7 @@ describe("toBeLevel5xx", () => {
|
|||||||
|
|
||||||
test("give error if the expect value is not a number with no negation", () => {
|
test("give error if the expect value is not a number with no negation", () => {
|
||||||
return expect(
|
return expect(
|
||||||
execTestScript(`pw.expect("foo").toBeLevel5xx()`, fakeResponse)()
|
func(`pw.expect("foo").toBeLevel5xx()`, fakeResponse)()
|
||||||
).resolves.toEqualRight([
|
).resolves.toEqualRight([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
expectResults: [
|
expectResults: [
|
||||||
@@ -367,7 +375,7 @@ describe("toBeLevel5xx", () => {
|
|||||||
test("assertion fails for 500 series with negation", async () => {
|
test("assertion fails for 500 series with negation", async () => {
|
||||||
for (let i = 500; i < 600; i++) {
|
for (let i = 500; i < 600; i++) {
|
||||||
await expect(
|
await expect(
|
||||||
execTestScript(`pw.expect(${i}).not.toBeLevel5xx()`, fakeResponse)()
|
func(`pw.expect(${i}).not.toBeLevel5xx()`, fakeResponse)()
|
||||||
).resolves.toEqualRight([
|
).resolves.toEqualRight([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
expectResults: [
|
expectResults: [
|
||||||
@@ -384,7 +392,7 @@ describe("toBeLevel5xx", () => {
|
|||||||
test("assertion passes for non 500 series with negation", async () => {
|
test("assertion passes for non 500 series with negation", async () => {
|
||||||
for (let i = 200; i < 500; i++) {
|
for (let i = 200; i < 500; i++) {
|
||||||
await expect(
|
await expect(
|
||||||
execTestScript(`pw.expect(${i}).not.toBeLevel5xx()`, fakeResponse)()
|
func(`pw.expect(${i}).not.toBeLevel5xx()`, fakeResponse)()
|
||||||
).resolves.toEqualRight([
|
).resolves.toEqualRight([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
expectResults: [
|
expectResults: [
|
||||||
@@ -400,7 +408,7 @@ describe("toBeLevel5xx", () => {
|
|||||||
|
|
||||||
test("give error if the expect value is not a number with negation", () => {
|
test("give error if the expect value is not a number with negation", () => {
|
||||||
return expect(
|
return expect(
|
||||||
execTestScript(`pw.expect("foo").not.toBeLevel5xx()`, fakeResponse)()
|
func(`pw.expect("foo").not.toBeLevel5xx()`, fakeResponse)()
|
||||||
).resolves.toEqualRight([
|
).resolves.toEqualRight([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
expectResults: [
|
expectResults: [
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import * as TE from "fp-ts/TaskEither"
|
||||||
|
import { pipe } from "fp-ts/function"
|
||||||
import { execTestScript, TestResponse } from "../../../test-runner"
|
import { execTestScript, TestResponse } from "../../../test-runner"
|
||||||
|
|
||||||
const fakeResponse: TestResponse = {
|
const fakeResponse: TestResponse = {
|
||||||
@@ -6,10 +8,16 @@ const fakeResponse: TestResponse = {
|
|||||||
headers: [],
|
headers: [],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const func = (script: string, res: TestResponse) =>
|
||||||
|
pipe(
|
||||||
|
execTestScript(script, { global: [], selected: [] }, res),
|
||||||
|
TE.map((x) => x.tests)
|
||||||
|
)
|
||||||
|
|
||||||
describe("toBeType", () => {
|
describe("toBeType", () => {
|
||||||
test("asserts true for valid type expectations with no negation", () => {
|
test("asserts true for valid type expectations with no negation", () => {
|
||||||
return expect(
|
return expect(
|
||||||
execTestScript(
|
func(
|
||||||
`
|
`
|
||||||
pw.expect(2).toBeType("number")
|
pw.expect(2).toBeType("number")
|
||||||
pw.expect("2").toBeType("string")
|
pw.expect("2").toBeType("string")
|
||||||
@@ -40,7 +48,7 @@ describe("toBeType", () => {
|
|||||||
|
|
||||||
test("asserts false for invalid type expectations with no negation", () => {
|
test("asserts false for invalid type expectations with no negation", () => {
|
||||||
return expect(
|
return expect(
|
||||||
execTestScript(
|
func(
|
||||||
`
|
`
|
||||||
pw.expect(2).toBeType("string")
|
pw.expect(2).toBeType("string")
|
||||||
pw.expect("2").toBeType("number")
|
pw.expect("2").toBeType("number")
|
||||||
@@ -71,7 +79,7 @@ describe("toBeType", () => {
|
|||||||
|
|
||||||
test("asserts false for valid type expectations with negation", () => {
|
test("asserts false for valid type expectations with negation", () => {
|
||||||
return expect(
|
return expect(
|
||||||
execTestScript(
|
func(
|
||||||
`
|
`
|
||||||
pw.expect(2).not.toBeType("number")
|
pw.expect(2).not.toBeType("number")
|
||||||
pw.expect("2").not.toBeType("string")
|
pw.expect("2").not.toBeType("string")
|
||||||
@@ -105,7 +113,7 @@ describe("toBeType", () => {
|
|||||||
|
|
||||||
test("asserts true for invalid type expectations with negation", () => {
|
test("asserts true for invalid type expectations with negation", () => {
|
||||||
return expect(
|
return expect(
|
||||||
execTestScript(
|
func(
|
||||||
`
|
`
|
||||||
pw.expect(2).not.toBeType("string")
|
pw.expect(2).not.toBeType("string")
|
||||||
pw.expect("2").not.toBeType("number")
|
pw.expect("2").not.toBeType("number")
|
||||||
@@ -139,7 +147,7 @@ describe("toBeType", () => {
|
|||||||
|
|
||||||
test("gives error for invalid type names without negation", () => {
|
test("gives error for invalid type names without negation", () => {
|
||||||
return expect(
|
return expect(
|
||||||
execTestScript(
|
func(
|
||||||
`
|
`
|
||||||
pw.expect(2).toBeType("foo")
|
pw.expect(2).toBeType("foo")
|
||||||
pw.expect("2").toBeType("bar")
|
pw.expect("2").toBeType("bar")
|
||||||
@@ -179,7 +187,7 @@ describe("toBeType", () => {
|
|||||||
|
|
||||||
test("gives error for invalid type names with negation", () => {
|
test("gives error for invalid type names with negation", () => {
|
||||||
return expect(
|
return expect(
|
||||||
execTestScript(
|
func(
|
||||||
`
|
`
|
||||||
pw.expect(2).not.toBeType("foo")
|
pw.expect(2).not.toBeType("foo")
|
||||||
pw.expect("2").not.toBeType("bar")
|
pw.expect("2").not.toBeType("bar")
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import * as TE from "fp-ts/TaskEither"
|
||||||
|
import { pipe } from "fp-ts/function"
|
||||||
import { execTestScript, TestResponse } from "../../../test-runner"
|
import { execTestScript, TestResponse } from "../../../test-runner"
|
||||||
|
|
||||||
const fakeResponse: TestResponse = {
|
const fakeResponse: TestResponse = {
|
||||||
@@ -6,10 +8,16 @@ const fakeResponse: TestResponse = {
|
|||||||
headers: [],
|
headers: [],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const func = (script: string, res: TestResponse) =>
|
||||||
|
pipe(
|
||||||
|
execTestScript(script, { global: [], selected: [] }, res),
|
||||||
|
TE.map((x) => x.tests)
|
||||||
|
)
|
||||||
|
|
||||||
describe("toHaveLength", () => {
|
describe("toHaveLength", () => {
|
||||||
test("asserts true for valid lengths with no negation", () => {
|
test("asserts true for valid lengths with no negation", () => {
|
||||||
return expect(
|
return expect(
|
||||||
execTestScript(
|
func(
|
||||||
`
|
`
|
||||||
pw.expect([1, 2, 3, 4]).toHaveLength(4)
|
pw.expect([1, 2, 3, 4]).toHaveLength(4)
|
||||||
pw.expect([]).toHaveLength(0)
|
pw.expect([]).toHaveLength(0)
|
||||||
@@ -28,7 +36,7 @@ describe("toHaveLength", () => {
|
|||||||
|
|
||||||
test("asserts false for invalid lengths with no negation", () => {
|
test("asserts false for invalid lengths with no negation", () => {
|
||||||
return expect(
|
return expect(
|
||||||
execTestScript(
|
func(
|
||||||
`
|
`
|
||||||
pw.expect([]).toHaveLength(4)
|
pw.expect([]).toHaveLength(4)
|
||||||
pw.expect([1, 2, 3, 4]).toHaveLength(0)
|
pw.expect([1, 2, 3, 4]).toHaveLength(0)
|
||||||
@@ -47,7 +55,7 @@ describe("toHaveLength", () => {
|
|||||||
|
|
||||||
test("asserts false for valid lengths with negation", () => {
|
test("asserts false for valid lengths with negation", () => {
|
||||||
return expect(
|
return expect(
|
||||||
execTestScript(
|
func(
|
||||||
`
|
`
|
||||||
pw.expect([1, 2, 3, 4]).not.toHaveLength(4)
|
pw.expect([1, 2, 3, 4]).not.toHaveLength(4)
|
||||||
pw.expect([]).not.toHaveLength(0)
|
pw.expect([]).not.toHaveLength(0)
|
||||||
@@ -72,7 +80,7 @@ describe("toHaveLength", () => {
|
|||||||
|
|
||||||
test("asserts true for invalid lengths with negation", () => {
|
test("asserts true for invalid lengths with negation", () => {
|
||||||
return expect(
|
return expect(
|
||||||
execTestScript(
|
func(
|
||||||
`
|
`
|
||||||
pw.expect([]).not.toHaveLength(4)
|
pw.expect([]).not.toHaveLength(4)
|
||||||
pw.expect([1, 2, 3, 4]).not.toHaveLength(0)
|
pw.expect([1, 2, 3, 4]).not.toHaveLength(0)
|
||||||
@@ -97,7 +105,7 @@ describe("toHaveLength", () => {
|
|||||||
|
|
||||||
test("gives error if not called on an array or a string with no negation", () => {
|
test("gives error if not called on an array or a string with no negation", () => {
|
||||||
return expect(
|
return expect(
|
||||||
execTestScript(
|
func(
|
||||||
`
|
`
|
||||||
pw.expect(5).toHaveLength(0)
|
pw.expect(5).toHaveLength(0)
|
||||||
pw.expect(true).toHaveLength(0)
|
pw.expect(true).toHaveLength(0)
|
||||||
@@ -124,7 +132,7 @@ describe("toHaveLength", () => {
|
|||||||
|
|
||||||
test("gives error if not called on an array or a string with negation", () => {
|
test("gives error if not called on an array or a string with negation", () => {
|
||||||
return expect(
|
return expect(
|
||||||
execTestScript(
|
func(
|
||||||
`
|
`
|
||||||
pw.expect(5).not.toHaveLength(0)
|
pw.expect(5).not.toHaveLength(0)
|
||||||
pw.expect(true).not.toHaveLength(0)
|
pw.expect(true).not.toHaveLength(0)
|
||||||
@@ -151,7 +159,7 @@ describe("toHaveLength", () => {
|
|||||||
|
|
||||||
test("gives an error if toHaveLength parameter is not a number without negation", () => {
|
test("gives an error if toHaveLength parameter is not a number without negation", () => {
|
||||||
return expect(
|
return expect(
|
||||||
execTestScript(
|
func(
|
||||||
`
|
`
|
||||||
pw.expect([1, 2, 3, 4]).toHaveLength("a")
|
pw.expect([1, 2, 3, 4]).toHaveLength("a")
|
||||||
`,
|
`,
|
||||||
@@ -171,7 +179,7 @@ describe("toHaveLength", () => {
|
|||||||
|
|
||||||
test("gives an error if toHaveLength parameter is not a number with negation", () => {
|
test("gives an error if toHaveLength parameter is not a number with negation", () => {
|
||||||
return expect(
|
return expect(
|
||||||
execTestScript(
|
func(
|
||||||
`
|
`
|
||||||
pw.expect([1, 2, 3, 4]).not.toHaveLength("a")
|
pw.expect([1, 2, 3, 4]).not.toHaveLength("a")
|
||||||
`,
|
`,
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import * as TE from "fp-ts/TaskEither"
|
||||||
|
import { pipe } from "fp-ts/function"
|
||||||
import { execTestScript, TestResponse } from "../../test-runner"
|
import { execTestScript, TestResponse } from "../../test-runner"
|
||||||
|
|
||||||
const fakeResponse: TestResponse = {
|
const fakeResponse: TestResponse = {
|
||||||
@@ -6,10 +8,16 @@ const fakeResponse: TestResponse = {
|
|||||||
headers: [],
|
headers: [],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const func = (script: string, res: TestResponse) =>
|
||||||
|
pipe(
|
||||||
|
execTestScript(script, { global: [], selected: [] }, res),
|
||||||
|
TE.map((x) => x.tests)
|
||||||
|
)
|
||||||
|
|
||||||
describe("execTestScript function behavior", () => {
|
describe("execTestScript function behavior", () => {
|
||||||
test("returns a resolved promise for a valid test scripts with all green", () => {
|
test("returns a resolved promise for a valid test scripts with all green", () => {
|
||||||
return expect(
|
return expect(
|
||||||
execTestScript(
|
func(
|
||||||
`
|
`
|
||||||
pw.test("Arithmetic operations", () => {
|
pw.test("Arithmetic operations", () => {
|
||||||
const size = 500 + 500;
|
const size = 500 + 500;
|
||||||
@@ -26,7 +34,7 @@ describe("execTestScript function behavior", () => {
|
|||||||
|
|
||||||
test("resolves for tests with failed expectations", () => {
|
test("resolves for tests with failed expectations", () => {
|
||||||
return expect(
|
return expect(
|
||||||
execTestScript(
|
func(
|
||||||
`
|
`
|
||||||
pw.test("Arithmetic operations", () => {
|
pw.test("Arithmetic operations", () => {
|
||||||
const size = 500 + 500;
|
const size = 500 + 500;
|
||||||
@@ -44,7 +52,7 @@ describe("execTestScript function behavior", () => {
|
|||||||
// TODO: We need a more concrete behavior for this
|
// TODO: We need a more concrete behavior for this
|
||||||
test("rejects for invalid syntax on tests", () => {
|
test("rejects for invalid syntax on tests", () => {
|
||||||
return expect(
|
return expect(
|
||||||
execTestScript(
|
func(
|
||||||
`
|
`
|
||||||
pw.test("Arithmetic operations", () => {
|
pw.test("Arithmetic operations", () => {
|
||||||
const size = 500 + 500;
|
const size = 500 + 500;
|
||||||
|
|||||||
@@ -1,22 +1,34 @@
|
|||||||
import { pipe } from "fp-ts/lib/function"
|
import { pipe } from "fp-ts/function"
|
||||||
import { chain, right } from "fp-ts/lib/TaskEither"
|
import * as TE from "fp-ts/TaskEither"
|
||||||
import { execPreRequestScript } from "./preRequest"
|
import { execPreRequestScript } from "./preRequest"
|
||||||
import {
|
import {
|
||||||
execTestScript,
|
execTestScript,
|
||||||
TestResponse,
|
TestResponse,
|
||||||
TestDescriptor as _TestDescriptor,
|
TestDescriptor as _TestDescriptor,
|
||||||
|
TestResult,
|
||||||
} from "./test-runner"
|
} from "./test-runner"
|
||||||
|
|
||||||
export type TestDescriptor = _TestDescriptor
|
export type TestDescriptor = _TestDescriptor
|
||||||
|
export type SandboxTestResult = TestResult & { tests: TestDescriptor }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes a given test script on the test-runner sandbox
|
* Executes a given test script on the test-runner sandbox
|
||||||
* @param testScript The string of the script to run
|
* @param testScript The string of the script to run
|
||||||
* @returns A TaskEither with an error message or a TestDescriptor with the final status
|
* @returns A TaskEither with an error message or a TestDescriptor with the final status
|
||||||
*/
|
*/
|
||||||
export const runTestScript = (testScript: string, response: TestResponse) =>
|
export const runTestScript = (
|
||||||
|
testScript: string,
|
||||||
|
envs: TestResult["envs"],
|
||||||
|
response: TestResponse
|
||||||
|
) =>
|
||||||
pipe(
|
pipe(
|
||||||
execTestScript(testScript, response),
|
execTestScript(testScript, envs, response),
|
||||||
chain((results) => right(results[0])) // execTestScript returns an array of descriptors with a single element (extract that)
|
TE.chain((results) =>
|
||||||
|
TE.right(<SandboxTestResult>{
|
||||||
|
envs: results.envs,
|
||||||
|
tests: results.tests[0],
|
||||||
|
})
|
||||||
|
) // execTestScript returns an array of descriptors with a single element (extract that)
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,63 +1,148 @@
|
|||||||
import { pipe } from "fp-ts/lib/function"
|
import { pipe } from "fp-ts/function"
|
||||||
import { chain, TaskEither, tryCatch, right, left } from "fp-ts/lib/TaskEither"
|
import * as O from "fp-ts/Option"
|
||||||
|
import * as E from "fp-ts/Either"
|
||||||
|
import * as TE from "fp-ts/lib/TaskEither"
|
||||||
import * as qjs from "quickjs-emscripten"
|
import * as qjs from "quickjs-emscripten"
|
||||||
import clone from "lodash/clone"
|
import cloneDeep from "lodash/clone"
|
||||||
|
import { Environment, parseTemplateStringE } from "@hoppscotch/data"
|
||||||
|
import { getEnv, setEnv } from "./utils"
|
||||||
|
|
||||||
type EnvEntry = {
|
type Envs = {
|
||||||
key: string
|
global: Environment["variables"]
|
||||||
value: string
|
selected: Environment["variables"]
|
||||||
}
|
}
|
||||||
|
|
||||||
export const execPreRequestScript = (
|
export const execPreRequestScript = (
|
||||||
preRequestScript: string,
|
preRequestScript: string,
|
||||||
env: EnvEntry[]
|
envs: Envs
|
||||||
): TaskEither<string, EnvEntry[]> =>
|
): TE.TaskEither<string, Envs> =>
|
||||||
pipe(
|
pipe(
|
||||||
tryCatch(
|
TE.tryCatch(
|
||||||
async () => await qjs.getQuickJS(),
|
async () => await qjs.getQuickJS(),
|
||||||
(reason) => `QuickJS initialization failed: ${reason}`
|
(reason) => `QuickJS initialization failed: ${reason}`
|
||||||
),
|
),
|
||||||
chain((QuickJS) => {
|
TE.chain((QuickJS) => {
|
||||||
const finalEnv = clone(env)
|
let currentEnvs = cloneDeep(envs)
|
||||||
|
|
||||||
const vm = QuickJS.createVm()
|
const vm = QuickJS.createVm()
|
||||||
|
|
||||||
const pwHandle = vm.newObject()
|
const pwHandle = vm.newObject()
|
||||||
|
|
||||||
|
// Environment management APIs
|
||||||
|
// TODO: Unified Implementation
|
||||||
const envHandle = vm.newObject()
|
const envHandle = vm.newObject()
|
||||||
|
|
||||||
const envSetFuncHandle = vm.newFunction(
|
const envGetHandle = vm.newFunction("get", (keyHandle) => {
|
||||||
"set",
|
const key: unknown = vm.dump(keyHandle)
|
||||||
(keyHandle, valueHandle) => {
|
|
||||||
const key = vm.dump(keyHandle)
|
|
||||||
const value = vm.dump(valueHandle)
|
|
||||||
|
|
||||||
if (typeof key !== "string")
|
|
||||||
return {
|
|
||||||
error: vm.newString("Expected key to be a string"),
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof value !== "string")
|
|
||||||
return {
|
|
||||||
error: vm.newString("Expected value to be a string"),
|
|
||||||
}
|
|
||||||
|
|
||||||
const keyIndex = finalEnv.findIndex((env) => env.key === key)
|
|
||||||
|
|
||||||
if (keyIndex === -1) {
|
|
||||||
finalEnv.push({ key, value })
|
|
||||||
} else {
|
|
||||||
finalEnv[keyIndex] = { key, value }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (typeof key !== "string") {
|
||||||
return {
|
return {
|
||||||
value: vm.undefined,
|
error: vm.newString("Expected key to be a string"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
vm.setProp(envHandle, "set", envSetFuncHandle)
|
const result = pipe(
|
||||||
envSetFuncHandle.dispose()
|
getEnv(key, currentEnvs),
|
||||||
|
O.match(
|
||||||
|
() => vm.undefined,
|
||||||
|
({ value }) => vm.newString(value)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
value: result,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const envGetResolveHandle = vm.newFunction("getResolve", (keyHandle) => {
|
||||||
|
const key: unknown = vm.dump(keyHandle)
|
||||||
|
|
||||||
|
if (typeof key !== "string") {
|
||||||
|
return {
|
||||||
|
error: vm.newString("Expected key to be a string"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = pipe(
|
||||||
|
getEnv(key, currentEnvs),
|
||||||
|
E.fromOption(() => "INVALID_KEY" as const),
|
||||||
|
|
||||||
|
E.map(({ value }) =>
|
||||||
|
pipe(
|
||||||
|
parseTemplateStringE(value, [...envs.selected, ...envs.global]),
|
||||||
|
// If the recursive resolution failed, return the unresolved value
|
||||||
|
E.getOrElse(() => value)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
|
||||||
|
// Create a new VM String
|
||||||
|
// NOTE: Do not shorten this to map(vm.newString) apparently it breaks it
|
||||||
|
E.map((x) => vm.newString(x)),
|
||||||
|
|
||||||
|
E.getOrElse(() => vm.undefined)
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
value: result,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const envSetHandle = vm.newFunction("set", (keyHandle, valueHandle) => {
|
||||||
|
const key: unknown = vm.dump(keyHandle)
|
||||||
|
const value: unknown = vm.dump(valueHandle)
|
||||||
|
|
||||||
|
if (typeof key !== "string") {
|
||||||
|
return {
|
||||||
|
error: vm.newString("Expected key to be a string"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof value !== "string") {
|
||||||
|
return {
|
||||||
|
error: vm.newString("Expected value to be a string"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
currentEnvs = setEnv(key, value, currentEnvs)
|
||||||
|
|
||||||
|
return {
|
||||||
|
value: vm.undefined,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const envResolveHandle = vm.newFunction("resolve", (valueHandle) => {
|
||||||
|
const value: unknown = vm.dump(valueHandle)
|
||||||
|
|
||||||
|
if (typeof value !== "string") {
|
||||||
|
return {
|
||||||
|
error: vm.newString("Expected value to be a string"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = pipe(
|
||||||
|
parseTemplateStringE(value, [
|
||||||
|
...currentEnvs.selected,
|
||||||
|
...currentEnvs.global,
|
||||||
|
]),
|
||||||
|
E.getOrElse(() => value)
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
value: vm.newString(result),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
vm.setProp(envHandle, "resolve", envResolveHandle)
|
||||||
|
envResolveHandle.dispose()
|
||||||
|
|
||||||
|
vm.setProp(envHandle, "set", envSetHandle)
|
||||||
|
envSetHandle.dispose()
|
||||||
|
|
||||||
|
vm.setProp(envHandle, "getResolve", envGetResolveHandle)
|
||||||
|
envGetResolveHandle.dispose()
|
||||||
|
|
||||||
|
vm.setProp(envHandle, "get", envGetHandle)
|
||||||
|
envGetHandle.dispose()
|
||||||
|
|
||||||
vm.setProp(pwHandle, "env", envHandle)
|
vm.setProp(pwHandle, "env", envHandle)
|
||||||
envHandle.dispose()
|
envHandle.dispose()
|
||||||
@@ -71,11 +156,11 @@ export const execPreRequestScript = (
|
|||||||
const errorData = vm.dump(evalRes.error)
|
const errorData = vm.dump(evalRes.error)
|
||||||
evalRes.error.dispose()
|
evalRes.error.dispose()
|
||||||
|
|
||||||
return left(errorData)
|
return TE.left(errorData)
|
||||||
}
|
}
|
||||||
|
|
||||||
vm.dispose()
|
vm.dispose()
|
||||||
|
|
||||||
return right(finalEnv)
|
return TE.right(currentEnvs)
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
import { isLeft } from "fp-ts/lib/Either"
|
import * as O from "fp-ts/Option"
|
||||||
import { pipe } from "fp-ts/lib/function"
|
import * as E from "fp-ts/Either"
|
||||||
import { TaskEither, tryCatch, chain, right, left } from "fp-ts/lib/TaskEither"
|
import * as TE from "fp-ts/TaskEither"
|
||||||
|
import { pipe } from "fp-ts/function"
|
||||||
import * as qjs from "quickjs-emscripten"
|
import * as qjs from "quickjs-emscripten"
|
||||||
import { marshalObjectToVM } from "./utils"
|
import { Environment, parseTemplateStringE } from "@hoppscotch/data"
|
||||||
|
import cloneDeep from "lodash/cloneDeep"
|
||||||
|
import { getEnv, marshalObjectToVM, setEnv } from "./utils"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The response object structure exposed to the test script
|
* The response object structure exposed to the test script
|
||||||
@@ -44,6 +47,17 @@ export type TestDescriptor = {
|
|||||||
children: TestDescriptor[]
|
children: TestDescriptor[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the result of a test script execution
|
||||||
|
*/
|
||||||
|
export type TestResult = {
|
||||||
|
tests: TestDescriptor[]
|
||||||
|
envs: {
|
||||||
|
global: Environment["variables"]
|
||||||
|
selected: Environment["variables"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an Expectation object for use inside the sandbox
|
* Creates an Expectation object for use inside the sandbox
|
||||||
* @param vm The QuickJS sandbox VM instance
|
* @param vm The QuickJS sandbox VM instance
|
||||||
@@ -325,16 +339,19 @@ function createExpectation(
|
|||||||
|
|
||||||
export const execTestScript = (
|
export const execTestScript = (
|
||||||
testScript: string,
|
testScript: string,
|
||||||
|
envs: TestResult["envs"],
|
||||||
response: TestResponse
|
response: TestResponse
|
||||||
): TaskEither<string, TestDescriptor[]> =>
|
): TE.TaskEither<string, TestResult> =>
|
||||||
pipe(
|
pipe(
|
||||||
tryCatch(
|
TE.tryCatch(
|
||||||
async () => await qjs.getQuickJS(),
|
async () => await qjs.getQuickJS(),
|
||||||
(reason) => `QuickJS initialization failed: ${reason}`
|
(reason) => `QuickJS initialization failed: ${reason}`
|
||||||
),
|
),
|
||||||
chain(
|
TE.chain(
|
||||||
// TODO: Make this more functional ?
|
// TODO: Make this more functional ?
|
||||||
(QuickJS) => {
|
(QuickJS) => {
|
||||||
|
let currentEnvs = cloneDeep(envs)
|
||||||
|
|
||||||
const vm = QuickJS.createVm()
|
const vm = QuickJS.createVm()
|
||||||
|
|
||||||
const pwHandle = vm.newObject()
|
const pwHandle = vm.newObject()
|
||||||
@@ -374,8 +391,10 @@ export const execTestScript = (
|
|||||||
|
|
||||||
// Marshal response object
|
// Marshal response object
|
||||||
const responseObjHandle = marshalObjectToVM(vm, response)
|
const responseObjHandle = marshalObjectToVM(vm, response)
|
||||||
if (isLeft(responseObjHandle))
|
if (E.isLeft(responseObjHandle))
|
||||||
return left(`Response marshalling failed: ${responseObjHandle.left}`)
|
return TE.left(
|
||||||
|
`Response marshalling failed: ${responseObjHandle.left}`
|
||||||
|
)
|
||||||
|
|
||||||
vm.setProp(pwHandle, "response", responseObjHandle.right)
|
vm.setProp(pwHandle, "response", responseObjHandle.right)
|
||||||
responseObjHandle.right.dispose()
|
responseObjHandle.right.dispose()
|
||||||
@@ -386,6 +405,131 @@ export const execTestScript = (
|
|||||||
vm.setProp(pwHandle, "test", testFuncHandle)
|
vm.setProp(pwHandle, "test", testFuncHandle)
|
||||||
testFuncHandle.dispose()
|
testFuncHandle.dispose()
|
||||||
|
|
||||||
|
// Environment management APIs
|
||||||
|
// TODO: Unified Implementation
|
||||||
|
const envHandle = vm.newObject()
|
||||||
|
|
||||||
|
const envGetHandle = vm.newFunction("get", (keyHandle) => {
|
||||||
|
const key: unknown = vm.dump(keyHandle)
|
||||||
|
|
||||||
|
if (typeof key !== "string") {
|
||||||
|
return {
|
||||||
|
error: vm.newString("Expected key to be a string"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = pipe(
|
||||||
|
getEnv(key, currentEnvs),
|
||||||
|
O.match(
|
||||||
|
() => vm.undefined,
|
||||||
|
({ value }) => vm.newString(value)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
value: result,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const envGetResolveHandle = vm.newFunction(
|
||||||
|
"getResolve",
|
||||||
|
(keyHandle) => {
|
||||||
|
const key: unknown = vm.dump(keyHandle)
|
||||||
|
|
||||||
|
if (typeof key !== "string") {
|
||||||
|
return {
|
||||||
|
error: vm.newString("Expected key to be a string"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = pipe(
|
||||||
|
getEnv(key, currentEnvs),
|
||||||
|
E.fromOption(() => "INVALID_KEY" as const),
|
||||||
|
|
||||||
|
E.map(({ value }) =>
|
||||||
|
pipe(
|
||||||
|
parseTemplateStringE(value, [
|
||||||
|
...envs.selected,
|
||||||
|
...envs.global,
|
||||||
|
]),
|
||||||
|
// If the recursive resolution failed, return the unresolved value
|
||||||
|
E.getOrElse(() => value)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
|
||||||
|
// Create a new VM String
|
||||||
|
// NOTE: Do not shorten this to map(vm.newString) apparently it breaks it
|
||||||
|
E.map((x) => vm.newString(x)),
|
||||||
|
|
||||||
|
E.getOrElse(() => vm.undefined)
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
value: result,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const envSetHandle = vm.newFunction("set", (keyHandle, valueHandle) => {
|
||||||
|
const key: unknown = vm.dump(keyHandle)
|
||||||
|
const value: unknown = vm.dump(valueHandle)
|
||||||
|
|
||||||
|
if (typeof key !== "string") {
|
||||||
|
return {
|
||||||
|
error: vm.newString("Expected key to be a string"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof value !== "string") {
|
||||||
|
return {
|
||||||
|
error: vm.newString("Expected value to be a string"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
currentEnvs = setEnv(key, value, currentEnvs)
|
||||||
|
|
||||||
|
return {
|
||||||
|
value: vm.undefined,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const envResolveHandle = vm.newFunction("resolve", (valueHandle) => {
|
||||||
|
const value: unknown = vm.dump(valueHandle)
|
||||||
|
|
||||||
|
if (typeof value !== "string") {
|
||||||
|
return {
|
||||||
|
error: vm.newString("Expected value to be a string"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = pipe(
|
||||||
|
parseTemplateStringE(value, [
|
||||||
|
...currentEnvs.selected,
|
||||||
|
...currentEnvs.global,
|
||||||
|
]),
|
||||||
|
E.getOrElse(() => value)
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
value: vm.newString(result),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
vm.setProp(envHandle, "resolve", envResolveHandle)
|
||||||
|
envResolveHandle.dispose()
|
||||||
|
|
||||||
|
vm.setProp(envHandle, "set", envSetHandle)
|
||||||
|
envSetHandle.dispose()
|
||||||
|
|
||||||
|
vm.setProp(envHandle, "getResolve", envGetResolveHandle)
|
||||||
|
envGetResolveHandle.dispose()
|
||||||
|
|
||||||
|
vm.setProp(envHandle, "get", envGetHandle)
|
||||||
|
envGetHandle.dispose()
|
||||||
|
|
||||||
|
vm.setProp(pwHandle, "env", envHandle)
|
||||||
|
envHandle.dispose()
|
||||||
|
|
||||||
vm.setProp(vm.global, "pw", pwHandle)
|
vm.setProp(vm.global, "pw", pwHandle)
|
||||||
pwHandle.dispose()
|
pwHandle.dispose()
|
||||||
|
|
||||||
@@ -395,12 +539,15 @@ export const execTestScript = (
|
|||||||
const errorData = vm.dump(evalRes.error)
|
const errorData = vm.dump(evalRes.error)
|
||||||
evalRes.error.dispose()
|
evalRes.error.dispose()
|
||||||
|
|
||||||
return left(`Script evaluation failed: ${errorData}`)
|
return TE.left(`Script evaluation failed: ${errorData}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
vm.dispose()
|
vm.dispose()
|
||||||
|
|
||||||
return right(testRunStack)
|
return TE.right({
|
||||||
|
tests: testRunStack,
|
||||||
|
envs: currentEnvs,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,16 +1,18 @@
|
|||||||
import { Either, left, right } from "fp-ts/lib/Either"
|
import * as O from "fp-ts/Option"
|
||||||
|
import * as E from "fp-ts/Either"
|
||||||
import * as QuickJS from "quickjs-emscripten"
|
import * as QuickJS from "quickjs-emscripten"
|
||||||
|
import { TestResult } from "./test-runner"
|
||||||
|
|
||||||
export function marshalObjectToVM(
|
export function marshalObjectToVM(
|
||||||
vm: QuickJS.QuickJSVm,
|
vm: QuickJS.QuickJSVm,
|
||||||
obj: object
|
obj: object
|
||||||
): Either<string, QuickJS.QuickJSHandle> {
|
): E.Either<string, QuickJS.QuickJSHandle> {
|
||||||
let jsonString
|
let jsonString
|
||||||
|
|
||||||
try {
|
try {
|
||||||
jsonString = JSON.stringify(obj)
|
jsonString = JSON.stringify(obj)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return left("Marshaling stringification failed")
|
return E.left("Marshaling stringification failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
const vmStringHandle = vm.newString(jsonString)
|
const vmStringHandle = vm.newString(jsonString)
|
||||||
@@ -26,7 +28,7 @@ export function marshalObjectToVM(
|
|||||||
|
|
||||||
if (parseResultHandle.error) {
|
if (parseResultHandle.error) {
|
||||||
parseResultHandle.error.dispose()
|
parseResultHandle.error.dispose()
|
||||||
return left("Marshaling failed")
|
return E.left("Marshaling failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
const resultHandle = vm.unwrapResult(parseResultHandle)
|
const resultHandle = vm.unwrapResult(parseResultHandle)
|
||||||
@@ -35,5 +37,53 @@ export function marshalObjectToVM(
|
|||||||
parseFuncHandle.dispose()
|
parseFuncHandle.dispose()
|
||||||
jsonHandle.dispose()
|
jsonHandle.dispose()
|
||||||
|
|
||||||
return right(resultHandle)
|
return E.right(resultHandle)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getEnv(envName: string, envs: TestResult["envs"]) {
|
||||||
|
return O.fromNullable(
|
||||||
|
envs.selected.find((x) => x.key === envName) ??
|
||||||
|
envs.global.find((x) => x.key === envName)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setEnv(
|
||||||
|
envName: string,
|
||||||
|
envValue: string,
|
||||||
|
envs: TestResult["envs"]
|
||||||
|
): TestResult["envs"] {
|
||||||
|
const indexInSelected = envs.selected.findIndex((x) => x.key === envName)
|
||||||
|
|
||||||
|
// Found the match in selected
|
||||||
|
if (indexInSelected >= 0) {
|
||||||
|
envs.selected[indexInSelected].value = envValue
|
||||||
|
|
||||||
|
return {
|
||||||
|
global: envs.global,
|
||||||
|
selected: envs.selected,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const indexInGlobal = envs.global.findIndex((x) => x.key == envName)
|
||||||
|
|
||||||
|
// Found a match in globals
|
||||||
|
if (indexInGlobal >= 0) {
|
||||||
|
envs.global[indexInGlobal].value = envValue
|
||||||
|
|
||||||
|
return {
|
||||||
|
global: envs.global,
|
||||||
|
selected: envs.selected,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Didn't find in both places, create a new variable in selected
|
||||||
|
envs.selected.push({
|
||||||
|
key: envName,
|
||||||
|
value: envValue,
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
global: envs.global,
|
||||||
|
selected: envs.selected,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
428
pnpm-lock.yaml
generated
428
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user