feat: auto locate to the last testcase (#197)

This commit is contained in:
Rick 2023-09-01 11:34:27 +08:00 committed by GitHub
parent 9efccb1430
commit 2bbb634688
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 121 additions and 52 deletions

View File

@ -45,6 +45,7 @@ Mirror Images: docker.m.daocloud.io/linuxsuren/api-testing`,
flags.StringVarP(&opt.version, "version", "", version.GetVersion(), "The version of the service image") flags.StringVarP(&opt.version, "version", "", version.GetVersion(), "The version of the service image")
flags.StringVarP(&opt.localStorage, "local-storage", "", "/var/data/atest", flags.StringVarP(&opt.localStorage, "local-storage", "", "/var/data/atest",
"The local storage path which will be mounted into the container") "The local storage path which will be mounted into the container")
flags.StringVarP(&opt.secretServer, "secret-server", "", "", "The secret server URL")
return return
} }
@ -58,6 +59,7 @@ type serviceOption struct {
mode string mode string
localStorage string localStorage string
pull string pull string
secretServer string
stdOut io.Writer stdOut io.Writer
} }
@ -213,7 +215,7 @@ func (o *serviceOption) getContainerService() (service Service, err error) {
clientPath = client clientPath = client
} }
service = newContainerService(o.Execer, clientPath, service = newContainerService(o.Execer, clientPath,
o.image, o.version, o.pull, o.localStorage, o.stdOut) o.image, o.version, o.pull, o.localStorage, o.secretServer, o.stdOut)
} }
return return
} }
@ -319,13 +321,14 @@ type containerService struct {
tag string tag string
pull string pull string
localStorage string localStorage string
secretServer string
stdOut io.Writer stdOut io.Writer
errOut io.Writer errOut io.Writer
} }
const defaultImage = "ghcr.io/linuxsuren/api-testing" const defaultImage = "ghcr.io/linuxsuren/api-testing"
func newContainerService(execer fakeruntime.Execer, client, image, tag, pull, localStorage string, writer io.Writer) (svc Service) { func newContainerService(execer fakeruntime.Execer, client, image, tag, pull, localStorage string, secretServer string, writer io.Writer) (svc Service) {
if tag == "" { if tag == "" {
tag = "latest" tag = "latest"
} }
@ -341,6 +344,7 @@ func newContainerService(execer fakeruntime.Execer, client, image, tag, pull, lo
tag: tag, tag: tag,
pull: pull, pull: pull,
localStorage: localStorage, localStorage: localStorage,
secretServer: secretServer,
stdOut: writer, stdOut: writer,
errOut: writer, errOut: writer,
} }
@ -398,14 +402,20 @@ func (s *containerService) exist() bool {
} }
func (s *containerService) getStartArgs() []string { func (s *containerService) getStartArgs() []string {
return []string{"run", "--name=" + s.name, args := []string{"run", "--name=" + s.name,
"--restart=always", "--restart=always",
"-d", "-d",
fmt.Sprintf("--pull=%s", s.pull), fmt.Sprintf("--pull=%s", s.pull),
"--network=host", "--network=host",
"-v", s.localStorage + ":/var/www/data", "-v", s.localStorage + ":/var/www/data",
"-v", "/root/.config/atest:/root/.config/atest", "-v", "/root/.config/atest:/root/.config/atest",
s.image + ":" + s.tag} s.image + ":" + s.tag,
"atest", "server"}
if s.secretServer != "" {
args = append(args, "--secret-server="+s.secretServer)
}
args = append(args, "--console-path=/var/www/html")
return args
} }
type podmanService struct { type podmanService struct {

View File

@ -10,6 +10,7 @@ import { ElTree } from 'element-plus'
import type { FormInstance, FormRules } from 'element-plus' import type { FormInstance, FormRules } from 'element-plus'
import { Edit, Share } from '@element-plus/icons-vue' import { Edit, Share } from '@element-plus/icons-vue'
import type { Suite } from './types' import type { Suite } from './types'
import { GetLastTestCaseLocation, SetLastTestCaseLocation } from './views/cache'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
const { t } = useI18n() const { t } = useI18n()
@ -18,6 +19,7 @@ interface Tree {
id: string id: string
label: string label: string
parent: string parent: string
parentID: string
store: string store: string
children?: Tree[] children?: Tree[]
} }
@ -50,12 +52,14 @@ const handleNodeClick = (data: Tree) => {
id: data.label + item.name, id: data.label + item.name,
label: item.name, label: item.name,
store: data.store, store: data.store,
parent: data.label parent: data.label,
parentID: data.id
} as Tree) } as Tree)
}) })
} }
}) })
} else { } else {
SetLastTestCaseLocation(data.parentID, data.id)
testCaseName.value = data.label testCaseName.value = data.label
testSuite.value = data.parent testSuite.value = data.parent
store.value = data.store store.value = data.store
@ -74,7 +78,8 @@ function loadTestSuites(storeName: string) {
'X-Store-Name': storeName 'X-Store-Name': storeName
}, },
} }
fetch('/server.Runner/GetSuites', requestOptions) return async () => {
await fetch('/server.Runner/GetSuites', requestOptions)
.then((response) => response.json()) .then((response) => response.json())
.then((d) => { .then((d) => {
if (!d.data) { if (!d.data) {
@ -93,27 +98,14 @@ function loadTestSuites(storeName: string) {
id: k + item, id: k + item,
label: item, label: item,
store: storeName, store: storeName,
parent: k parent: k,
parentID: suite.id
} as Tree) } as Tree)
}) })
data.value.push(suite) data.value.push(suite)
}) })
if (data.value.length > 0) {
const firstItem = data.value[0]
if (firstItem.children && firstItem.children.length > 0) {
const child = firstItem.children[0].id
currentNodekey.value = child
treeRef.value!.setCurrentKey(child)
treeRef.value!.setCheckedKeys([child], false)
}
viewName.value = 'testsuite'
testSuite.value = firstItem.label
store.value = firstItem.store
}
}) })
}
} }
interface Store { interface Store {
@ -128,17 +120,52 @@ function loadStores() {
} }
fetch('/server.Runner/GetStores', requestOptions) fetch('/server.Runner/GetStores', requestOptions)
.then((response) => response.json()) .then((response) => response.json())
.then((d) => { .then(async (d) => {
stores.value = d.data stores.value = d.data
data.value = [] as Tree[] data.value = [] as Tree[]
d.data.forEach((item: any) => { for (const item of d.data) {
if (item.ready) { if (item.ready) {
loadTestSuites(item.name) await loadTestSuites(item.name)()
}
} }
})
if (data.value.length === 0) { if (data.value.length > 0) {
const key = GetLastTestCaseLocation()
let targetSuite = {} as Tree
let targetChild = {} as Tree
if (key.suite !== '' && key.testcase !== '') {
for (var i = 0; i < data.value.length; i++) {
const item = data.value[i]
if (item.id === key.suite && item.children) {
for (var j = 0; j < item.children.length; j++) {
const child = item.children[j]
if (child.id === key.testcase) {
targetSuite = item
targetChild = child
break
}
}
break
}
}
}
if (!targetChild.id || targetChild.id === '') {
targetSuite = data.value[0]
if (targetSuite.children && targetSuite.children.length > 0) {
targetChild = targetSuite.children[0]
}
}
viewName.value = 'testsuite'
currentNodekey.value = targetChild.id
treeRef.value!.setCurrentKey(targetChild.id)
treeRef.value!.setCheckedKeys([targetChild.id], false)
testSuite.value = targetSuite.label
store.value = targetSuite.store
} else {
viewName.value = "" viewName.value = ""
} }
}) })
@ -278,6 +305,8 @@ const viewName = ref('')
@node-click="handleNodeClick" @node-click="handleNodeClick"
data-intro="This is the test suite tree. You can click the test suite to edit it." data-intro="This is the test suite tree. You can click the test suite to edit it."
/> />
<TemplateFunctions/>
</el-aside> </el-aside>
<el-main> <el-main>
@ -391,8 +420,6 @@ const viewName = ref('')
</span> </span>
</template> </template>
</el-dialog> </el-dialog>
<TemplateFunctions/>
</template> </template>
<style scoped> <style scoped>

View File

@ -25,7 +25,13 @@ function loadStores() {
method: 'POST', method: 'POST',
} }
fetch('/server.Runner/GetSecrets', requestOptions) fetch('/server.Runner/GetSecrets', requestOptions)
.then((response) => response.json()) .then((response) => {
if (!response.ok) {
throw new Error(response.statusText)
} else {
response.json()
}
})
.then((e) => { .then((e) => {
secrets.value = e.data secrets.value = e.data
}) })
@ -125,6 +131,10 @@ const submitForm = async (formEl: FormInstance | undefined) => {
</el-table-column> </el-table-column>
</el-table> </el-table>
<div style="margin-top: 20px; margin-bottom: 20px; position: absolute; bottom: 0px;">
Follow <el-link href="https://linuxsuren.github.io/api-testing/#secret-server" target="_blank">the instructions</el-link> to configure the secret server.
</div>
<el-dialog v-model="dialogVisible" :title="t('title.createSecret')" width="30%" draggable> <el-dialog v-model="dialogVisible" :title="t('title.createSecret')" width="30%" draggable>
<template #footer> <template #footer>
<span class="dialog-footer"> <span class="dialog-footer">

View File

@ -185,6 +185,10 @@ function updateKeys() {
</el-table-column> </el-table-column>
</el-table> </el-table>
<div style="margin-top: 20px; margin-bottom: 20px; position: absolute; bottom: 0px;">
Follow <el-link href="https://linuxsuren.github.io/api-testing/#storage" target="_blank">the instructions</el-link> to configure the storage plugins.
</div>
<el-dialog v-model="dialogVisible" :title="t('title.createStore')" width="30%" draggable> <el-dialog v-model="dialogVisible" :title="t('title.createStore')" width="30%" draggable>
<template #footer> <template #footer>
<span class="dialog-footer"> <span class="dialog-footer">

View File

@ -15,3 +15,21 @@ export function GetTestCaseResponseCache(id: string) {
export function SetTestCaseResponseCache(id: string, resp: TestCaseResponse) { export function SetTestCaseResponseCache(id: string, resp: TestCaseResponse) {
sessionStorage.setItem(id, JSON.stringify(resp)) sessionStorage.setItem(id, JSON.stringify(resp))
} }
const lastTestCaseLocationKey = "api-testing-case-location"
export function GetLastTestCaseLocation() {
const val = sessionStorage.getItem(lastTestCaseLocationKey)
if (val && val !== '') {
return JSON.parse(val)
} else {
return {}
}
}
export function SetLastTestCaseLocation(suite: string, testcase: string) {
sessionStorage.setItem(lastTestCaseLocationKey, JSON.stringify({
suite: suite,
testcase: testcase
}))
return
}