feat: better ui
This commit is contained in:
+571
-47
@@ -1477,22 +1477,21 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-for="(binding, bindingIndex) in mockSet.bindings"
|
|
||||||
:key="`${mockSet.path}-binding-${bindingIndex}`"
|
|
||||||
class="test-mock-binding"
|
class="test-mock-binding"
|
||||||
|
:key="`${mockSet.path}-binding-${activeTestMockBindingName(mockSet)}`"
|
||||||
>
|
>
|
||||||
<div class="test-mock-binding-header">
|
<div class="test-mock-binding-header">
|
||||||
<div class="test-mock-binding-body">
|
<div class="test-mock-binding-body">
|
||||||
<label
|
<label
|
||||||
class="field-label"
|
class="field-label"
|
||||||
:for="`test-mock-binding-${group.key}-${testEntry.index}-${mockSetIndex}-${bindingIndex}`"
|
:for="`test-mock-binding-${group.key}-${testEntry.index}-${mockSetIndex}`"
|
||||||
>
|
>
|
||||||
Function Mock
|
Function Mock
|
||||||
</label>
|
</label>
|
||||||
<q-select
|
<q-select
|
||||||
:id="`test-mock-binding-${group.key}-${testEntry.index}-${mockSetIndex}-${bindingIndex}`"
|
:id="`test-mock-binding-${group.key}-${testEntry.index}-${mockSetIndex}`"
|
||||||
:model-value="binding.selectedMockName"
|
:model-value="activeTestMockBindingName(mockSet)"
|
||||||
:options="testMockBindingOptions(binding.selectedMockName)"
|
:options="testMockBindingOptions(mockSet)"
|
||||||
emit-value
|
emit-value
|
||||||
map-options
|
map-options
|
||||||
outlined
|
outlined
|
||||||
@@ -1501,7 +1500,7 @@
|
|||||||
behavior="menu"
|
behavior="menu"
|
||||||
hide-dropdown-icon
|
hide-dropdown-icon
|
||||||
class="fixture-select"
|
class="fixture-select"
|
||||||
@update:model-value="handleTestMockBindingSelection(testEntry, mockSet, binding, $event)"
|
@update:model-value="handleTestMockBindingSelection(testEntry, mockSet, $event)"
|
||||||
>
|
>
|
||||||
<template v-slot:append>
|
<template v-slot:append>
|
||||||
<span class="fixture-select-icon" aria-hidden="true">expand_more</span>
|
<span class="fixture-select-icon" aria-hidden="true">expand_more</span>
|
||||||
@@ -1510,10 +1509,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="test-mock-item-list" v-if="binding.items.length">
|
<div
|
||||||
|
class="test-mock-item-list"
|
||||||
|
v-if="activeTestMockBinding(mockSet) && activeTestMockBinding(mockSet).items.length"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
v-for="(item, itemIndex) in binding.items"
|
v-for="(item, itemIndex) in activeTestMockBinding(mockSet).items"
|
||||||
:key="`${mockSet.path}-binding-${bindingIndex}-item-${itemIndex}`"
|
:key="`${mockSet.path}-binding-${activeTestMockBindingName(mockSet)}-item-${itemIndex}`"
|
||||||
class="test-mock-item-card"
|
class="test-mock-item-card"
|
||||||
>
|
>
|
||||||
<div class="section-title">
|
<div class="section-title">
|
||||||
@@ -1524,7 +1526,7 @@
|
|||||||
color="negative"
|
color="negative"
|
||||||
outline
|
outline
|
||||||
label="Remove"
|
label="Remove"
|
||||||
@click="removeTestMockBindingItem(testEntry, mockSet, binding, itemIndex)"
|
@click="removeTestMockBindingItem(testEntry, mockSet, activeTestMockBinding(mockSet), itemIndex)"
|
||||||
></q-btn>
|
></q-btn>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -1543,12 +1545,12 @@
|
|||||||
<div>
|
<div>
|
||||||
<label
|
<label
|
||||||
class="field-label"
|
class="field-label"
|
||||||
:for="`test-mock-item-description-${group.key}-${testEntry.index}-${mockSetIndex}-${bindingIndex}-${itemIndex}`"
|
:for="`test-mock-item-description-${group.key}-${testEntry.index}-${mockSetIndex}-${activeTestMockBindingName(mockSet)}-${itemIndex}`"
|
||||||
>
|
>
|
||||||
Description
|
Description
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
:id="`test-mock-item-description-${group.key}-${testEntry.index}-${mockSetIndex}-${bindingIndex}-${itemIndex}`"
|
:id="`test-mock-item-description-${group.key}-${testEntry.index}-${mockSetIndex}-${activeTestMockBindingName(mockSet)}-${itemIndex}`"
|
||||||
v-model="item.descriptionText"
|
v-model="item.descriptionText"
|
||||||
class="native-input"
|
class="native-input"
|
||||||
type="text"
|
type="text"
|
||||||
@@ -1561,12 +1563,12 @@
|
|||||||
<div>
|
<div>
|
||||||
<label
|
<label
|
||||||
class="field-label"
|
class="field-label"
|
||||||
:for="`test-mock-item-request-type-${group.key}-${testEntry.index}-${mockSetIndex}-${bindingIndex}-${itemIndex}`"
|
:for="`test-mock-item-request-type-${group.key}-${testEntry.index}-${mockSetIndex}-${activeTestMockBindingName(mockSet)}-${itemIndex}`"
|
||||||
>
|
>
|
||||||
Request Type
|
Request Type
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
:id="`test-mock-item-request-type-${group.key}-${testEntry.index}-${mockSetIndex}-${bindingIndex}-${itemIndex}`"
|
:id="`test-mock-item-request-type-${group.key}-${testEntry.index}-${mockSetIndex}-${activeTestMockBindingName(mockSet)}-${itemIndex}`"
|
||||||
v-model="item.requestType"
|
v-model="item.requestType"
|
||||||
class="native-input"
|
class="native-input"
|
||||||
type="text"
|
type="text"
|
||||||
@@ -1579,12 +1581,12 @@
|
|||||||
<div>
|
<div>
|
||||||
<label
|
<label
|
||||||
class="field-label"
|
class="field-label"
|
||||||
:for="`test-mock-item-request-body-${group.key}-${testEntry.index}-${mockSetIndex}-${bindingIndex}-${itemIndex}`"
|
:for="`test-mock-item-request-body-${group.key}-${testEntry.index}-${mockSetIndex}-${activeTestMockBindingName(mockSet)}-${itemIndex}`"
|
||||||
>
|
>
|
||||||
Request Body
|
Request Body
|
||||||
</label>
|
</label>
|
||||||
<textarea
|
<textarea
|
||||||
:id="`test-mock-item-request-body-${group.key}-${testEntry.index}-${mockSetIndex}-${bindingIndex}-${itemIndex}`"
|
:id="`test-mock-item-request-body-${group.key}-${testEntry.index}-${mockSetIndex}-${activeTestMockBindingName(mockSet)}-${itemIndex}`"
|
||||||
v-model="item.requestBodyText"
|
v-model="item.requestBodyText"
|
||||||
class="native-textarea test-mock-item-json"
|
class="native-textarea test-mock-item-json"
|
||||||
spellcheck="false"
|
spellcheck="false"
|
||||||
@@ -1598,12 +1600,12 @@
|
|||||||
<div>
|
<div>
|
||||||
<label
|
<label
|
||||||
class="field-label"
|
class="field-label"
|
||||||
:for="`test-mock-item-response-type-${group.key}-${testEntry.index}-${mockSetIndex}-${bindingIndex}-${itemIndex}`"
|
:for="`test-mock-item-response-type-${group.key}-${testEntry.index}-${mockSetIndex}-${activeTestMockBindingName(mockSet)}-${itemIndex}`"
|
||||||
>
|
>
|
||||||
Response Type
|
Response Type
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
:id="`test-mock-item-response-type-${group.key}-${testEntry.index}-${mockSetIndex}-${bindingIndex}-${itemIndex}`"
|
:id="`test-mock-item-response-type-${group.key}-${testEntry.index}-${mockSetIndex}-${activeTestMockBindingName(mockSet)}-${itemIndex}`"
|
||||||
v-model="item.responseType"
|
v-model="item.responseType"
|
||||||
class="native-input"
|
class="native-input"
|
||||||
type="text"
|
type="text"
|
||||||
@@ -1616,12 +1618,12 @@
|
|||||||
<div class="test-mock-item-full">
|
<div class="test-mock-item-full">
|
||||||
<label
|
<label
|
||||||
class="field-label"
|
class="field-label"
|
||||||
:for="`test-mock-item-response-${group.key}-${testEntry.index}-${mockSetIndex}-${bindingIndex}-${itemIndex}`"
|
:for="`test-mock-item-response-${group.key}-${testEntry.index}-${mockSetIndex}-${activeTestMockBindingName(mockSet)}-${itemIndex}`"
|
||||||
>
|
>
|
||||||
Response
|
Response
|
||||||
</label>
|
</label>
|
||||||
<textarea
|
<textarea
|
||||||
:id="`test-mock-item-response-${group.key}-${testEntry.index}-${mockSetIndex}-${bindingIndex}-${itemIndex}`"
|
:id="`test-mock-item-response-${group.key}-${testEntry.index}-${mockSetIndex}-${activeTestMockBindingName(mockSet)}-${itemIndex}`"
|
||||||
v-model="item.responseText"
|
v-model="item.responseText"
|
||||||
class="native-textarea test-mock-item-json"
|
class="native-textarea test-mock-item-json"
|
||||||
spellcheck="false"
|
spellcheck="false"
|
||||||
@@ -1648,7 +1650,8 @@
|
|||||||
color="primary"
|
color="primary"
|
||||||
outline
|
outline
|
||||||
label="Add Object"
|
label="Add Object"
|
||||||
@click="addTestMockBindingItem(testEntry, mockSet, binding)"
|
:disable="!activeTestMockBinding(mockSet)"
|
||||||
|
@click="addTestMockBindingItem(testEntry, mockSet, activeTestMockBinding(mockSet))"
|
||||||
></q-btn>
|
></q-btn>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -2688,6 +2691,7 @@
|
|||||||
const functionMockDrafts = {}
|
const functionMockDrafts = {}
|
||||||
const selectedFunctionByDataset = {}
|
const selectedFunctionByDataset = {}
|
||||||
const selectedFundingSourceByDataset = {}
|
const selectedFundingSourceByDataset = {}
|
||||||
|
const selectedTestMockBindingByScope = {}
|
||||||
const selectedTestFundingSourceByDataset = {}
|
const selectedTestFundingSourceByDataset = {}
|
||||||
const settingsDrafts = {}
|
const settingsDrafts = {}
|
||||||
|
|
||||||
@@ -2709,6 +2713,7 @@
|
|||||||
settingsDraftRowId: 0,
|
settingsDraftRowId: 0,
|
||||||
settingsDrafts,
|
settingsDrafts,
|
||||||
selectedDatasetKey: 'rest',
|
selectedDatasetKey: 'rest',
|
||||||
|
selectedTestMockBindingByScope,
|
||||||
selectedTestFundingSourceByDataset,
|
selectedTestFundingSourceByDataset,
|
||||||
selectedTestTypeByScope: {},
|
selectedTestTypeByScope: {},
|
||||||
selectedFunctionByDataset,
|
selectedFunctionByDataset,
|
||||||
@@ -3269,6 +3274,7 @@
|
|||||||
selectedDatasetKey: this.selectedDatasetKey,
|
selectedDatasetKey: this.selectedDatasetKey,
|
||||||
selectedFunctionByDataset: this.selectedFunctionByDataset,
|
selectedFunctionByDataset: this.selectedFunctionByDataset,
|
||||||
selectedFundingSourceByDataset: this.selectedFundingSourceByDataset,
|
selectedFundingSourceByDataset: this.selectedFundingSourceByDataset,
|
||||||
|
selectedTestMockBindingByScope: this.selectedTestMockBindingByScope,
|
||||||
selectedTestFundingSourceByDataset:
|
selectedTestFundingSourceByDataset:
|
||||||
this.selectedTestFundingSourceByDataset,
|
this.selectedTestFundingSourceByDataset,
|
||||||
selectedTestTypeByScope: this.selectedTestTypeByScope
|
selectedTestTypeByScope: this.selectedTestTypeByScope
|
||||||
@@ -3311,6 +3317,12 @@
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isPlainObject(state.selectedTestMockBindingByScope)) {
|
||||||
|
this.selectedTestMockBindingByScope = {
|
||||||
|
...state.selectedTestMockBindingByScope
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (isPlainObject(state.selectedTestFundingSourceByDataset)) {
|
if (isPlainObject(state.selectedTestFundingSourceByDataset)) {
|
||||||
Object.assign(
|
Object.assign(
|
||||||
this.selectedTestFundingSourceByDataset,
|
this.selectedTestFundingSourceByDataset,
|
||||||
@@ -3375,6 +3387,7 @@
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
id: ++this.functionMockDraftRowId,
|
id: ++this.functionMockDraftRowId,
|
||||||
|
originalName: name,
|
||||||
name,
|
name,
|
||||||
uri: mock.uri ?? '',
|
uri: mock.uri ?? '',
|
||||||
method: mock.method ?? '',
|
method: mock.method ?? '',
|
||||||
@@ -3391,6 +3404,282 @@
|
|||||||
error: ''
|
error: ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
nextGeneratedFunctionMockName() {
|
||||||
|
const existingNames = new Set(
|
||||||
|
this.currentFunctionMockRows
|
||||||
|
.map(row => (row.name || '').trim())
|
||||||
|
.filter(Boolean)
|
||||||
|
)
|
||||||
|
|
||||||
|
let index = 1
|
||||||
|
let candidate = `new_mock_${index}`
|
||||||
|
|
||||||
|
while (existingNames.has(candidate)) {
|
||||||
|
index += 1
|
||||||
|
candidate = `new_mock_${index}`
|
||||||
|
}
|
||||||
|
|
||||||
|
return candidate
|
||||||
|
},
|
||||||
|
findSampleFunctionMockValue(datasetKey, functionName, fundingSourceName) {
|
||||||
|
const mocks =
|
||||||
|
this.datasets[datasetKey].data?.functions?.[functionName]?.mocks?.[
|
||||||
|
fundingSourceName
|
||||||
|
] || {}
|
||||||
|
|
||||||
|
return (
|
||||||
|
Object.values(mocks).find(value => isPlainObject(value)) || null
|
||||||
|
)
|
||||||
|
},
|
||||||
|
findSampleTestMockItem(datasetKey, functionName, fundingSourceName) {
|
||||||
|
const tests =
|
||||||
|
this.datasets[datasetKey].data?.functions?.[functionName]?.tests || []
|
||||||
|
|
||||||
|
for (const test of tests) {
|
||||||
|
const fundingSourceMocks = test?.mocks?.[fundingSourceName]
|
||||||
|
if (!fundingSourceMocks) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
const mockSets = Array.isArray(fundingSourceMocks)
|
||||||
|
? fundingSourceMocks
|
||||||
|
: [fundingSourceMocks]
|
||||||
|
|
||||||
|
for (const mockSet of mockSets) {
|
||||||
|
if (!isPlainObject(mockSet)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const [mockName, items] of Object.entries(mockSet)) {
|
||||||
|
if (mockName === 'description') {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
const firstItem = Array.isArray(items) ? items[0] : items
|
||||||
|
if (isPlainObject(firstItem)) {
|
||||||
|
return firstItem
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
},
|
||||||
|
createFunctionMockValueTemplate(datasetKey, functionName, fundingSourceName) {
|
||||||
|
const sample = this.findSampleFunctionMockValue(
|
||||||
|
datasetKey,
|
||||||
|
functionName,
|
||||||
|
fundingSourceName
|
||||||
|
)
|
||||||
|
|
||||||
|
if (isPlainObject(sample)) {
|
||||||
|
const template = {}
|
||||||
|
const sampleMethod =
|
||||||
|
typeof sample.method === 'string' ? sample.method : ''
|
||||||
|
const looksLikeHttpVerb = /^[A-Z]+$/.test(sampleMethod)
|
||||||
|
|
||||||
|
if (Object.prototype.hasOwnProperty.call(sample, 'uri')) {
|
||||||
|
template.uri = ''
|
||||||
|
}
|
||||||
|
if (Object.prototype.hasOwnProperty.call(sample, 'headers')) {
|
||||||
|
template.headers = {}
|
||||||
|
}
|
||||||
|
if (Object.prototype.hasOwnProperty.call(sample, 'query_params')) {
|
||||||
|
template.query_params = {}
|
||||||
|
}
|
||||||
|
if (Object.prototype.hasOwnProperty.call(sample, 'method')) {
|
||||||
|
template.method = looksLikeHttpVerb ? sampleMethod : ''
|
||||||
|
}
|
||||||
|
if (Object.prototype.hasOwnProperty.call(sample, 'request_type')) {
|
||||||
|
template.request_type =
|
||||||
|
typeof sample.request_type === 'string' && sample.request_type.trim()
|
||||||
|
? sample.request_type
|
||||||
|
: 'function'
|
||||||
|
}
|
||||||
|
if (Object.prototype.hasOwnProperty.call(sample, 'response_type')) {
|
||||||
|
template.response_type =
|
||||||
|
typeof sample.response_type === 'string' &&
|
||||||
|
sample.response_type.trim()
|
||||||
|
? sample.response_type
|
||||||
|
: 'data'
|
||||||
|
}
|
||||||
|
if (Object.prototype.hasOwnProperty.call(sample, 'response')) {
|
||||||
|
template.response = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
return template
|
||||||
|
}
|
||||||
|
|
||||||
|
if (datasetKey === 'rest') {
|
||||||
|
return {
|
||||||
|
uri: '',
|
||||||
|
headers: {},
|
||||||
|
method: 'GET'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
method: '',
|
||||||
|
request_type: 'function',
|
||||||
|
response_type: 'data',
|
||||||
|
response: {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
createTestMockItemTemplate(
|
||||||
|
datasetKey,
|
||||||
|
functionName,
|
||||||
|
fundingSourceName,
|
||||||
|
functionMockValue = {}
|
||||||
|
) {
|
||||||
|
const sample = this.findSampleTestMockItem(
|
||||||
|
datasetKey,
|
||||||
|
functionName,
|
||||||
|
fundingSourceName
|
||||||
|
)
|
||||||
|
|
||||||
|
if (isPlainObject(sample)) {
|
||||||
|
const template = {}
|
||||||
|
|
||||||
|
if (Object.prototype.hasOwnProperty.call(sample, 'request_type')) {
|
||||||
|
template.request_type =
|
||||||
|
typeof sample.request_type === 'string' ? sample.request_type : ''
|
||||||
|
}
|
||||||
|
if (Object.prototype.hasOwnProperty.call(sample, 'request_body')) {
|
||||||
|
template.request_body = {}
|
||||||
|
}
|
||||||
|
if (Object.prototype.hasOwnProperty.call(sample, 'response_type')) {
|
||||||
|
template.response_type =
|
||||||
|
typeof sample.response_type === 'string'
|
||||||
|
? sample.response_type
|
||||||
|
: 'json'
|
||||||
|
}
|
||||||
|
template.response = {}
|
||||||
|
|
||||||
|
return template
|
||||||
|
}
|
||||||
|
|
||||||
|
if (datasetKey === 'rest') {
|
||||||
|
return {
|
||||||
|
response_type: 'json',
|
||||||
|
response: {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
isPlainObject(functionMockValue) &&
|
||||||
|
Object.prototype.hasOwnProperty.call(functionMockValue, 'response_type')
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
response: {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
response_type: 'data',
|
||||||
|
response: {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
withFundingSourceMockSets(data, functionName, fundingSourceName, visitor) {
|
||||||
|
const tests = data?.functions?.[functionName]?.tests || []
|
||||||
|
|
||||||
|
tests.forEach((test, testIndex) => {
|
||||||
|
if (
|
||||||
|
!test.mocks ||
|
||||||
|
!Object.prototype.hasOwnProperty.call(test.mocks, fundingSourceName)
|
||||||
|
) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const fundingSourceMocks = test.mocks[fundingSourceName]
|
||||||
|
|
||||||
|
if (Array.isArray(fundingSourceMocks)) {
|
||||||
|
fundingSourceMocks.forEach((mockSet, mockSetIndex) => {
|
||||||
|
if (isPlainObject(mockSet)) {
|
||||||
|
visitor(mockSet, test, testIndex, mockSetIndex)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isPlainObject(fundingSourceMocks)) {
|
||||||
|
visitor(fundingSourceMocks, test, testIndex, 0)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
addFunctionMockToTestSets(
|
||||||
|
data,
|
||||||
|
functionName,
|
||||||
|
fundingSourceName,
|
||||||
|
mockName,
|
||||||
|
functionMockValue
|
||||||
|
) {
|
||||||
|
const defaultItem = this.createTestMockItemTemplate(
|
||||||
|
this.selectedDatasetKey,
|
||||||
|
functionName,
|
||||||
|
fundingSourceName,
|
||||||
|
functionMockValue
|
||||||
|
)
|
||||||
|
|
||||||
|
this.withFundingSourceMockSets(
|
||||||
|
data,
|
||||||
|
functionName,
|
||||||
|
fundingSourceName,
|
||||||
|
mockSet => {
|
||||||
|
if (!Object.prototype.hasOwnProperty.call(mockSet, mockName)) {
|
||||||
|
mockSet[mockName] = [deepClone(defaultItem)]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
renameFunctionMockInTestSets(
|
||||||
|
data,
|
||||||
|
functionName,
|
||||||
|
fundingSourceName,
|
||||||
|
previousName,
|
||||||
|
nextName
|
||||||
|
) {
|
||||||
|
if (!previousName || !nextName || previousName === nextName) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.withFundingSourceMockSets(
|
||||||
|
data,
|
||||||
|
functionName,
|
||||||
|
fundingSourceName,
|
||||||
|
mockSet => {
|
||||||
|
if (!Object.prototype.hasOwnProperty.call(mockSet, previousName)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Object.prototype.hasOwnProperty.call(mockSet, nextName)) {
|
||||||
|
mockSet[nextName] = mockSet[previousName]
|
||||||
|
}
|
||||||
|
|
||||||
|
delete mockSet[previousName]
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
removeFunctionMockFromTestSets(
|
||||||
|
data,
|
||||||
|
functionName,
|
||||||
|
fundingSourceName,
|
||||||
|
mockName
|
||||||
|
) {
|
||||||
|
if (!mockName) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this.withFundingSourceMockSets(
|
||||||
|
data,
|
||||||
|
functionName,
|
||||||
|
fundingSourceName,
|
||||||
|
mockSet => {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(mockSet, mockName)) {
|
||||||
|
delete mockSet[mockName]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
createTestMockBindingDraft(mockName = '', items = []) {
|
createTestMockBindingDraft(mockName = '', items = []) {
|
||||||
const normalizedItems = Array.isArray(items)
|
const normalizedItems = Array.isArray(items)
|
||||||
? items
|
? items
|
||||||
@@ -3403,13 +3692,31 @@
|
|||||||
items: normalizedItems.map(item => createTestMockItemDraftState(item))
|
items: normalizedItems.map(item => createTestMockItemDraftState(item))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
testMockBindingOptions(selectedMockName = '') {
|
testMockBindingScopeKey(mockSet) {
|
||||||
const names = this.currentFunctionMockNameOptions.map(
|
if (!mockSet?.path) {
|
||||||
option => option.value
|
return ''
|
||||||
)
|
}
|
||||||
|
|
||||||
if (selectedMockName && !names.includes(selectedMockName)) {
|
return [
|
||||||
names.unshift(selectedMockName)
|
this.selectedDatasetKey,
|
||||||
|
this.currentFunctionName,
|
||||||
|
this.currentTestFundingSourceName,
|
||||||
|
mockSet.path
|
||||||
|
].join(':')
|
||||||
|
},
|
||||||
|
testMockBindingOptions(mockSet) {
|
||||||
|
const names = this.currentFunctionMockNameOptions.map(option => option.value)
|
||||||
|
const activeName = this.activeTestMockBindingName(mockSet)
|
||||||
|
|
||||||
|
;(mockSet?.bindings || []).forEach(binding => {
|
||||||
|
const name = (binding.selectedMockName || '').trim()
|
||||||
|
if (name && !names.includes(name)) {
|
||||||
|
names.push(name)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (activeName && !names.includes(activeName)) {
|
||||||
|
names.unshift(activeName)
|
||||||
}
|
}
|
||||||
|
|
||||||
return names.map(name => ({
|
return names.map(name => ({
|
||||||
@@ -3417,6 +3724,29 @@
|
|||||||
value: name
|
value: name
|
||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
|
activeTestMockBindingName(mockSet) {
|
||||||
|
const scopeKey = this.testMockBindingScopeKey(mockSet)
|
||||||
|
const selectedName = scopeKey
|
||||||
|
? this.selectedTestMockBindingByScope[scopeKey]
|
||||||
|
: ''
|
||||||
|
const bindingNames = (mockSet?.bindings || [])
|
||||||
|
.map(binding => (binding.selectedMockName || '').trim())
|
||||||
|
.filter(Boolean)
|
||||||
|
|
||||||
|
if (selectedName && bindingNames.includes(selectedName)) {
|
||||||
|
return selectedName
|
||||||
|
}
|
||||||
|
|
||||||
|
return bindingNames[0] || ''
|
||||||
|
},
|
||||||
|
activeTestMockBinding(mockSet) {
|
||||||
|
const activeName = this.activeTestMockBindingName(mockSet)
|
||||||
|
return (
|
||||||
|
(mockSet?.bindings || []).find(
|
||||||
|
binding => (binding.selectedMockName || '').trim() === activeName
|
||||||
|
) || null
|
||||||
|
)
|
||||||
|
},
|
||||||
nextAvailableTestMockName(mockSet) {
|
nextAvailableTestMockName(mockSet) {
|
||||||
const usedNames = new Set(
|
const usedNames = new Set(
|
||||||
(mockSet.bindings || [])
|
(mockSet.bindings || [])
|
||||||
@@ -3430,6 +3760,21 @@
|
|||||||
|
|
||||||
return availableName?.value || ''
|
return availableName?.value || ''
|
||||||
},
|
},
|
||||||
|
createDefaultTestMockBindingItems(mockName) {
|
||||||
|
const functionMockValue =
|
||||||
|
this.datasets[this.selectedDatasetKey].data?.functions?.[
|
||||||
|
this.currentFunctionName
|
||||||
|
]?.mocks?.[this.currentTestFundingSourceName]?.[mockName] || {}
|
||||||
|
|
||||||
|
return [
|
||||||
|
this.createTestMockItemTemplate(
|
||||||
|
this.selectedDatasetKey,
|
||||||
|
this.currentFunctionName,
|
||||||
|
this.currentTestFundingSourceName,
|
||||||
|
functionMockValue
|
||||||
|
)
|
||||||
|
]
|
||||||
|
},
|
||||||
testMockItemTitle(item, itemIndex) {
|
testMockItemTitle(item, itemIndex) {
|
||||||
const description = item?.descriptionText || ''
|
const description = item?.descriptionText || ''
|
||||||
|
|
||||||
@@ -3451,29 +3796,53 @@
|
|||||||
item.skip = Boolean(value)
|
item.skip = Boolean(value)
|
||||||
this.persistTestMockSet(testEntry, mockSet)
|
this.persistTestMockSet(testEntry, mockSet)
|
||||||
},
|
},
|
||||||
handleTestMockBindingSelection(testEntry, mockSet, binding, value) {
|
handleTestMockBindingSelection(testEntry, mockSet, value) {
|
||||||
const nextName = typeof value === 'string' ? value : ''
|
const nextName = typeof value === 'string' ? value : ''
|
||||||
const previousName = (binding.selectedMockName || '').trim()
|
const scopeKey = this.testMockBindingScopeKey(mockSet)
|
||||||
|
if (!nextName || !scopeKey) {
|
||||||
binding.selectedMockName = nextName
|
return
|
||||||
|
|
||||||
if (!nextName) {
|
|
||||||
binding.items = []
|
|
||||||
} else if (nextName !== previousName || !Array.isArray(binding.items)) {
|
|
||||||
binding.items = [createTestMockItemDraftState({})]
|
|
||||||
} else if (!binding.items.length) {
|
|
||||||
binding.items.push(createTestMockItemDraftState({}))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.persistTestMockSet(testEntry, mockSet)
|
let binding = (mockSet.bindings || []).find(
|
||||||
|
candidate => (candidate.selectedMockName || '').trim() === nextName
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!binding) {
|
||||||
|
binding = this.createTestMockBindingDraft(
|
||||||
|
nextName,
|
||||||
|
this.createDefaultTestMockBindingItems(nextName)
|
||||||
|
)
|
||||||
|
mockSet.bindings.push(binding)
|
||||||
|
this.selectedTestMockBindingByScope[scopeKey] = nextName
|
||||||
|
this.persistUiState()
|
||||||
|
this.persistTestMockSet(testEntry, mockSet)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Array.isArray(binding.items)) {
|
||||||
|
binding.items = []
|
||||||
|
}
|
||||||
|
|
||||||
|
this.selectedTestMockBindingByScope[scopeKey] = nextName
|
||||||
|
this.persistUiState()
|
||||||
},
|
},
|
||||||
addTestMockBinding(testEntry, mockSet) {
|
addTestMockBinding(testEntry, mockSet) {
|
||||||
|
const nextName = this.nextAvailableTestMockName(mockSet)
|
||||||
|
if (!nextName) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
mockSet.bindings.push(
|
mockSet.bindings.push(
|
||||||
this.createTestMockBindingDraft(
|
this.createTestMockBindingDraft(
|
||||||
this.nextAvailableTestMockName(mockSet),
|
nextName,
|
||||||
[{}]
|
this.createDefaultTestMockBindingItems(nextName)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
const scopeKey = this.testMockBindingScopeKey(mockSet)
|
||||||
|
if (scopeKey) {
|
||||||
|
this.selectedTestMockBindingByScope[scopeKey] = nextName
|
||||||
|
this.persistUiState()
|
||||||
|
}
|
||||||
this.persistTestMockSet(testEntry, mockSet)
|
this.persistTestMockSet(testEntry, mockSet)
|
||||||
},
|
},
|
||||||
addTestMockBindingItem(testEntry, mockSet, binding) {
|
addTestMockBindingItem(testEntry, mockSet, binding) {
|
||||||
@@ -3998,17 +4367,89 @@
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const newMockName = this.nextGeneratedFunctionMockName()
|
||||||
|
const nextMockValue = this.createFunctionMockValueTemplate(
|
||||||
|
this.selectedDatasetKey,
|
||||||
|
this.currentFunctionName,
|
||||||
|
this.currentTestFundingSourceName
|
||||||
|
)
|
||||||
const rows = this.ensureFunctionMockDraft(
|
const rows = this.ensureFunctionMockDraft(
|
||||||
this.selectedDatasetKey,
|
this.selectedDatasetKey,
|
||||||
this.currentFunctionName,
|
this.currentFunctionName,
|
||||||
this.currentTestFundingSourceName
|
this.currentTestFundingSourceName
|
||||||
)
|
)
|
||||||
rows.push(this.createFunctionMockDraftRow('', {}))
|
rows.push(this.createFunctionMockDraftRow(newMockName, nextMockValue))
|
||||||
|
|
||||||
|
this.applyDatasetMutation(
|
||||||
|
this.selectedDatasetKey,
|
||||||
|
data => {
|
||||||
|
if (!data.functions[this.currentFunctionName].mocks) {
|
||||||
|
data.functions[this.currentFunctionName].mocks = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
!data.functions[this.currentFunctionName].mocks[
|
||||||
|
this.currentTestFundingSourceName
|
||||||
|
]
|
||||||
|
) {
|
||||||
|
data.functions[this.currentFunctionName].mocks[
|
||||||
|
this.currentTestFundingSourceName
|
||||||
|
] = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
data.functions[this.currentFunctionName].mocks[
|
||||||
|
this.currentTestFundingSourceName
|
||||||
|
][newMockName] = deepClone(nextMockValue)
|
||||||
|
|
||||||
|
this.addFunctionMockToTestSets(
|
||||||
|
data,
|
||||||
|
this.currentFunctionName,
|
||||||
|
this.currentTestFundingSourceName,
|
||||||
|
newMockName,
|
||||||
|
nextMockValue
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
preserveFunctionMockDrafts: true,
|
||||||
|
preserveSettingsDrafts: true
|
||||||
|
}
|
||||||
|
)
|
||||||
},
|
},
|
||||||
removeFunctionMockRow(rowIndex) {
|
removeFunctionMockRow(rowIndex) {
|
||||||
const rows = this.currentFunctionMockRows
|
const rows = this.currentFunctionMockRows
|
||||||
rows.splice(rowIndex, 1)
|
const [removedRow] = rows.splice(rowIndex, 1)
|
||||||
this.persistFunctionMocks()
|
|
||||||
|
this.applyDatasetMutation(
|
||||||
|
this.selectedDatasetKey,
|
||||||
|
data => {
|
||||||
|
const functionMocks =
|
||||||
|
data.functions?.[this.currentFunctionName]?.mocks?.[
|
||||||
|
this.currentTestFundingSourceName
|
||||||
|
]
|
||||||
|
|
||||||
|
if (
|
||||||
|
functionMocks &&
|
||||||
|
removedRow?.originalName &&
|
||||||
|
Object.prototype.hasOwnProperty.call(
|
||||||
|
functionMocks,
|
||||||
|
removedRow.originalName
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
delete functionMocks[removedRow.originalName]
|
||||||
|
}
|
||||||
|
|
||||||
|
this.removeFunctionMockFromTestSets(
|
||||||
|
data,
|
||||||
|
this.currentFunctionName,
|
||||||
|
this.currentTestFundingSourceName,
|
||||||
|
removedRow?.originalName || removedRow?.name || ''
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
preserveFunctionMockDrafts: true,
|
||||||
|
preserveSettingsDrafts: true
|
||||||
|
}
|
||||||
|
)
|
||||||
},
|
},
|
||||||
persistFunctionMocks(options = {}) {
|
persistFunctionMocks(options = {}) {
|
||||||
if (!this.currentFunctionName || !this.currentTestFundingSourceName) {
|
if (!this.currentFunctionName || !this.currentTestFundingSourceName) {
|
||||||
@@ -4017,6 +4458,7 @@
|
|||||||
|
|
||||||
const rows = this.currentFunctionMockRows
|
const rows = this.currentFunctionMockRows
|
||||||
const nextMocks = {}
|
const nextMocks = {}
|
||||||
|
const renamePairs = []
|
||||||
|
|
||||||
for (const row of rows) {
|
for (const row of rows) {
|
||||||
row.error = ''
|
row.error = ''
|
||||||
@@ -4024,9 +4466,34 @@
|
|||||||
|
|
||||||
for (const row of rows) {
|
for (const row of rows) {
|
||||||
const name = row.name.trim()
|
const name = row.name.trim()
|
||||||
|
const originalName = (row.originalName || '').trim()
|
||||||
|
|
||||||
|
if (!name && !originalName) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if (!name) {
|
if (!name) {
|
||||||
continue
|
row.error = 'Mock name cannot be empty.'
|
||||||
|
if (!options.silent) {
|
||||||
|
this.notify(
|
||||||
|
`Could not save mock "${originalName || 'new mock'}".`,
|
||||||
|
'negative',
|
||||||
|
row.error
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Object.prototype.hasOwnProperty.call(nextMocks, name)) {
|
||||||
|
row.error = `Duplicate mock name: ${name}`
|
||||||
|
if (!options.silent) {
|
||||||
|
this.notify(
|
||||||
|
`Could not save mock "${name}".`,
|
||||||
|
'negative',
|
||||||
|
row.error
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -4043,22 +4510,79 @@
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (originalName && originalName !== name) {
|
||||||
|
renamePairs.push({
|
||||||
|
from: originalName,
|
||||||
|
to: name
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.applyDatasetMutation(
|
this.applyDatasetMutation(
|
||||||
this.selectedDatasetKey,
|
this.selectedDatasetKey,
|
||||||
data => {
|
data => {
|
||||||
|
const currentMocks =
|
||||||
|
data.functions?.[this.currentFunctionName]?.mocks?.[
|
||||||
|
this.currentTestFundingSourceName
|
||||||
|
] || {}
|
||||||
|
const currentNames = Object.keys(currentMocks)
|
||||||
|
const nextNames = Object.keys(nextMocks)
|
||||||
|
const renameFrom = new Set(renamePairs.map(item => item.from))
|
||||||
|
const renameTo = new Set(renamePairs.map(item => item.to))
|
||||||
|
const removedNames = currentNames.filter(
|
||||||
|
name => !nextNames.includes(name) && !renameFrom.has(name)
|
||||||
|
)
|
||||||
|
const addedNames = nextNames.filter(
|
||||||
|
name => !currentNames.includes(name) && !renameTo.has(name)
|
||||||
|
)
|
||||||
|
|
||||||
if (!data.functions[this.currentFunctionName].mocks) {
|
if (!data.functions[this.currentFunctionName].mocks) {
|
||||||
data.functions[this.currentFunctionName].mocks = {}
|
data.functions[this.currentFunctionName].mocks = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renamePairs.forEach(pair => {
|
||||||
|
this.renameFunctionMockInTestSets(
|
||||||
|
data,
|
||||||
|
this.currentFunctionName,
|
||||||
|
this.currentTestFundingSourceName,
|
||||||
|
pair.from,
|
||||||
|
pair.to
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
removedNames.forEach(name => {
|
||||||
|
this.removeFunctionMockFromTestSets(
|
||||||
|
data,
|
||||||
|
this.currentFunctionName,
|
||||||
|
this.currentTestFundingSourceName,
|
||||||
|
name
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
addedNames.forEach(name => {
|
||||||
|
this.addFunctionMockToTestSets(
|
||||||
|
data,
|
||||||
|
this.currentFunctionName,
|
||||||
|
this.currentTestFundingSourceName,
|
||||||
|
name,
|
||||||
|
nextMocks[name]
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
data.functions[this.currentFunctionName].mocks[
|
data.functions[this.currentFunctionName].mocks[
|
||||||
this.currentTestFundingSourceName
|
this.currentTestFundingSourceName
|
||||||
] = nextMocks
|
] = nextMocks
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
preserveFunctionMockDrafts: true
|
preserveFunctionMockDrafts: true,
|
||||||
|
preserveSettingsDrafts: true
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
rows.forEach(row => {
|
||||||
|
row.originalName = row.name.trim()
|
||||||
|
})
|
||||||
},
|
},
|
||||||
baseWalletPath(functionName, fundingSourceName) {
|
baseWalletPath(functionName, fundingSourceName) {
|
||||||
return `functions.${functionName}.mocks.${fundingSourceName}`
|
return `functions.${functionName}.mocks.${fundingSourceName}`
|
||||||
|
|||||||
Reference in New Issue
Block a user