207 lines
5 KiB
Vue
207 lines
5 KiB
Vue
<template>
|
|
<HoppSmartTabs
|
|
v-if="doc.response"
|
|
v-model="selectedLensTab"
|
|
styles="sticky overflow-x-auto flex-shrink-0 z-10 bg-primary top-lowerPrimaryStickyFold"
|
|
>
|
|
<HoppSmartTab
|
|
v-for="(lens, index) in validLenses"
|
|
:id="lens.renderer"
|
|
:key="`lens-${index}`"
|
|
:label="t(lens.lensName)"
|
|
class="flex h-full w-full flex-1 flex-col"
|
|
>
|
|
<component
|
|
:is="lensRendererFor(lens.renderer)"
|
|
v-model:response="doc.response"
|
|
:is-savable="isSavable"
|
|
:is-editable="isEditable"
|
|
:tab-id="props.tabId"
|
|
@save-as-example="$emit('save-as-example')"
|
|
/>
|
|
</HoppSmartTab>
|
|
<HoppSmartTab
|
|
v-if="maybeHeaders"
|
|
id="headers"
|
|
:label="t('response.headers')"
|
|
:info="`${maybeHeaders.length}`"
|
|
class="flex flex-1 flex-col"
|
|
>
|
|
<LensesHeadersRenderer v-model="maybeHeaders" :is-editable="false" />
|
|
</HoppSmartTab>
|
|
<HoppSmartTab
|
|
v-if="doc.response?.type !== 'network_fail' && !isEditable"
|
|
id="results"
|
|
:label="t('test.results')"
|
|
:indicator="showIndicator"
|
|
class="flex flex-1 flex-col"
|
|
>
|
|
<HttpTestResult
|
|
v-model="doc.testResults"
|
|
:is-loading="doc.response?.type === 'loading'"
|
|
/>
|
|
</HoppSmartTab>
|
|
<HoppSmartTab
|
|
v-if="requestHeaders"
|
|
id="req-headers"
|
|
:label="t('response.request_headers')"
|
|
:info="`${requestHeaders?.length}`"
|
|
class="flex flex-1 flex-col"
|
|
>
|
|
<LensesHeadersRenderer
|
|
:model-value="requestHeaders"
|
|
:is-editable="false"
|
|
/>
|
|
</HoppSmartTab>
|
|
<HoppSmartTab
|
|
v-if="showConsoleTab"
|
|
id="console"
|
|
label="Console"
|
|
class="flex flex-1 flex-col"
|
|
>
|
|
<ConsolePanel :messages="consoleEntries" />
|
|
</HoppSmartTab>
|
|
</HoppSmartTabs>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { useI18n } from "@composables/i18n"
|
|
import { useVModel } from "@vueuse/core"
|
|
import { computed, ref, watch } from "vue"
|
|
import { useSetting } from "~/composables/settings"
|
|
import {
|
|
getLensRenderers,
|
|
getSuitableLenses,
|
|
Lens,
|
|
} from "~/helpers/lenses/lenses"
|
|
import { HoppRequestDocument } from "~/helpers/rest/document"
|
|
import { ConsoleEntry } from "../console/Panel.vue"
|
|
|
|
const props = defineProps<{
|
|
document: HoppRequestDocument
|
|
isEditable: boolean
|
|
tabId: string
|
|
isTestRunner?: boolean
|
|
}>()
|
|
|
|
const emit = defineEmits<{
|
|
(e: "update:document", document: HoppRequestDocument): void
|
|
(e: "save-as-example"): void
|
|
}>()
|
|
|
|
const doc = useVModel(props, "document", emit)
|
|
const t = useI18n()
|
|
const EXPERIMENTAL_SCRIPTING_SANDBOX = useSetting(
|
|
"EXPERIMENTAL_SCRIPTING_SANDBOX"
|
|
)
|
|
|
|
const isSavable = computed(() => {
|
|
return doc.value.response?.type === "success" && doc.value.saveContext
|
|
})
|
|
|
|
const showIndicator = computed(() => {
|
|
if (!doc.value.testResults) return false
|
|
|
|
const { expectResults, tests, envDiff } = doc.value.testResults
|
|
return Boolean(
|
|
expectResults.length ||
|
|
tests.length ||
|
|
envDiff.selected.additions.length ||
|
|
envDiff.selected.updations.length ||
|
|
envDiff.global.updations.length
|
|
)
|
|
})
|
|
|
|
const allLensRenderers = getLensRenderers()
|
|
|
|
function lensRendererFor(name: string) {
|
|
return allLensRenderers[name]
|
|
}
|
|
|
|
const selectedLensTab = ref("")
|
|
|
|
const maybeHeaders = computed(() => {
|
|
if (
|
|
!doc.value.response ||
|
|
!(
|
|
doc.value.response.type === "success" ||
|
|
doc.value.response.type === "fail"
|
|
)
|
|
)
|
|
return null
|
|
return doc.value.response.headers
|
|
})
|
|
|
|
const requestHeaders = computed(() => {
|
|
if (
|
|
!props.isTestRunner ||
|
|
!doc.value.response ||
|
|
!(
|
|
doc.value.response.type === "success" ||
|
|
doc.value.response.type === "fail" ||
|
|
doc.value.response.type === "network_fail"
|
|
)
|
|
)
|
|
return null
|
|
return doc.value.response?.req.headers || doc.value.request.headers
|
|
})
|
|
|
|
const validLenses = computed(() => {
|
|
if (!doc.value.response) return []
|
|
return getSuitableLenses(doc.value.response)
|
|
})
|
|
|
|
const showConsoleTab = computed(() => {
|
|
if (!doc.value.testResults?.consoleEntries) {
|
|
return false
|
|
}
|
|
|
|
return (
|
|
doc.value.testResults?.consoleEntries.length > 0 &&
|
|
EXPERIMENTAL_SCRIPTING_SANDBOX.value
|
|
)
|
|
})
|
|
|
|
const consoleEntries = computed(() => {
|
|
if (!doc.value.testResults?.consoleEntries) {
|
|
return []
|
|
}
|
|
|
|
return doc.value.testResults?.consoleEntries.filter(({ type }) =>
|
|
["log", "warn", "debug", "error", "info"].includes(type)
|
|
) as ConsoleEntry[]
|
|
})
|
|
|
|
watch(
|
|
validLenses,
|
|
(newLenses: Lens[]) => {
|
|
if (newLenses.length === 0) {
|
|
selectedLensTab.value = "req-headers"
|
|
return
|
|
}
|
|
|
|
const validRenderers = [
|
|
...newLenses.map((x) => x.renderer),
|
|
"headers",
|
|
"results",
|
|
]
|
|
|
|
const { responseTabPreference } = doc.value
|
|
|
|
if (
|
|
responseTabPreference &&
|
|
validRenderers.includes(responseTabPreference)
|
|
) {
|
|
selectedLensTab.value = responseTabPreference
|
|
} else {
|
|
selectedLensTab.value = newLenses[0].renderer
|
|
}
|
|
},
|
|
{ immediate: true }
|
|
)
|
|
|
|
watch(selectedLensTab, (newLensID) => {
|
|
if (props.isTestRunner) return
|
|
doc.value.responseTabPreference = newLensID
|
|
})
|
|
</script>
|