Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,13 @@ root = true
[*]
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
charset = utf-8

# 4 space indentation
[*.{py,proto,go,js,ts,json,vue}]
[*.{py,proto,js,ts,json,vue}]
indent_style = space
indent_size = 4

[*.go]
indent_style = tab
9 changes: 9 additions & 0 deletions cmd/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ type mockOption struct {
port int
prefix string
metrics bool
tls bool
tlsCert string
tlsKey string
}

func createMockCmd() (c *cobra.Command) {
Expand All @@ -47,12 +50,18 @@ func createMockCmd() (c *cobra.Command) {
flags.IntVarP(&opt.port, "port", "", 6060, "The mock server port")
flags.StringVarP(&opt.prefix, "prefix", "", "/mock", "The mock server API prefix")
flags.BoolVarP(&opt.metrics, "metrics", "m", true, "Enable request metrics collection")
flags.BoolVarP(&opt.tls, "tls", "", false, "Enable TLS mode. Set to true to enable TLS. Alow SAN certificates")
flags.StringVarP(&opt.tlsCert, "cert-file", "", "", "The path to the certificate file, Alow SAN certificates")
flags.StringVarP(&opt.tlsKey, "key-file", "", "", "The path to the key file, Alow SAN certificates")
return
}

func (o *mockOption) runE(c *cobra.Command, args []string) (err error) {
reader := mock.NewLocalFileReader(args[0])
server := mock.NewInMemoryServer(c.Context(), o.port)
if o.tls {
server.WithTLS(o.tlsCert, o.tlsKey)
}
if o.metrics {
server.EnableMetrics()
}
Expand Down
9 changes: 7 additions & 2 deletions cmd/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,7 @@ func (o *serverOption) runE(cmd *cobra.Command, args []string) (err error) {
server.RegisterMockServer(s, mockServerController)
server.RegisterDataServerServer(s, remoteServer.(server.DataServerServer))
server.RegisterThemeExtensionServer(s, remoteServer.(server.ThemeExtensionServer))
server.RegisterUIExtensionServer(s, remoteServer.(server.UIExtensionServer))
serverLogger.Info("gRPC server listening at", "addr", lis.Addr())
s.Serve(lis)
}()
Expand Down Expand Up @@ -345,15 +346,19 @@ func (o *serverOption) runE(cmd *cobra.Command, args []string) (err error) {
server.RegisterRunnerHandlerFromEndpoint(ctx, mux, gRPCServerAddr, opts),
server.RegisterMockHandlerFromEndpoint(ctx, mux, gRPCServerAddr, opts),
server.RegisterThemeExtensionHandlerFromEndpoint(ctx, mux, gRPCServerAddr, opts),
server.RegisterDataServerHandlerFromEndpoint(ctx, mux, gRPCServerAddr, opts))
server.RegisterDataServerHandlerFromEndpoint(ctx, mux, gRPCServerAddr, opts),
server.RegisterUIExtensionHandlerFromEndpoint(ctx, mux, gRPCServerAddr, opts),
)
} else {
dialOption := []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(math.MaxInt))}
err = errors.Join(
server.RegisterRunnerHandlerFromEndpoint(ctx, mux, gRPCServerAddr, dialOption),
server.RegisterMockHandlerFromEndpoint(ctx, mux, gRPCServerAddr, dialOption),
server.RegisterThemeExtensionHandlerFromEndpoint(ctx, mux, gRPCServerAddr, dialOption),
server.RegisterDataServerHandlerFromEndpoint(ctx, mux, gRPCServerAddr, dialOption))
server.RegisterDataServerHandlerFromEndpoint(ctx, mux, gRPCServerAddr, dialOption),
server.RegisterUIExtensionHandlerFromEndpoint(ctx, mux, gRPCServerAddr, dialOption),
)
}

