Implemented most of logic behind REST Mock Services
Added dev.sh script to run r11-tools in dev-mode with hot-reload for frontend
This commit is contained in:
@@ -36,14 +36,12 @@ public class MockController {
|
||||
|
||||
/**
|
||||
* Updates queried message with given set of data
|
||||
* @param body {@link MockedMessageDto} json representation
|
||||
* @param message {@link MockedMessageDto} json representation
|
||||
* @return confirmation and 200 OK
|
||||
*/
|
||||
@SneakyThrows
|
||||
@PutMapping
|
||||
public ResponseEntity<String> updateMessage(@RequestBody String body){
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
MockedMessageDto message = mapper.readValue(body, MockedMessageDto.class);
|
||||
public ResponseEntity<String> updateMessage(@RequestBody MockedMessageDto message){
|
||||
return klausService.setMockedResponse(message);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,34 +1,42 @@
|
||||
<script setup>
|
||||
import {ref} from 'vue';
|
||||
<script setup lang="ts">
|
||||
import { ref} from 'vue';
|
||||
|
||||
const props = defineProps(
|
||||
{
|
||||
headersObject : Object
|
||||
}
|
||||
)
|
||||
const headerData = ref( props.headersObject )
|
||||
|
||||
const emit = defineEmits([
|
||||
'update:httpHeaders'
|
||||
])
|
||||
|
||||
const headerData = ref(props.headersObject)
|
||||
const newHeaderName = ref('');
|
||||
const newHeaderValue = ref('');
|
||||
|
||||
function isHeaderEssential(headerName){
|
||||
function isHeaderEssential(headerName : string){
|
||||
return headerName == "Keep-Alive" || headerName == "Connection" || headerName == "Date"
|
||||
}
|
||||
|
||||
function setEssentialHeaderStyle(headerName){
|
||||
return isHeaderEssential(headerName) ? "text-gray-400" : "text-red-400";
|
||||
function setEssentialHeaderStyle(headerName : string){
|
||||
return isHeaderEssential(headerName) ? "text-gray-400" : "text-red-400";
|
||||
}
|
||||
|
||||
function deleteHeader(index){
|
||||
if(!isHeaderEssential(index)){
|
||||
function deleteHeader(index : string){
|
||||
if(!isHeaderEssential(index) && headerData.value != undefined){
|
||||
delete headerData.value[index]
|
||||
emit('update:httpHeaders',headerData.value)
|
||||
}
|
||||
}
|
||||
|
||||
function addNewHeader(name, value){
|
||||
headerData.value[name] = value;
|
||||
newHeaderName.value = "";
|
||||
newHeaderValue.value = "";
|
||||
function addNewHeader(name : string, value : string){
|
||||
if (headerData.value != undefined){
|
||||
headerData.value[name] = value;
|
||||
newHeaderName.value = "";
|
||||
newHeaderValue.value = "";
|
||||
emit('update:httpHeaders',headerData.value)
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, type Ref } from 'vue';
|
||||
|
||||
interface historyRecord {
|
||||
clientUUID : String,
|
||||
dateTimeStamp: String,
|
||||
headers : Object,
|
||||
httpMethod: String,
|
||||
requestBody: String
|
||||
}
|
||||
|
||||
|
||||
const clientUUID = localStorage.getItem("clientUUID")
|
||||
const fetchLink = window.location.protocol + "//" + window.location.hostname + "/mock/api/event";
|
||||
const historyRecords : Ref<Array<historyRecord>> = ref([])
|
||||
fetch(fetchLink+"/"+clientUUID).then(response => response.json()).then(data => { historyRecords.value = data });
|
||||
|
||||
function parseTimeStamp(timestamp : String){
|
||||
return timestamp.substring(10,19).replace("T"," ");
|
||||
}
|
||||
|
||||
function showHeaders(headers:Object){
|
||||
|
||||
}
|
||||
|
||||
function showBody(body : String){
|
||||
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<table class="text-white h-28 w-5/12 text-center border-l-4 border-b-2">
|
||||
<tr>
|
||||
<th>Time</th>
|
||||
<th>HTTP Method</th>
|
||||
<th>HTTP Headers</th>
|
||||
<th>Request Body</th>
|
||||
</tr>
|
||||
<tr v-for="(item , index) in historyRecords" :key="index">
|
||||
<td> {{ parseTimeStamp(item.dateTimeStamp) }} </td>
|
||||
<td> {{ item.httpMethod }} </td>
|
||||
<td> <button @click="showHeaders(item.headers);">Show Headers</button> </td>
|
||||
<td> <button @click="showBody(item.requestBody)">Show Body</button> </td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</template>
|
||||
36
Frontend/src/components/mock/MockedMessageToastComponent.vue
Normal file
36
Frontend/src/components/mock/MockedMessageToastComponent.vue
Normal file
@@ -0,0 +1,36 @@
|
||||
<script setup lang="ts">
|
||||
import { ref} from 'vue';
|
||||
|
||||
const emit = defineEmits([
|
||||
'closed:toast_closed'
|
||||
])
|
||||
|
||||
const props = defineProps(
|
||||
{
|
||||
message: {type: String, required: true},
|
||||
visible: {type: String, required: true},
|
||||
}
|
||||
)
|
||||
|
||||
function hideToast(){
|
||||
emit('closed:toast_closed',"hidden")
|
||||
}
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<div id="toast-success" :class="visible" class="flex items-center w-full max-w-xs p-4 mb-4 text-gray-500 bg-white rounded-lg shadow dark:text-gray-400 dark:bg-gray-800" role="alert">
|
||||
<div class="inline-flex items-center justify-center flex-shrink-0 w-8 h-8 text-green-500 bg-green-100 rounded-lg dark:bg-green-800 dark:text-green-200">
|
||||
<svg aria-hidden="true" class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"></path></svg>
|
||||
<span class="sr-only">Check icon</span>
|
||||
</div>
|
||||
<div class="ml-3 text-sm font-normal">{{ props.message }}</div>
|
||||
<button @click="hideToast" type="button" class="ml-auto -mx-1.5 -my-1.5 bg-white text-gray-400 hover:text-gray-900 rounded-lg focus:ring-2 focus:ring-gray-300 p-1.5 hover:bg-gray-100 inline-flex h-8 w-8 dark:text-gray-500 dark:hover:text-white dark:bg-gray-800 dark:hover:bg-gray-700">
|
||||
<span class="sr-only">Close</span>
|
||||
<svg aria-hidden="true" class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path></svg>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,6 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import {ref, onBeforeMount , type Ref} from 'vue';
|
||||
import {ref, type Ref} from 'vue';
|
||||
import HeadersComponent from './HeadersComponent.vue';
|
||||
import SaveComponent from './SaveComponent.vue';
|
||||
|
||||
const clientUUID = ref('');
|
||||
const host = window.location.protocol + "//" + window.location.hostname + "/mock";
|
||||
@@ -21,15 +22,12 @@ const exampleData : mockedMessageData = {
|
||||
httpHeaders: {Connection:"keep-alive"},
|
||||
httpStatus: 200,
|
||||
}
|
||||
let messageData : Ref<mockedMessageData> = ref(exampleData) ;
|
||||
|
||||
|
||||
onBeforeMount( () => {
|
||||
if ( localStorage.clientUUID != undefined ){
|
||||
let messageData : Ref<mockedMessageData> = ref(exampleData);
|
||||
if ( localStorage.clientUUID != undefined ){
|
||||
clientUUID.value = localStorage.clientUUID;
|
||||
}
|
||||
fetch(host + '/api/mock/' + clientUUID.value).then( response => response.json() ).then(data => putDataInFields(data));
|
||||
} )
|
||||
}
|
||||
fetch(host + '/api/mock/' + clientUUID.value).then( response => response.json() ).then(data => {putDataInFields(data); });
|
||||
|
||||
function putDataInFields(data: mockedMessageData){
|
||||
clientUUID.value = data.clientUUID;
|
||||
@@ -41,28 +39,33 @@ function putDataInFields(data: mockedMessageData){
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-col w-3/5 text-center gap-6">
|
||||
<div class="flex flex-col w-3/5 text-center dark:text-white gap-6">
|
||||
<div>
|
||||
<label for="link">Link</label><br/>
|
||||
<div class="p-2 border-white border-2">
|
||||
<a class="underline" :href="mockMessageLink">{{ mockMessageLink }}</a>
|
||||
</div>
|
||||
<div class="flex gap-4">
|
||||
<div class="p-2 w-full border-white border-2">
|
||||
<a class="underline" :href="mockMessageLink">{{ mockMessageLink }}</a>
|
||||
</div>
|
||||
<SaveComponent v-bind:message-data="messageData"></SaveComponent>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-row w-full gap-64">
|
||||
<div class="w-full">
|
||||
<label for="contentType">Content Type</label><br/>
|
||||
<input class="bg-gray-600 w-full" id="contentType" type="text" :value="messageData.contentType"/>
|
||||
<input class="bg-gray-600 w-full" id="contentType" type="text" v-model="messageData.contentType"/>
|
||||
</div>
|
||||
<div class=" w-full">
|
||||
|
||||
<div class="w-full">
|
||||
<label for="httpStatus">HttpStatus</label><br/>
|
||||
<input class="bg-gray-600 w-full" id="httpStatus" type="text" :value="messageData.httpStatus"/>
|
||||
<input class="bg-gray-600 w-full" id="httpStatus" type="text" v-model="messageData.httpStatus"/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
<label for="messageBody">Body</label>
|
||||
<textarea class="bg-gray-600 h-64" id="messageBody" :value="messageData.messageBody.toString()"></textarea>
|
||||
<textarea class="bg-gray-600 h-64" id="messageBody" v-model="messageData.messageBody"></textarea>
|
||||
</div>
|
||||
<HeadersComponent :key="JSON.stringify(messageData.httpHeaders)" :headers-object="messageData.httpHeaders"></HeadersComponent>
|
||||
<HeadersComponent @update:httpHeaders="(newHeaders: object) => {messageData.httpHeaders = newHeaders }" :key="JSON.stringify(messageData.httpHeaders)" :headers-object="messageData.httpHeaders"></HeadersComponent>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
45
Frontend/src/components/mock/SaveComponent.vue
Normal file
45
Frontend/src/components/mock/SaveComponent.vue
Normal file
@@ -0,0 +1,45 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import MockedMessageToastComponent from './MockedMessageToastComponent.vue';
|
||||
|
||||
|
||||
const props = defineProps(
|
||||
{
|
||||
messageData : {type: Object, required:true}
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
const message = ref('');
|
||||
const visible = ref('hidden');
|
||||
const fetchLink = window.location.protocol + "//" + window.location.hostname + "/mock/api/mock"
|
||||
|
||||
function prepareAndSendData(){
|
||||
if (props.messageData != null|| props.messageData != undefined ){
|
||||
fetch(fetchLink, { method: "put", body:JSON.stringify(props.messageData), headers: { "Content-Type" : "application/json" }})
|
||||
.then( response => response.text() )
|
||||
.then( data => {message.value = data} )
|
||||
.catch(exception => {message.value = exception})
|
||||
|
||||
showToast();
|
||||
}
|
||||
}
|
||||
|
||||
function showToast(){
|
||||
visible.value = "visible";
|
||||
}
|
||||
|
||||
function hideToast(){
|
||||
visible.value = "hidden";
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<button @click="prepareAndSendData()" class="w-2/12 tool-button">Save</button>
|
||||
|
||||
<div class="fixed bottom-5 right-12">
|
||||
<MockedMessageToastComponent @closed:toast_closed="hideToast()" v-bind:visible="visible" v-bind:message="message"/>
|
||||
</div>
|
||||
</template>
|
||||
@@ -34,11 +34,6 @@ const routes = [
|
||||
name: 'xslt',
|
||||
component: () => xsltTool
|
||||
},
|
||||
{
|
||||
path: '/xml/xpath',
|
||||
name: 'xpath',
|
||||
component: () => restMock
|
||||
},
|
||||
{
|
||||
path: '/rest/mock',
|
||||
name: 'restmock',
|
||||
|
||||
@@ -1,20 +1,14 @@
|
||||
<script lang="ts">
|
||||
<script setup lang="ts">
|
||||
import RestMockMessageComponent from '@components/mock/RestMockMessageComponent.vue'
|
||||
import mockedMessageData from '@components/mock/RestMockMessageComponent.vue'
|
||||
|
||||
export default {
|
||||
name:"RestMockView",
|
||||
components: {RestMockMessageComponent}
|
||||
}
|
||||
|
||||
import HistoryComponent from '@components/mock/HistoryComponent.vue'
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<div class="flex w-full h-screen items-center flex-col">
|
||||
<div class="flex gap-6 w-full h-screen">
|
||||
<RestMockMessageComponent></RestMockMessageComponent>
|
||||
<HistoryComponent></HistoryComponent>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user