feat: better fields
This commit is contained in:
+164
-91
@@ -720,13 +720,22 @@
|
|||||||
.function-mocks-table-grid {
|
.function-mocks-table-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.function-mocks-table-grid--rest {
|
||||||
grid-template-columns:
|
grid-template-columns:
|
||||||
minmax(150px, 1fr)
|
minmax(150px, 1fr)
|
||||||
minmax(240px, 1.3fr)
|
minmax(240px, 1.3fr)
|
||||||
minmax(220px, 1.2fr)
|
minmax(220px, 1.2fr)
|
||||||
minmax(180px, 1fr)
|
minmax(180px, 1fr);
|
||||||
minmax(260px, 1.3fr);
|
}
|
||||||
align-items: stretch;
|
|
||||||
|
.function-mocks-table-grid--rpc {
|
||||||
|
grid-template-columns:
|
||||||
|
minmax(150px, 1fr)
|
||||||
|
minmax(280px, 1.35fr)
|
||||||
|
minmax(320px, 1.65fr);
|
||||||
}
|
}
|
||||||
|
|
||||||
.function-mocks-header {
|
.function-mocks-header {
|
||||||
@@ -1567,7 +1576,7 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div v-if="activeTestMockBindingMode(mockSet) === 'rest'">
|
||||||
<label
|
<label
|
||||||
class="field-label"
|
class="field-label"
|
||||||
:for="`test-mock-item-request-type-${group.key}-${testEntry.index}-${mockSetIndex}-${activeTestMockBindingName(mockSet)}-${itemIndex}`"
|
:for="`test-mock-item-request-type-${group.key}-${testEntry.index}-${mockSetIndex}-${activeTestMockBindingName(mockSet)}-${itemIndex}`"
|
||||||
@@ -1585,7 +1594,7 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div v-if="activeTestMockBindingMode(mockSet) === 'rest'">
|
||||||
<label
|
<label
|
||||||
class="field-label"
|
class="field-label"
|
||||||
:for="`test-mock-item-request-body-${group.key}-${testEntry.index}-${mockSetIndex}-${activeTestMockBindingName(mockSet)}-${itemIndex}`"
|
:for="`test-mock-item-request-body-${group.key}-${testEntry.index}-${mockSetIndex}-${activeTestMockBindingName(mockSet)}-${itemIndex}`"
|
||||||
@@ -1918,12 +1927,19 @@
|
|||||||
<div class="settings-editor" v-if="currentFunctionMockRows.length">
|
<div class="settings-editor" v-if="currentFunctionMockRows.length">
|
||||||
<div class="function-mocks-table-wrap">
|
<div class="function-mocks-table-wrap">
|
||||||
<div class="function-mocks-table">
|
<div class="function-mocks-table">
|
||||||
<div class="function-mocks-header function-mocks-table-grid">
|
<div
|
||||||
|
class="function-mocks-header function-mocks-table-grid"
|
||||||
|
:class="`function-mocks-table-grid--${currentFunctionMockEditorMode}`"
|
||||||
|
>
|
||||||
<div class="function-mocks-heading">Mock Name</div>
|
<div class="function-mocks-heading">Mock Name</div>
|
||||||
<div class="function-mocks-heading">Method</div>
|
<div class="function-mocks-heading">Method</div>
|
||||||
<div class="function-mocks-heading">Headers JSON</div>
|
<template v-if="currentFunctionMockEditorMode === 'rest'">
|
||||||
<div class="function-mocks-heading">Query Params JSON</div>
|
<div class="function-mocks-heading">Headers JSON</div>
|
||||||
<div class="function-mocks-heading">Response</div>
|
<div class="function-mocks-heading">Query Params JSON</div>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<div class="function-mocks-heading">Response</div>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
@@ -1931,7 +1947,10 @@
|
|||||||
:key="mockRow.id"
|
:key="mockRow.id"
|
||||||
class="function-mocks-row"
|
class="function-mocks-row"
|
||||||
>
|
>
|
||||||
<div class="function-mocks-table-grid">
|
<div
|
||||||
|
class="function-mocks-table-grid"
|
||||||
|
:class="`function-mocks-table-grid--${functionMockRowMode(mockRow)}`"
|
||||||
|
>
|
||||||
<div>
|
<div>
|
||||||
<input
|
<input
|
||||||
:id="`function-mock-name-${mockRow.id}`"
|
:id="`function-mock-name-${mockRow.id}`"
|
||||||
@@ -2015,68 +2034,74 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="function-mock-json-cell">
|
<template v-if="functionMockRowMode(mockRow) === 'rest'">
|
||||||
<textarea
|
<div class="function-mock-json-cell">
|
||||||
:id="`function-mock-headers-${mockRow.id}`"
|
|
||||||
v-model="mockRow.headersText"
|
|
||||||
class="native-textarea"
|
|
||||||
placeholder='{"Authorization":"Bearer ..."}'
|
|
||||||
spellcheck="false"
|
|
||||||
@input="persistFunctionMocks({ silent: true })"
|
|
||||||
></textarea>
|
|
||||||
<div class="settings-hint q-mt-sm">
|
|
||||||
Headers JSON: JSON object of request headers that must match.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="function-mock-json-cell">
|
|
||||||
<textarea
|
|
||||||
:id="`function-mock-query-${mockRow.id}`"
|
|
||||||
v-model="mockRow.queryParamsText"
|
|
||||||
class="native-textarea"
|
|
||||||
placeholder='{"foo":"bar"}'
|
|
||||||
spellcheck="false"
|
|
||||||
@input="persistFunctionMocks({ silent: true })"
|
|
||||||
></textarea>
|
|
||||||
<div class="settings-hint q-mt-sm">
|
|
||||||
Query Params JSON: JSON object of expected query-string parameters.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="function-mock-cell-stack">
|
|
||||||
<div class="function-mock-subfield">
|
|
||||||
<input
|
|
||||||
:id="`function-mock-response-type-${mockRow.id}`"
|
|
||||||
v-model="mockRow.responseType"
|
|
||||||
class="native-input"
|
|
||||||
type="text"
|
|
||||||
placeholder="json"
|
|
||||||
spellcheck="false"
|
|
||||||
@input="persistFunctionMocks({ silent: true })"
|
|
||||||
/>
|
|
||||||
<div class="settings-hint">
|
|
||||||
Response Type: Optional response mode such as
|
|
||||||
<code>json</code>,
|
|
||||||
<code>data</code>,
|
|
||||||
or
|
|
||||||
<code>exception</code>.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="function-mock-subfield">
|
|
||||||
<textarea
|
<textarea
|
||||||
:id="`function-mock-response-${mockRow.id}`"
|
:id="`function-mock-headers-${mockRow.id}`"
|
||||||
v-model="mockRow.responseText"
|
v-model="mockRow.headersText"
|
||||||
class="native-textarea"
|
class="native-textarea"
|
||||||
placeholder='{"field":"value"}'
|
placeholder='{"Authorization":"Bearer ..."}'
|
||||||
spellcheck="false"
|
spellcheck="false"
|
||||||
@input="persistFunctionMocks({ silent: true })"
|
@input="persistFunctionMocks({ silent: true })"
|
||||||
></textarea>
|
></textarea>
|
||||||
<div class="settings-hint">
|
<div class="settings-hint q-mt-sm">
|
||||||
Response Body: JSON payload, data object, or exception body returned by the mock.
|
Headers JSON: JSON object of request headers that must match.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
<div class="function-mock-json-cell">
|
||||||
|
<textarea
|
||||||
|
:id="`function-mock-query-${mockRow.id}`"
|
||||||
|
v-model="mockRow.queryParamsText"
|
||||||
|
class="native-textarea"
|
||||||
|
placeholder='{"foo":"bar"}'
|
||||||
|
spellcheck="false"
|
||||||
|
@input="persistFunctionMocks({ silent: true })"
|
||||||
|
></textarea>
|
||||||
|
<div class="settings-hint q-mt-sm">
|
||||||
|
Query Params JSON: JSON object of expected query-string parameters.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-else>
|
||||||
|
<div class="function-mock-cell-stack">
|
||||||
|
<div class="function-mock-subfield">
|
||||||
|
<input
|
||||||
|
:id="`function-mock-response-type-${mockRow.id}`"
|
||||||
|
v-model="mockRow.responseType"
|
||||||
|
class="native-input"
|
||||||
|
type="text"
|
||||||
|
placeholder="data"
|
||||||
|
spellcheck="false"
|
||||||
|
@input="persistFunctionMocks({ silent: true })"
|
||||||
|
/>
|
||||||
|
<div class="settings-hint">
|
||||||
|
Response Type: Optional RPC return mode such as
|
||||||
|
<code>data</code>,
|
||||||
|
<code>function</code>,
|
||||||
|
<code>async-function</code>,
|
||||||
|
<code>json</code>,
|
||||||
|
or
|
||||||
|
<code>exception</code>.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="function-mock-subfield">
|
||||||
|
<textarea
|
||||||
|
:id="`function-mock-response-${mockRow.id}`"
|
||||||
|
v-model="mockRow.responseText"
|
||||||
|
class="native-textarea"
|
||||||
|
placeholder='{"method_name":{"request_type":"function","response_type":"json","response":{}}}'
|
||||||
|
spellcheck="false"
|
||||||
|
@input="persistFunctionMocks({ silent: true })"
|
||||||
|
></textarea>
|
||||||
|
<div class="settings-hint">
|
||||||
|
Response: RPC mock object returned by the patched function.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="mockRow.error" class="settings-error function-mocks-note">
|
<div v-if="mockRow.error" class="settings-error function-mocks-note">
|
||||||
@@ -2859,6 +2884,13 @@
|
|||||||
this.currentTestFundingSourceName
|
this.currentTestFundingSourceName
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
currentFunctionMockEditorMode() {
|
||||||
|
if (this.currentFunctionMockRows.length) {
|
||||||
|
return this.functionMockRowMode(this.currentFunctionMockRows[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.selectedDatasetKey === 'rpc' ? 'rpc' : 'rest'
|
||||||
|
},
|
||||||
currentFunctionMockNameOptions() {
|
currentFunctionMockNameOptions() {
|
||||||
const seen = new Set()
|
const seen = new Set()
|
||||||
|
|
||||||
@@ -3763,6 +3795,32 @@
|
|||||||
) || null
|
) || null
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
functionMockRowMode(row) {
|
||||||
|
return row?.requestType === 'function' ? 'rpc' : 'rest'
|
||||||
|
},
|
||||||
|
functionMockModeByName(mockName) {
|
||||||
|
const normalizedName = (mockName || '').trim()
|
||||||
|
if (!normalizedName) {
|
||||||
|
return this.selectedDatasetKey === 'rpc' ? 'rpc' : 'rest'
|
||||||
|
}
|
||||||
|
|
||||||
|
const draftRow = this.currentFunctionMockRows.find(
|
||||||
|
row => (row.name || '').trim() === normalizedName
|
||||||
|
)
|
||||||
|
if (draftRow) {
|
||||||
|
return this.functionMockRowMode(draftRow)
|
||||||
|
}
|
||||||
|
|
||||||
|
const mockValue =
|
||||||
|
this.datasets[this.selectedDatasetKey].data?.functions?.[
|
||||||
|
this.currentFunctionName
|
||||||
|
]?.mocks?.[this.currentTestFundingSourceName]?.[normalizedName] || {}
|
||||||
|
|
||||||
|
return mockValue?.request_type === 'function' ? 'rpc' : 'rest'
|
||||||
|
},
|
||||||
|
activeTestMockBindingMode(mockSet) {
|
||||||
|
return this.functionMockModeByName(this.activeTestMockBindingName(mockSet))
|
||||||
|
},
|
||||||
nextAvailableTestMockName(mockSet) {
|
nextAvailableTestMockName(mockSet) {
|
||||||
const usedNames = new Set(
|
const usedNames = new Set(
|
||||||
(mockSet.bindings || [])
|
(mockSet.bindings || [])
|
||||||
@@ -4004,46 +4062,49 @@
|
|||||||
},
|
},
|
||||||
parseFunctionMockRowBody(row) {
|
parseFunctionMockRowBody(row) {
|
||||||
const mock = {}
|
const mock = {}
|
||||||
|
const mode = this.functionMockRowMode(row)
|
||||||
|
|
||||||
const name = row.name.trim()
|
const name = row.name.trim()
|
||||||
if (!name) {
|
if (!name) {
|
||||||
throw new Error('Mock name cannot be empty.')
|
throw new Error('Mock name cannot be empty.')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (row.uri.trim() !== '') {
|
|
||||||
mock.uri = row.uri
|
|
||||||
}
|
|
||||||
|
|
||||||
if (row.method.trim() !== '') {
|
if (row.method.trim() !== '') {
|
||||||
mock.method = row.method
|
mock.method = row.method
|
||||||
}
|
}
|
||||||
|
|
||||||
if (row.headersText.trim() !== '') {
|
if (mode === 'rest') {
|
||||||
const parsedHeaders = JSON.parse(row.headersText)
|
if (row.uri.trim() !== '') {
|
||||||
if (!isPlainObject(parsedHeaders)) {
|
mock.uri = row.uri
|
||||||
throw new Error('Headers must be a JSON object.')
|
|
||||||
}
|
}
|
||||||
mock.headers = parsedHeaders
|
|
||||||
}
|
|
||||||
|
|
||||||
if (row.queryParamsText.trim() !== '') {
|
if (row.headersText.trim() !== '') {
|
||||||
const parsedQueryParams = JSON.parse(row.queryParamsText)
|
const parsedHeaders = JSON.parse(row.headersText)
|
||||||
if (!isPlainObject(parsedQueryParams)) {
|
if (!isPlainObject(parsedHeaders)) {
|
||||||
throw new Error('Query params must be a JSON object.')
|
throw new Error('Headers must be a JSON object.')
|
||||||
|
}
|
||||||
|
mock.headers = parsedHeaders
|
||||||
}
|
}
|
||||||
mock.query_params = parsedQueryParams
|
|
||||||
}
|
|
||||||
|
|
||||||
if (row.requestType.trim() !== '') {
|
if (row.queryParamsText.trim() !== '') {
|
||||||
mock.request_type = row.requestType
|
const parsedQueryParams = JSON.parse(row.queryParamsText)
|
||||||
}
|
if (!isPlainObject(parsedQueryParams)) {
|
||||||
|
throw new Error('Query params must be a JSON object.')
|
||||||
|
}
|
||||||
|
mock.query_params = parsedQueryParams
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (row.requestType.trim() !== '') {
|
||||||
|
mock.request_type = row.requestType
|
||||||
|
}
|
||||||
|
|
||||||
if (row.responseType.trim() !== '') {
|
if (row.responseType.trim() !== '') {
|
||||||
mock.response_type = row.responseType
|
mock.response_type = row.responseType
|
||||||
}
|
}
|
||||||
|
|
||||||
if (row.responseText.trim() !== '') {
|
if (row.responseText.trim() !== '') {
|
||||||
mock.response = JSON.parse(row.responseText)
|
mock.response = JSON.parse(row.responseText)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return mock
|
return mock
|
||||||
@@ -4060,6 +4121,11 @@
|
|||||||
|
|
||||||
if (row.requestType === 'function') {
|
if (row.requestType === 'function') {
|
||||||
row.uri = ''
|
row.uri = ''
|
||||||
|
row.headersText = ''
|
||||||
|
row.queryParamsText = ''
|
||||||
|
} else {
|
||||||
|
row.responseType = ''
|
||||||
|
row.responseText = ''
|
||||||
}
|
}
|
||||||
|
|
||||||
this.persistFunctionMocks({ silent: true })
|
this.persistFunctionMocks({ silent: true })
|
||||||
@@ -4167,6 +4233,7 @@
|
|||||||
|
|
||||||
for (const binding of mockSet.bindings || []) {
|
for (const binding of mockSet.bindings || []) {
|
||||||
const mockName = (binding.selectedMockName || '').trim()
|
const mockName = (binding.selectedMockName || '').trim()
|
||||||
|
const bindingMode = this.functionMockModeByName(mockName)
|
||||||
|
|
||||||
if (!mockName) {
|
if (!mockName) {
|
||||||
if ((binding.items || []).length) {
|
if ((binding.items || []).length) {
|
||||||
@@ -4210,11 +4277,17 @@
|
|||||||
nextItem.skip = Boolean(item.skip)
|
nextItem.skip = Boolean(item.skip)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((item.requestType || '').trim() !== '') {
|
if (
|
||||||
|
bindingMode === 'rest' &&
|
||||||
|
(item.requestType || '').trim() !== ''
|
||||||
|
) {
|
||||||
nextItem.request_type = item.requestType.trim()
|
nextItem.request_type = item.requestType.trim()
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((item.requestBodyText || '').trim() !== '') {
|
if (
|
||||||
|
bindingMode === 'rest' &&
|
||||||
|
(item.requestBodyText || '').trim() !== ''
|
||||||
|
) {
|
||||||
try {
|
try {
|
||||||
nextItem.request_body = this.parseEditableTestJson(
|
nextItem.request_body = this.parseEditableTestJson(
|
||||||
item.requestBodyText,
|
item.requestBodyText,
|
||||||
|
|||||||
Reference in New Issue
Block a user