if err == nil {
Expand Down
33 changes: 25 additions & 8 deletions console/atest-ui/src/App.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<script setup lang="ts">
import {
Document,
Menu as IconMenu,
Histogram,
Location,
Expand All @@ -16,10 +15,10 @@ import TestingPanel from './views/TestingPanel.vue'
import TestingHistoryPanel from './views/TestingHistoryPanel.vue'
import MockManager from './views/MockManager.vue'
import StoreManager from './views/StoreManager.vue'
import SecretManager from './views/SecretManager.vue'
import WelcomePage from './views/WelcomePage.vue'
import DataManager from './views/DataManager.vue'
import MagicKey from './components/MagicKey.vue'
import Extension from './views/Extension.vue'
import { useI18n } from 'vue-i18n'
import ElementPlus from 'element-plus';
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
Expand Down Expand Up @@ -109,6 +108,19 @@ const theme = ref(getTheme())
watch(theme, (e) => {
setTheme(e)
})

interface Menu {
name: string
icon: string
index: string
}

const extensionMenus = ref([] as Menu[]);
API.GetMenus((menus) => {
if (menus.data && menus.data.length > 0) {
extensionMenus.value = menus.data;
}
});
</script>

<template>
Expand Down Expand Up @@ -144,14 +156,16 @@ watch(theme, (e) => {
<el-icon><DataAnalysis /></el-icon>
<template #title>{{ t('title.data' )}}</template>
</el-menu-item>
<el-menu-item index="secret">
<el-icon><document /></el-icon>
<template #title>{{ t('title.secrets') }}</template>
</el-menu-item>
<el-menu-item index="store">
<el-icon><location /></el-icon>
<template #title>{{ t('title.stores') }}</template>
</el-menu-item>
<span v-for="menu in extensionMenus" :key="menu.index" :index="menu.index">
<el-menu-item :index="menu.index">
<el-icon><IconMenu /></el-icon>
<template #title>{{ menu.name }}</template>
</el-menu-item>
</span>
</el-menu>
</el-aside>

Expand All @@ -166,8 +180,11 @@ watch(theme, (e) => {
<DataManager v-else-if="panelName === 'data'" />
<MockManager v-else-if="panelName === 'mock'" />
<StoreManager v-else-if="panelName === 'store'" />
<SecretManager v-else-if="panelName === 'secret'" />
<WelcomePage v-else />
<WelcomePage v-else-if="panelName === 'welcome' || panelName === ''" />

<span v-for="menu in extensionMenus" :key="menu.index" :index="menu.index">
<Extension v-if="panelName === menu.index" :name="menu.name" />
</span>
</el-main>

<div style="position: absolute; bottom: 0px; right: 10px;">
Expand Down
49 changes: 49 additions & 0 deletions console/atest-ui/src/views/Extension.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<script setup lang="ts">
import { API } from './net';

interface Props {
name: string
}
const props = defineProps<Props>()

const loadPlugin = async (): Promise<void> => {
try {
API.GetPageOfCSS(props.name, (d) => {
const style = document.createElement('style');
style.type = 'text/css';
style.textContent = d.message;
document.head.appendChild(style);
});

API.GetPageOfJS(props.name, (d) => {
const script = document.createElement('script');
script.type = 'text/javascript';
script.textContent = d.message;
document.head.appendChild(script);

const plugin = window.ATestPlugin;

if (plugin && plugin.mount) {
console.log('extension load success');
const container = document.getElementById("plugin-container");
plugin.mount(container);
}
});
} catch (error) {
console.log(`extension load error: ${(error as Error).message}`)
} finally {
console.log('extension load finally');
}
};
try {
loadPlugin();
} catch (error) {
console.error('extension load error:', error);
}
</script>

<template>
<div id="plugin-container">
{{ props.name }}
</div>
</template>
45 changes: 34 additions & 11 deletions console/atest-ui/src/views/MockManager.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<script setup lang="ts">
import { ref, watch } from 'vue';
import { Codemirror } from 'vue-codemirror';
import { ElMessage } from 'element-plus'
import yaml from 'js-yaml';
import { jsonSchema } from "codemirror-json-schema";
import { NewTemplateLangComplete, NewHeaderLangComplete } from './languageComplete'
Expand Down Expand Up @@ -34,6 +35,10 @@ interface MockConfig {
ConfigAsJSON: string
Prefix: string
Port: number
storeKind: string
storeLocalFile?: string
storeURL?: string
storeRemote?: string
}

const tabActive = ref('yaml')
Expand Down Expand Up @@ -64,10 +69,18 @@ function jsonToYaml(jsonData: object | string): string {
}

const link = ref('')
API.GetMockConfig((d) => {
mockConfig.value = d
link.value = `http://${window.location.hostname}:${d.Port}${d.Prefix}/api.json`
})
const loadConfig = () => {
API.GetMockConfig((d) => {
ElMessage({
showClose: true,
message: 'Config loaded!',
type: 'success'
});
mockConfig.value = d
link.value = `http://${window.location.hostname}:${d.Port}${d.Prefix}/api.json`
})
}
loadConfig()
const prefixChanged = (p: string) => {
mockConfig.value.Prefix = p
}
Expand Down Expand Up @@ -96,13 +109,21 @@ items:
<template>
<div>
<el-button type="primary" @click="insertSample">{{t('button.insertSample')}}</el-button>
<el-button type="warning" @click="API.ReloadMockServer(mockConfig)">{{t('button.reload')}}</el-button>
<el-button type="warning" @click="API.ReloadMockServer(mockConfig).then(() => loadConfig())">{{t('button.reload')}}</el-button>
<el-divider direction="vertical" />
<el-link target="_blank" :href="link">{{ link }}</el-link> <!-- Noncompliant -->
</div>
<div class="config">
API Prefix:<EditButton :value="mockConfig.Prefix" @changed="prefixChanged"/>
Port:<EditButton :value="mockConfig.Port" @changed="portChanged"/>
Store:
<el-select v-model="mockConfig.storeKind" placeholder="Select Store Kind"
class="m-2 select"
size="default">
<el-option label="Memory" value="memory"></el-option>
<el-option label="Local File" value="localFile"></el-option>
</el-select>
<el-input v-model="mockConfig.storeLocalFile" placeholder="Local File Path" v-if="mockConfig.storeKind === 'localFile'"></el-input>
</div>
<el-splitter layout="vertical" style="height: calc(100vh - 100px);">
<el-splitter-panel size="70%">
Expand All @@ -118,12 +139,12 @@ items:
</el-tabs>
</el-splitter-panel>
<el-splitter-panel size="30%">
<el-card class="log-output" shadow="hover">
<el-card shadow="hover">
<template #header>
<span>{{ t('title.logs') }}</span>
</template>
<el-scrollbar ref="logScrollbar">
<pre style="white-space: pre-wrap; word-break: break-all;">{{ logOutput }}</pre>
<el-scrollbar>
<pre style="white-space: pre-wrap; word-break: break-all;">{{logOutput}}</pre>
</el-scrollbar>
</el-card>
</el-splitter-panel>
Expand All @@ -137,8 +158,10 @@ items:
align-items: center;
gap: 8px;
}
.log-output {
height: 100%;
overflow: auto;
.select {
width: 150px !important;
}
.el-input {
--el-input-width: 300px !important;
}
</style>
Loading
Loading