Add centralized API client with axios interceptors, remove vue-axios
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
15
package-lock.json
generated
15
package-lock.json
generated
@@ -32,7 +32,6 @@
|
|||||||
"primevue": "^4.5.4",
|
"primevue": "^4.5.4",
|
||||||
"tippy.js": "^6.3.7",
|
"tippy.js": "^6.3.7",
|
||||||
"vue": "^3.5.29",
|
"vue": "^3.5.29",
|
||||||
"vue-axios": "^3.5.2",
|
|
||||||
"vue-chartjs": "^5.3.3",
|
"vue-chartjs": "^5.3.3",
|
||||||
"vue-router": "^5.0.3",
|
"vue-router": "^5.0.3",
|
||||||
"vue-sweetalert2": "^5.0.11",
|
"vue-sweetalert2": "^5.0.11",
|
||||||
@@ -7997,15 +7996,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vue-axios": {
|
|
||||||
"version": "3.5.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/vue-axios/-/vue-axios-3.5.2.tgz",
|
|
||||||
"integrity": "sha512-GP+dct7UlAWkl1qoP3ppw0z6jcSua5/IrMpjB5O8bh089iIiJ+hdxPYH2NPEpajlYgkW5EVMP95ttXWdas1O0g==",
|
|
||||||
"peerDependencies": {
|
|
||||||
"axios": "*",
|
|
||||||
"vue": "^3.0.0 || ^2.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/vue-chartjs": {
|
"node_modules/vue-chartjs": {
|
||||||
"version": "5.3.3",
|
"version": "5.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/vue-chartjs/-/vue-chartjs-5.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/vue-chartjs/-/vue-chartjs-5.3.3.tgz",
|
||||||
@@ -13305,11 +13295,6 @@
|
|||||||
"@vue/shared": "3.5.29"
|
"@vue/shared": "3.5.29"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"vue-axios": {
|
|
||||||
"version": "3.5.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/vue-axios/-/vue-axios-3.5.2.tgz",
|
|
||||||
"integrity": "sha512-GP+dct7UlAWkl1qoP3ppw0z6jcSua5/IrMpjB5O8bh089iIiJ+hdxPYH2NPEpajlYgkW5EVMP95ttXWdas1O0g=="
|
|
||||||
},
|
|
||||||
"vue-chartjs": {
|
"vue-chartjs": {
|
||||||
"version": "5.3.3",
|
"version": "5.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/vue-chartjs/-/vue-chartjs-5.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/vue-chartjs/-/vue-chartjs-5.3.3.tgz",
|
||||||
|
|||||||
@@ -39,7 +39,6 @@
|
|||||||
"primevue": "^4.5.4",
|
"primevue": "^4.5.4",
|
||||||
"tippy.js": "^6.3.7",
|
"tippy.js": "^6.3.7",
|
||||||
"vue": "^3.5.29",
|
"vue": "^3.5.29",
|
||||||
"vue-axios": "^3.5.2",
|
|
||||||
"vue-chartjs": "^5.3.3",
|
"vue-chartjs": "^5.3.3",
|
||||||
"vue-router": "^5.0.3",
|
"vue-router": "^5.0.3",
|
||||||
"vue-sweetalert2": "^5.0.11",
|
"vue-sweetalert2": "^5.0.11",
|
||||||
|
|||||||
33
src/api/auth.js
Normal file
33
src/api/auth.js
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import axios from 'axios';
|
||||||
|
import { getCookie, setCookie, setCookieWithoutExpiration } from '@/utils/cookieUtil.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refresh the access token using the refresh token cookie.
|
||||||
|
* Uses plain axios (not apiClient) to avoid interceptor loops.
|
||||||
|
* @returns {Promise<string>} The new access token.
|
||||||
|
*/
|
||||||
|
export async function refreshTokenAndGetNew() {
|
||||||
|
const api = '/api/oauth/token';
|
||||||
|
const config = {
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const data = {
|
||||||
|
grant_type: 'refresh_token',
|
||||||
|
refresh_token: getCookie('luciaRefreshToken'),
|
||||||
|
};
|
||||||
|
|
||||||
|
const response = await axios.post(api, data, config);
|
||||||
|
const newAccessToken = response.data.access_token;
|
||||||
|
const newRefreshToken = response.data.refresh_token;
|
||||||
|
|
||||||
|
setCookieWithoutExpiration('luciaToken', newAccessToken);
|
||||||
|
// Expire in ~6 months
|
||||||
|
const expiredMs = new Date();
|
||||||
|
expiredMs.setMonth(expiredMs.getMonth() + 6);
|
||||||
|
const days = Math.ceil((expiredMs.getTime() - Date.now()) / (24 * 60 * 60 * 1000));
|
||||||
|
setCookie('luciaRefreshToken', newRefreshToken, days);
|
||||||
|
|
||||||
|
return newAccessToken;
|
||||||
|
}
|
||||||
78
src/api/client.js
Normal file
78
src/api/client.js
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
import axios from 'axios';
|
||||||
|
import { getCookie, deleteCookie } from '@/utils/cookieUtil.js';
|
||||||
|
|
||||||
|
const apiClient = axios.create();
|
||||||
|
|
||||||
|
// Request interceptor: automatically attach Authorization header
|
||||||
|
apiClient.interceptors.request.use((config) => {
|
||||||
|
const token = getCookie('luciaToken');
|
||||||
|
if (token) {
|
||||||
|
config.headers.Authorization = `Bearer ${token}`;
|
||||||
|
}
|
||||||
|
return config;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Response interceptor: handle 401 by attempting token refresh
|
||||||
|
let isRefreshing = false;
|
||||||
|
let pendingRequests = [];
|
||||||
|
|
||||||
|
function onRefreshSuccess(newToken) {
|
||||||
|
pendingRequests.forEach((cb) => cb(newToken));
|
||||||
|
pendingRequests = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
function onRefreshFailure(error) {
|
||||||
|
pendingRequests.forEach((cb) => cb(null, error));
|
||||||
|
pendingRequests = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
apiClient.interceptors.response.use(
|
||||||
|
(response) => response,
|
||||||
|
async (error) => {
|
||||||
|
const originalRequest = error.config;
|
||||||
|
|
||||||
|
// Only attempt refresh on 401, and not for auth endpoints or already-retried requests
|
||||||
|
if (
|
||||||
|
error.response?.status !== 401 ||
|
||||||
|
originalRequest._retried ||
|
||||||
|
originalRequest.url === '/api/oauth/token'
|
||||||
|
) {
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isRefreshing) {
|
||||||
|
// Queue this request until the refresh completes
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
pendingRequests.push((newToken, err) => {
|
||||||
|
if (err) return reject(err);
|
||||||
|
originalRequest.headers.Authorization = `Bearer ${newToken}`;
|
||||||
|
originalRequest._retried = true;
|
||||||
|
resolve(apiClient(originalRequest));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
isRefreshing = true;
|
||||||
|
originalRequest._retried = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Dynamic import to avoid circular dependency with login store
|
||||||
|
const { refreshTokenAndGetNew } = await import('@/api/auth.js');
|
||||||
|
const newToken = await refreshTokenAndGetNew();
|
||||||
|
isRefreshing = false;
|
||||||
|
onRefreshSuccess(newToken);
|
||||||
|
originalRequest.headers.Authorization = `Bearer ${newToken}`;
|
||||||
|
return apiClient(originalRequest);
|
||||||
|
} catch (refreshError) {
|
||||||
|
isRefreshing = false;
|
||||||
|
onRefreshFailure(refreshError);
|
||||||
|
|
||||||
|
// Refresh failed: clear auth and redirect to login
|
||||||
|
deleteCookie('luciaToken');
|
||||||
|
window.location.href = '/login';
|
||||||
|
return Promise.reject(refreshError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
export default apiClient;
|
||||||
@@ -3,8 +3,6 @@ import { createApp, markRaw } from "vue";
|
|||||||
import App from "./App.vue";
|
import App from "./App.vue";
|
||||||
import router from "./router";
|
import router from "./router";
|
||||||
import pinia from '@/stores/main.js';
|
import pinia from '@/stores/main.js';
|
||||||
import axios from 'axios';
|
|
||||||
import VueAxios from 'vue-axios';
|
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import mitt from 'mitt';
|
import mitt from 'mitt';
|
||||||
import ToastPlugin from 'vue-toast-notification';
|
import ToastPlugin from 'vue-toast-notification';
|
||||||
@@ -49,15 +47,9 @@ import ContextMenu from 'primevue/contextmenu';
|
|||||||
const emitter = mitt();
|
const emitter = mitt();
|
||||||
const app = createApp(App);
|
const app = createApp(App);
|
||||||
|
|
||||||
// 將 Axios 實例添加到 Vue 的應用實例中
|
|
||||||
app.config.globalProperties.$http = axios;
|
|
||||||
app.$http = axios; // 將 $http 添加到 Vue 實例中
|
|
||||||
// Pinia Set
|
// Pinia Set
|
||||||
pinia.use(({ store }) => {
|
pinia.use(({ store }) => {
|
||||||
store.$router = markRaw(router);
|
store.$router = markRaw(router);
|
||||||
store.$axios = markRaw(axios);
|
|
||||||
store.$toast = markRaw(ToastPlugin);
|
|
||||||
store.$http = app.$http;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// can use `this.$moment` in Vue.js
|
// can use `this.$moment` in Vue.js
|
||||||
@@ -72,7 +64,6 @@ cytoscape.use( popper((ref) => ref) );
|
|||||||
|
|
||||||
app.use(pinia);
|
app.use(pinia);
|
||||||
app.use(router);
|
app.use(router);
|
||||||
app.use(VueAxios, axios);
|
|
||||||
app.use(VueSweetalert2);
|
app.use(VueSweetalert2);
|
||||||
app.use(ToastPlugin, { // use `this.$toast` in Vue.js
|
app.use(ToastPlugin, { // use `this.$toast` in Vue.js
|
||||||
position: 'bottom',
|
position: 'bottom',
|
||||||
|
|||||||
@@ -1,25 +1,17 @@
|
|||||||
import router from "@/router/index";
|
|
||||||
import loadingStore from '@/stores/loading.js';
|
import loadingStore from '@/stores/loading.js';
|
||||||
import {useToast} from 'vue-toast-notification';
|
import {useToast} from 'vue-toast-notification';
|
||||||
import 'vue-toast-notification/dist/theme-sugar.css';
|
import 'vue-toast-notification/dist/theme-sugar.css';
|
||||||
import axios from "axios";
|
|
||||||
import { deleteCookie } from "@/utils/cookieUtil.js";
|
|
||||||
|
|
||||||
// Delay loading and toast
|
// Delay loading and toast
|
||||||
const delay = (s = 0) => new Promise((resolve, reject) => setTimeout(resolve, s));
|
const delay = (s = 0) => new Promise((resolve, reject) => setTimeout(resolve, s));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* API catch error function
|
* API catch error function.
|
||||||
* @param {object} Error 後端 ERROR
|
* 401 errors are handled by the axios response interceptor in api/client.js.
|
||||||
|
* @param {object} error 後端 ERROR
|
||||||
* @param {string} toastMessage Toast 的提示文字
|
* @param {string} toastMessage Toast 的提示文字
|
||||||
* @returns {string} Error HTTP Status
|
|
||||||
*/
|
*/
|
||||||
export default async function apiError(error, toastMessage) {
|
export default async function apiError(error, toastMessage) {
|
||||||
if(error.request?.status === 401) {
|
|
||||||
delete axios.defaults.headers.common["Authorization"];
|
|
||||||
deleteCookie("luciaToken");
|
|
||||||
return router.push('/login');
|
|
||||||
}
|
|
||||||
const loading = loadingStore();
|
const loading = loadingStore();
|
||||||
const $toast = useToast();
|
const $toast = useToast();
|
||||||
await delay();
|
await delay();
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
|
import apiClient from '@/api/client.js';
|
||||||
import apiError from '@/module/apiError';
|
import apiError from '@/module/apiError';
|
||||||
import piniaLoginStore from '@/stores/login';
|
import piniaLoginStore from '@/stores/login';
|
||||||
import { JUST_CREATE_ACCOUNT_HOT_DURATION_MINS } from '@/constants/constants';
|
import { JUST_CREATE_ACCOUNT_HOT_DURATION_MINS } from '@/constants/constants';
|
||||||
@@ -87,7 +88,7 @@ export default defineStore('acctMgmtStore', {
|
|||||||
async getAllUserAccounts() {
|
async getAllUserAccounts() {
|
||||||
const apiGetUserList = `/api/users`;
|
const apiGetUserList = `/api/users`;
|
||||||
try {
|
try {
|
||||||
const response = await this.$axios.get(apiGetUserList);
|
const response = await apiClient.get(apiGetUserList);
|
||||||
const customizedResponseData = await this.customizeAllUserList(response.data);
|
const customizedResponseData = await this.customizeAllUserList(response.data);
|
||||||
this.allUserAccoutList = await this.moveCurrentLoginUserToFirstRow(customizedResponseData);
|
this.allUserAccoutList = await this.moveCurrentLoginUserToFirstRow(customizedResponseData);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -135,7 +136,7 @@ export default defineStore('acctMgmtStore', {
|
|||||||
const apiCreateAccount = `/api/users`;
|
const apiCreateAccount = `/api/users`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await this.$axios.post(apiCreateAccount, userToCreate);
|
const response = await apiClient.post(apiCreateAccount, userToCreate);
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
this.isOneAccountJustCreate = true;
|
this.isOneAccountJustCreate = true;
|
||||||
this.justCreateUsername = userToCreate.username;
|
this.justCreateUsername = userToCreate.username;
|
||||||
@@ -154,7 +155,7 @@ export default defineStore('acctMgmtStore', {
|
|||||||
const apiDelete = `/api/users/${userToDelete}`;
|
const apiDelete = `/api/users/${userToDelete}`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await this.$axios.delete(apiDelete);
|
const response = await apiClient.delete(apiDelete);
|
||||||
return response.status === 200;
|
return response.status === 200;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
apiError(error, 'Failed to delete the account.');
|
apiError(error, 'Failed to delete the account.');
|
||||||
@@ -170,7 +171,7 @@ export default defineStore('acctMgmtStore', {
|
|||||||
const apiEdit = `/api/users/${userToEdit}`;
|
const apiEdit = `/api/users/${userToEdit}`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await this.$axios.put(apiEdit, {
|
const response = await apiClient.put(apiEdit, {
|
||||||
username: editDetail.newUsername ? editDetail.newUsername : editDetail.username,
|
username: editDetail.newUsername ? editDetail.newUsername : editDetail.username,
|
||||||
password: editDetail.password,
|
password: editDetail.password,
|
||||||
name: editDetail.name,
|
name: editDetail.name,
|
||||||
@@ -186,7 +187,7 @@ export default defineStore('acctMgmtStore', {
|
|||||||
const apiEdit = `/api/users/${userToEdit}`;
|
const apiEdit = `/api/users/${userToEdit}`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await this.$axios.put(apiEdit, {
|
const response = await apiClient.put(apiEdit, {
|
||||||
username: userToEdit,
|
username: userToEdit,
|
||||||
name: newName,
|
name: newName,
|
||||||
is_active: this.currentViewingUser.is_active,
|
is_active: this.currentViewingUser.is_active,
|
||||||
@@ -202,7 +203,7 @@ export default defineStore('acctMgmtStore', {
|
|||||||
const apiEdit = `/api/users/${userToEdit}`;
|
const apiEdit = `/api/users/${userToEdit}`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await this.$axios.put(apiEdit, {
|
const response = await apiClient.put(apiEdit, {
|
||||||
username: userToEdit,
|
username: userToEdit,
|
||||||
name: this.currentViewingUser.name,
|
name: this.currentViewingUser.name,
|
||||||
password: newPwd,
|
password: newPwd,
|
||||||
@@ -223,7 +224,7 @@ export default defineStore('acctMgmtStore', {
|
|||||||
const apiAddRole = `/api/users/${usernameToEdit}/roles/${roleCode}`;
|
const apiAddRole = `/api/users/${usernameToEdit}/roles/${roleCode}`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await this.$axios.put(apiAddRole);
|
const response = await apiClient.put(apiAddRole);
|
||||||
return response.status === 200;
|
return response.status === 200;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
apiError(error, 'Failed to add role to the account.');
|
apiError(error, 'Failed to add role to the account.');
|
||||||
@@ -238,7 +239,7 @@ export default defineStore('acctMgmtStore', {
|
|||||||
const apiDeleteRole = `/api/users/${usernameToEdit}/roles/${roleCode}`;
|
const apiDeleteRole = `/api/users/${usernameToEdit}/roles/${roleCode}`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await this.$axios.delete(apiDeleteRole);
|
const response = await apiClient.delete(apiDeleteRole);
|
||||||
return response.status === 200;
|
return response.status === 200;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
apiError(error, 'Failed to delete a role frome the account.');
|
apiError(error, 'Failed to delete a role frome the account.');
|
||||||
@@ -252,7 +253,7 @@ export default defineStore('acctMgmtStore', {
|
|||||||
async getUserDetail(uniqueUsername: string): Promise<boolean> {
|
async getUserDetail(uniqueUsername: string): Promise<boolean> {
|
||||||
const apiUserDetail = `/api/users/${uniqueUsername}`;
|
const apiUserDetail = `/api/users/${uniqueUsername}`;
|
||||||
try {
|
try {
|
||||||
const response = await this.$axios.get(apiUserDetail);
|
const response = await apiClient.get(apiUserDetail);
|
||||||
this.currentViewingUser = response.data;
|
this.currentViewingUser = response.data;
|
||||||
this.currentViewingUser.is_admin = response.data.roles.some(role => role.code === 'admin');
|
this.currentViewingUser.is_admin = response.data.roles.some(role => role.code === 'admin');
|
||||||
return response.status === 200;
|
return response.status === 200;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
|
import apiClient from "@/api/client.js";
|
||||||
import apiError from '@/module/apiError.js';
|
import apiError from '@/module/apiError.js';
|
||||||
import { Decimal } from 'decimal.js';
|
import { Decimal } from 'decimal.js';
|
||||||
|
|
||||||
@@ -136,7 +137,7 @@ export default defineStore('allMapDataStore', {
|
|||||||
else api = `/api/logs/${logId}/discover`;
|
else api = `/api/logs/${logId}/discover`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await this.$axios.get(api);
|
const response = await apiClient.get(api);
|
||||||
this.allProcessMap = response.data.process_map;
|
this.allProcessMap = response.data.process_map;
|
||||||
this.allBpmn = response.data.bpmn;
|
this.allBpmn = response.data.bpmn;
|
||||||
this.allStats = response.data.stats;
|
this.allStats = response.data.stats;
|
||||||
@@ -163,10 +164,10 @@ export default defineStore('allMapDataStore', {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
let baseResponse;
|
let baseResponse;
|
||||||
const response = await this.$axios.get(api);
|
const response = await apiClient.get(api);
|
||||||
this.allTrace = response.data;
|
this.allTrace = response.data;
|
||||||
if(baseLogId) {
|
if(baseLogId) {
|
||||||
baseResponse = await this.$axios.get(baseApi);
|
baseResponse = await apiClient.get(baseApi);
|
||||||
this.allBaseTrace = baseResponse.data;
|
this.allBaseTrace = baseResponse.data;
|
||||||
}
|
}
|
||||||
} catch(error) {
|
} catch(error) {
|
||||||
@@ -190,7 +191,7 @@ export default defineStore('allMapDataStore', {
|
|||||||
else api = `/api/logs/${logId}/traces/${traceId}?start=${start}&page_size=20`;
|
else api = `/api/logs/${logId}/traces/${traceId}?start=${start}&page_size=20`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await this.$axios.get(api);
|
const response = await apiClient.get(api);
|
||||||
this.allTraceTaskSeq = response.data.task_seq;
|
this.allTraceTaskSeq = response.data.task_seq;
|
||||||
this.allCase = response.data.cases;
|
this.allCase = response.data.cases;
|
||||||
this.allCase.forEach(c => {
|
this.allCase.forEach(c => {
|
||||||
@@ -229,7 +230,7 @@ export default defineStore('allMapDataStore', {
|
|||||||
const api = `/api/logs/${logId}/traces/${traceId}?start=${start}&page_size=20`;
|
const api = `/api/logs/${logId}/traces/${traceId}?start=${start}&page_size=20`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await this.$axios.get(api);
|
const response = await apiClient.get(api);
|
||||||
this.allBaseTraceTaskSeq = response.data.task_seq;
|
this.allBaseTraceTaskSeq = response.data.task_seq;
|
||||||
this.allBaseCase = response.data.cases;
|
this.allBaseCase = response.data.cases;
|
||||||
this.allBaseCase.forEach(c => {
|
this.allBaseCase.forEach(c => {
|
||||||
@@ -266,7 +267,7 @@ export default defineStore('allMapDataStore', {
|
|||||||
const api = `/api/filters/params?log_id=${logId}`;
|
const api = `/api/filters/params?log_id=${logId}`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await this.$axios.get(api);
|
const response = await apiClient.get(api);
|
||||||
this.allFilterTask = response.data.tasks;
|
this.allFilterTask = response.data.tasks;
|
||||||
this.allFilterStartToEnd = response.data.sources;
|
this.allFilterStartToEnd = response.data.sources;
|
||||||
this.allFilterEndToStart = response.data.sinks;
|
this.allFilterEndToStart = response.data.sinks;
|
||||||
@@ -294,7 +295,7 @@ export default defineStore('allMapDataStore', {
|
|||||||
const api = `/api/filters/has-result?log_id=${logId}`;
|
const api = `/api/filters/has-result?log_id=${logId}`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await this.$axios.post(api, this.postRuleData)
|
const response = await apiClient.post(api, this.postRuleData)
|
||||||
this.hasResultRule = response.data.result;
|
this.hasResultRule = response.data.result;
|
||||||
} catch(error) {
|
} catch(error) {
|
||||||
apiError(error, 'Failed to load the Has Result.');
|
apiError(error, 'Failed to load the Has Result.');
|
||||||
@@ -308,7 +309,7 @@ export default defineStore('allMapDataStore', {
|
|||||||
const api = `/api/temp-filters?log_id=${logId}`;
|
const api = `/api/temp-filters?log_id=${logId}`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await this.$axios.post(api, this.postRuleData)
|
const response = await apiClient.post(api, this.postRuleData)
|
||||||
this.tempFilterId = response.data.id;
|
this.tempFilterId = response.data.id;
|
||||||
} catch(error) {
|
} catch(error) {
|
||||||
apiError(error, 'Failed to add the Temporary Filters.');
|
apiError(error, 'Failed to add the Temporary Filters.');
|
||||||
@@ -327,7 +328,7 @@ export default defineStore('allMapDataStore', {
|
|||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await this.$axios.post(api, createFilterObj);
|
const response = await apiClient.post(api, createFilterObj);
|
||||||
this.createFilterId = response.data.id;
|
this.createFilterId = response.data.id;
|
||||||
this.tempFilterId = null;
|
this.tempFilterId = null;
|
||||||
}catch(error) {
|
}catch(error) {
|
||||||
@@ -343,7 +344,7 @@ export default defineStore('allMapDataStore', {
|
|||||||
|
|
||||||
if(createFilterId){
|
if(createFilterId){
|
||||||
try {
|
try {
|
||||||
const response = await this.$axios.get(api);
|
const response = await apiClient.get(api);
|
||||||
this.temporaryData = response.data.rules;
|
this.temporaryData = response.data.rules;
|
||||||
this.logId = response.data.log.id;
|
this.logId = response.data.log.id;
|
||||||
this.filterName = response.data.name;
|
this.filterName = response.data.name;
|
||||||
@@ -362,7 +363,7 @@ export default defineStore('allMapDataStore', {
|
|||||||
const data = this.postRuleData;
|
const data = this.postRuleData;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await this.$axios.put(api, data);
|
const response = await apiClient.put(api, data);
|
||||||
this.isUpdateFilter = response.status === 200;
|
this.isUpdateFilter = response.status === 200;
|
||||||
this.tempFilterId = null;
|
this.tempFilterId = null;
|
||||||
}catch(error) {
|
}catch(error) {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
|
import apiClient from "@/api/client.js";
|
||||||
import apiError from '@/module/apiError.js';
|
import apiError from '@/module/apiError.js';
|
||||||
|
|
||||||
export default defineStore('compareStore', {
|
export default defineStore('compareStore', {
|
||||||
@@ -21,7 +22,7 @@ export default defineStore('compareStore', {
|
|||||||
const api = `/api/compare?datasets=${encodeURIComponent(queryString)}`;
|
const api = `/api/compare?datasets=${encodeURIComponent(queryString)}`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await this.$axios.get(api);
|
const response = await apiClient.get(api);
|
||||||
this.allCompareDashboardData = response.data;
|
this.allCompareDashboardData = response.data;
|
||||||
} catch(error) {
|
} catch(error) {
|
||||||
apiError(error, 'Failed to load the Compare.');
|
apiError(error, 'Failed to load the Compare.');
|
||||||
@@ -44,7 +45,7 @@ export default defineStore('compareStore', {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const response = await this.$axios.get(api);
|
const response = await apiClient.get(api);
|
||||||
|
|
||||||
return response.data.stats;
|
return response.data.stats;
|
||||||
} catch(error) {
|
} catch(error) {
|
||||||
@@ -58,7 +59,7 @@ export default defineStore('compareStore', {
|
|||||||
async getFileName(id) {
|
async getFileName(id) {
|
||||||
id = Number(id)
|
id = Number(id)
|
||||||
try {
|
try {
|
||||||
const response = await this.$axios.get('/api/files');
|
const response = await apiClient.get('/api/files');
|
||||||
const file = response.data.find(i => i.id === id);
|
const file = response.data.find(i => i.id === id);
|
||||||
|
|
||||||
if(file) return file.name;
|
if(file) return file.name;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { defineStore } from "pinia";
|
|||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import { Decimal } from 'decimal.js';
|
import { Decimal } from 'decimal.js';
|
||||||
import abbreviateNumber from '@/module/abbreviateNumber.js';
|
import abbreviateNumber from '@/module/abbreviateNumber.js';
|
||||||
|
import apiClient from "@/api/client.js";
|
||||||
import apiError from '@/module/apiError.js';
|
import apiError from '@/module/apiError.js';
|
||||||
|
|
||||||
export default defineStore('conformanceStore', {
|
export default defineStore('conformanceStore', {
|
||||||
@@ -201,7 +202,7 @@ export default defineStore('conformanceStore', {
|
|||||||
api = `/api/log-checks/params?log_id=${logId}`;
|
api = `/api/log-checks/params?log_id=${logId}`;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const response = await this.$axios.get(api);
|
const response = await apiClient.get(api);
|
||||||
this.allConformanceTask = response.data.tasks;
|
this.allConformanceTask = response.data.tasks;
|
||||||
this.allCfmSeqStart = response.data.sources;
|
this.allCfmSeqStart = response.data.sources;
|
||||||
this.allCfmSeqEnd = response.data.sinks;
|
this.allCfmSeqEnd = response.data.sinks;
|
||||||
@@ -230,7 +231,7 @@ export default defineStore('conformanceStore', {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await this.$axios.post(api, data);
|
const response = await apiClient.post(api, data);
|
||||||
if(filterId !== null) {
|
if(filterId !== null) {
|
||||||
this.conformanceFilterTempCheckId = response.data.id;
|
this.conformanceFilterTempCheckId = response.data.id;
|
||||||
}
|
}
|
||||||
@@ -266,7 +267,7 @@ export default defineStore('conformanceStore', {
|
|||||||
api = `/api/log-checks/${logCreateCheckId}`;
|
api = `/api/log-checks/${logCreateCheckId}`;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const response = await this.$axios.get(api);
|
const response = await apiClient.get(api);
|
||||||
if(!getRouteFile) {
|
if(!getRouteFile) {
|
||||||
this.allConformanceTempReportData = response.data
|
this.allConformanceTempReportData = response.data
|
||||||
} else {
|
} else {
|
||||||
@@ -302,7 +303,7 @@ export default defineStore('conformanceStore', {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await this.$axios.get(api);
|
const response = await apiClient.get(api);
|
||||||
this.allIssueTraces = response.data.traces;
|
this.allIssueTraces = response.data.traces;
|
||||||
} catch(error) {
|
} catch(error) {
|
||||||
apiError(error, 'Failed to Get the detail of a temporary log conformance issue.');
|
apiError(error, 'Failed to Get the detail of a temporary log conformance issue.');
|
||||||
@@ -336,7 +337,7 @@ export default defineStore('conformanceStore', {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await this.$axios.get(api);
|
const response = await apiClient.get(api);
|
||||||
this.allTaskSeq = response.data.task_seq;
|
this.allTaskSeq = response.data.task_seq;
|
||||||
this.allCases = response.data.cases;
|
this.allCases = response.data.cases;
|
||||||
return response.data.cases;
|
return response.data.cases;
|
||||||
@@ -366,7 +367,7 @@ export default defineStore('conformanceStore', {
|
|||||||
else if(logCreateCheckId !== null) api = `/api/log-checks/${logCreateCheckId}/loops/${loopNo}`;
|
else if(logCreateCheckId !== null) api = `/api/log-checks/${logCreateCheckId}/loops/${loopNo}`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await this.$axios.get(api);
|
const response = await apiClient.get(api);
|
||||||
this.allLoopTraces = response.data.traces;
|
this.allLoopTraces = response.data.traces;
|
||||||
} catch(error) {
|
} catch(error) {
|
||||||
apiError(error, 'Failed to Get the detail of a temporary log conformance loop.');
|
apiError(error, 'Failed to Get the detail of a temporary log conformance loop.');
|
||||||
@@ -392,7 +393,7 @@ export default defineStore('conformanceStore', {
|
|||||||
else if(logCreateCheckId !== null) api = `/api/log-checks/${logCreateCheckId}/loops/${loopNo}/traces/${traceId}?start=${start}&page_size=20`;
|
else if(logCreateCheckId !== null) api = `/api/log-checks/${logCreateCheckId}/loops/${loopNo}/traces/${traceId}?start=${start}&page_size=20`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await this.$axios.get(api);
|
const response = await apiClient.get(api);
|
||||||
this.allLoopTaskSeq = response.data.task_seq;
|
this.allLoopTaskSeq = response.data.task_seq;
|
||||||
this.allLoopCases = response.data.cases;
|
this.allLoopCases = response.data.cases;
|
||||||
return response.data.cases;
|
return response.data.cases;
|
||||||
@@ -422,7 +423,7 @@ export default defineStore('conformanceStore', {
|
|||||||
else api = `/api/log-checks?log_id=${logId}`;
|
else api = `/api/log-checks?log_id=${logId}`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await this.$axios.post(api, data);
|
const response = await apiClient.post(api, data);
|
||||||
if(filterId !== null) {
|
if(filterId !== null) {
|
||||||
this.conformanceFilterCreateCheckId = response.data.id;
|
this.conformanceFilterCreateCheckId = response.data.id;
|
||||||
this.conformanceFilterTempCheckId = null;
|
this.conformanceFilterTempCheckId = null;
|
||||||
@@ -449,7 +450,7 @@ export default defineStore('conformanceStore', {
|
|||||||
else if(logCreateCheckId !== null) api = `/api/log-checks/${logCreateCheckId}`;
|
else if(logCreateCheckId !== null) api = `/api/log-checks/${logCreateCheckId}`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await this.$axios.put(api, data);
|
const response = await apiClient.put(api, data);
|
||||||
this.isUpdateConformance = response.status === 200;
|
this.isUpdateConformance = response.status === 200;
|
||||||
this.conformanceLogTempCheckId = null;
|
this.conformanceLogTempCheckId = null;
|
||||||
this.conformanceFilterTempCheckId = null;
|
this.conformanceFilterTempCheckId = null;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import axios from "axios";
|
import apiClient from "@/api/client.js";
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import apiError from '@/module/apiError.js';
|
import apiError from '@/module/apiError.js';
|
||||||
import Swal from 'sweetalert2';
|
import Swal from 'sweetalert2';
|
||||||
@@ -66,7 +66,7 @@ export default defineStore('filesStore', {
|
|||||||
let parentLog = '';
|
let parentLog = '';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await axios.get(api);
|
const response = await apiClient.get(api);
|
||||||
|
|
||||||
this.allEventFiles = response.data;
|
this.allEventFiles = response.data;
|
||||||
this.allEventFiles.forEach(o => {
|
this.allEventFiles.forEach(o => {
|
||||||
@@ -119,7 +119,7 @@ export default defineStore('filesStore', {
|
|||||||
|
|
||||||
uploadloader(); // 進度條
|
uploadloader(); // 進度條
|
||||||
try {
|
try {
|
||||||
const response = await axios.post(api, fromData, config);
|
const response = await apiClient.post(api, fromData, config);
|
||||||
|
|
||||||
this.uploadId = response.data.id;
|
this.uploadId = response.data.id;
|
||||||
this.$router.push({name: 'Upload'});
|
this.$router.push({name: 'Upload'});
|
||||||
@@ -145,7 +145,7 @@ export default defineStore('filesStore', {
|
|||||||
const api = `/api/logs/csv-uploads/${uploadId}`;
|
const api = `/api/logs/csv-uploads/${uploadId}`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await axios.get(api);
|
const response = await apiClient.get(api);
|
||||||
this.allUploadDetail = response.data.preview;
|
this.allUploadDetail = response.data.preview;
|
||||||
} catch(error) {
|
} catch(error) {
|
||||||
apiError(error, 'Failed to get upload detail.');
|
apiError(error, 'Failed to get upload detail.');
|
||||||
@@ -161,7 +161,7 @@ export default defineStore('filesStore', {
|
|||||||
|
|
||||||
uploadloader(); // 進度條
|
uploadloader(); // 進度條
|
||||||
try {
|
try {
|
||||||
const response = await axios.post(api, data);
|
const response = await apiClient.post(api, data);
|
||||||
|
|
||||||
this.uploadLogId = await response.data.id;
|
this.uploadLogId = await response.data.id;
|
||||||
await Swal.close(); // 關閉進度條
|
await Swal.close(); // 關閉進度條
|
||||||
@@ -211,7 +211,7 @@ export default defineStore('filesStore', {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
await axios.put(api, data);
|
await apiClient.put(api, data);
|
||||||
this.uploadFileName = null;
|
this.uploadFileName = null;
|
||||||
await this.fetchAllFiles();
|
await this.fetchAllFiles();
|
||||||
} catch(error) {
|
} catch(error) {
|
||||||
@@ -241,7 +241,7 @@ export default defineStore('filesStore', {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const response = await axios.get(api);
|
const response = await apiClient.get(api);
|
||||||
this.allDependentsData = response.data;
|
this.allDependentsData = response.data;
|
||||||
} catch(error) {
|
} catch(error) {
|
||||||
apiError(error, 'Failed to get Dependents of the files.');
|
apiError(error, 'Failed to get Dependents of the files.');
|
||||||
@@ -276,7 +276,7 @@ export default defineStore('filesStore', {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
await axios.delete(api);
|
await apiClient.delete(api);
|
||||||
await this.fetchAllFiles();
|
await this.fetchAllFiles();
|
||||||
await deleteSuccess();
|
await deleteSuccess();
|
||||||
} catch(error) {
|
} catch(error) {
|
||||||
@@ -296,7 +296,7 @@ export default defineStore('filesStore', {
|
|||||||
loading.isLoading = true;
|
loading.isLoading = true;
|
||||||
api = `/api/deletion/${id}`;
|
api = `/api/deletion/${id}`;
|
||||||
try {
|
try {
|
||||||
await axios.delete(api);
|
await apiClient.delete(api);
|
||||||
} catch(error) {
|
} catch(error) {
|
||||||
apiError(error, 'Failed to Remove a Deletion Record.')
|
apiError(error, 'Failed to Remove a Deletion Record.')
|
||||||
} finally {
|
} finally {
|
||||||
@@ -329,7 +329,7 @@ export default defineStore('filesStore', {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const response = await axios.get(api);
|
const response = await apiClient.get(api);
|
||||||
const csvData = response.data;
|
const csvData = response.data;
|
||||||
const blob = new Blob([csvData], { type: 'text/csv' });
|
const blob = new Blob([csvData], { type: 'text/csv' });
|
||||||
const url = window.URL.createObjectURL(blob);
|
const url = window.URL.createObjectURL(blob);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
import apiClient from '@/api/client.js';
|
||||||
import apiError from '@/module/apiError.js';
|
import apiError from '@/module/apiError.js';
|
||||||
import { deleteCookie, setCookie, setCookieWithoutExpiration, getCookie } from "../utils/cookieUtil";
|
import { deleteCookie, setCookie, setCookieWithoutExpiration, getCookie } from "../utils/cookieUtil";
|
||||||
|
|
||||||
@@ -78,8 +79,6 @@ export default defineStore('loginStore', {
|
|||||||
|
|
||||||
setCookieWithoutExpiration("luciaToken", newAccessToken);
|
setCookieWithoutExpiration("luciaToken", newAccessToken);
|
||||||
setCookie("luciaRefreshToken", newRefreshToken, Math.ceil((this.expired - Date.now()) / (24 * 60 * 60 * 1000)));
|
setCookie("luciaRefreshToken", newRefreshToken, Math.ceil((this.expired - Date.now()) / (24 * 60 * 60 * 1000)));
|
||||||
|
|
||||||
axios.defaults.headers.common['Authorization'] = `Bearer ${newAccessToken}`;
|
|
||||||
}
|
}
|
||||||
} catch(error) {
|
} catch(error) {
|
||||||
// 若refresh token 失敗則導向至登入頁面
|
// 若refresh token 失敗則導向至登入頁面
|
||||||
@@ -91,7 +90,6 @@ export default defineStore('loginStore', {
|
|||||||
* Logout, token expired
|
* Logout, token expired
|
||||||
*/
|
*/
|
||||||
logOut() {
|
logOut() {
|
||||||
delete axios.defaults.headers.common["Authorization"];
|
|
||||||
deleteCookie("luciaToken");
|
deleteCookie("luciaToken");
|
||||||
|
|
||||||
this.isLoggedIn = false;
|
this.isLoggedIn = false;
|
||||||
@@ -106,7 +104,7 @@ export default defineStore('loginStore', {
|
|||||||
const api = '/api/my-account';
|
const api = '/api/my-account';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await axios.get(api);
|
const response = await apiClient.get(api);
|
||||||
|
|
||||||
this.userData = response.data;
|
this.userData = response.data;
|
||||||
} catch(error) {
|
} catch(error) {
|
||||||
@@ -120,7 +118,7 @@ export default defineStore('loginStore', {
|
|||||||
const api = '/api/my-account';
|
const api = '/api/my-account';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await axios.get(api);
|
await apiClient.get(api);
|
||||||
} catch(error) {
|
} catch(error) {
|
||||||
this.$router.push('/login');
|
this.$router.push('/login');
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
|
import apiClient from "@/api/client.js";
|
||||||
import apiError from '@/module/apiError.js';
|
import apiError from '@/module/apiError.js';
|
||||||
|
|
||||||
export default defineStore('performanceStore', {
|
export default defineStore('performanceStore', {
|
||||||
@@ -36,7 +37,7 @@ export default defineStore('performanceStore', {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const response = await this.$axios.get(api);
|
const response = await apiClient.get(api);
|
||||||
this.allPerformanceData = response.data;
|
this.allPerformanceData = response.data;
|
||||||
} catch(error) {
|
} catch(error) {
|
||||||
apiError(error, 'Failed to load the Performance.');
|
apiError(error, 'Failed to load the Performance.');
|
||||||
|
|||||||
8
src/types/shims-vue.d.ts
vendored
8
src/types/shims-vue.d.ts
vendored
@@ -4,11 +4,3 @@ declare module '*.vue' {
|
|||||||
const component: DefineComponent<{}, {}, any>;
|
const component: DefineComponent<{}, {}, any>;
|
||||||
export default component;
|
export default component;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare module 'vue/types/vue' {
|
|
||||||
import { AxiosInstance } from 'axios';
|
|
||||||
interface Vue {
|
|
||||||
$axios: AxiosInstance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
5
src/types/store.d.ts
vendored
5
src/types/store.d.ts
vendored
@@ -1,7 +1,8 @@
|
|||||||
import { AxiosInstance } from 'axios';
|
import 'pinia';
|
||||||
|
import { Router } from 'vue-router';
|
||||||
|
|
||||||
declare module 'pinia' {
|
declare module 'pinia' {
|
||||||
export interface PiniaCustomProperties {
|
export interface PiniaCustomProperties {
|
||||||
$axios: AxiosInstance;
|
$router: Router;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
8
src/types/vue-axios.d.ts
vendored
8
src/types/vue-axios.d.ts
vendored
@@ -1,7 +1 @@
|
|||||||
import { AxiosInstance } from 'axios';
|
// vue-axios type declarations removed — API client is used directly
|
||||||
|
|
||||||
declare module 'vue/types/vue' {
|
|
||||||
interface Vue {
|
|
||||||
$axios: AxiosInstance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
14
src/types/vue.d.ts
vendored
14
src/types/vue.d.ts
vendored
@@ -1,15 +1 @@
|
|||||||
import { AxiosInstance } from 'axios';
|
|
||||||
import { App } from 'vue';
|
import { App } from 'vue';
|
||||||
|
|
||||||
declare module '@vue/runtime-core' {
|
|
||||||
interface ComponentCustomProperties {
|
|
||||||
$http: AxiosInstance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 將類型擴展到 Vue 應用實例
|
|
||||||
declare module 'vue' {
|
|
||||||
interface App {
|
|
||||||
$http: AxiosInstance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -56,8 +56,6 @@
|
|||||||
import { onBeforeMount, computed, } from 'vue';
|
import { onBeforeMount, computed, } from 'vue';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import axios from 'axios';
|
|
||||||
import { getCookie } from "@/utils/cookieUtil.js";
|
|
||||||
import LoadingStore from '@/stores/loading.js';
|
import LoadingStore from '@/stores/loading.js';
|
||||||
import AllMapDataStore from '@/stores/allMapData.js';
|
import AllMapDataStore from '@/stores/allMapData.js';
|
||||||
import ConformanceStore from '@/stores/conformance.js';
|
import ConformanceStore from '@/stores/conformance.js';
|
||||||
@@ -519,10 +517,6 @@
|
|||||||
|
|
||||||
if (isCheckPage) {
|
if (isCheckPage) {
|
||||||
const conformanceStore = ConformanceStore();
|
const conformanceStore = ConformanceStore();
|
||||||
// Save token in Headers.
|
|
||||||
const token = getCookie('luciaToken');
|
|
||||||
|
|
||||||
axios.defaults.headers.common['Authorization'] = `Bearer ${token}`;
|
|
||||||
switch (to.params.type) {
|
switch (to.params.type) {
|
||||||
case 'log':
|
case 'log':
|
||||||
conformanceStore.conformanceLogCreateCheckId = to.params.fileId;
|
conformanceStore.conformanceLogCreateCheckId = to.params.fileId;
|
||||||
|
|||||||
@@ -9,13 +9,11 @@
|
|||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import axios from 'axios';
|
|
||||||
import LoadingStore from '@/stores/loading.js';
|
import LoadingStore from '@/stores/loading.js';
|
||||||
import ConformanceStore from '@/stores/conformance.js';
|
import ConformanceStore from '@/stores/conformance.js';
|
||||||
import StatusBar from '@/components/Discover/StatusBar.vue';
|
import StatusBar from '@/components/Discover/StatusBar.vue';
|
||||||
import ConformanceResults from '@/components/Discover/Conformance/ConformanceResults.vue';
|
import ConformanceResults from '@/components/Discover/Conformance/ConformanceResults.vue';
|
||||||
import ConformanceSidebar from '@/components/Discover/Conformance/ConformanceSidebar.vue';
|
import ConformanceSidebar from '@/components/Discover/Conformance/ConformanceSidebar.vue';
|
||||||
import { getCookie } from "@/utils/cookieUtil.js";
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
setup() {
|
setup() {
|
||||||
@@ -99,10 +97,6 @@ export default {
|
|||||||
// ([^;]*):捕獲 "luciaToken" 的值,直到遇到下一個分號或字符串結尾。
|
// ([^;]*):捕獲 "luciaToken" 的值,直到遇到下一個分號或字符串結尾。
|
||||||
// .*$:匹配剩餘的字符,確保完整的提取。
|
// .*$:匹配剩餘的字符,確保完整的提取。
|
||||||
// |^.*$:在找不到 "luciaToken" 的情況下,匹配整個字符串。
|
// |^.*$:在找不到 "luciaToken" 的情況下,匹配整個字符串。
|
||||||
// 實際應用
|
|
||||||
const token = getCookie('luciaToken');
|
|
||||||
|
|
||||||
axios.defaults.headers.common['Authorization'] = `Bearer ${token}`;
|
|
||||||
switch (to.params.type) {
|
switch (to.params.type) {
|
||||||
case 'log':
|
case 'log':
|
||||||
conformanceStore.setConformanceLogCreateCheckId(to.params.fileId);
|
conformanceStore.setConformanceLogCreateCheckId(to.params.fileId);
|
||||||
|
|||||||
@@ -64,8 +64,6 @@
|
|||||||
import { onBeforeMount, computed, } from 'vue';
|
import { onBeforeMount, computed, } from 'vue';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import axios from 'axios';
|
|
||||||
import { getCookie } from "@/utils/cookieUtil.js";
|
|
||||||
import LoadingStore from '@/stores/loading.js';
|
import LoadingStore from '@/stores/loading.js';
|
||||||
import AllMapDataStore from '@/stores/allMapData.js';
|
import AllMapDataStore from '@/stores/allMapData.js';
|
||||||
import ConformanceStore from '@/stores/conformance.js';
|
import ConformanceStore from '@/stores/conformance.js';
|
||||||
@@ -537,10 +535,6 @@ export default {
|
|||||||
|
|
||||||
if (isCheckPage) {
|
if (isCheckPage) {
|
||||||
const conformanceStore = ConformanceStore();
|
const conformanceStore = ConformanceStore();
|
||||||
// Save token in Headers.
|
|
||||||
const token = getCookie('luciaToken');
|
|
||||||
|
|
||||||
axios.defaults.headers.common['Authorization'] = `Bearer ${token}`;
|
|
||||||
switch (to.params.type) {
|
switch (to.params.type) {
|
||||||
case 'log':
|
case 'log':
|
||||||
conformanceStore.conformanceLogCreateCheckId = to.params.fileId;
|
conformanceStore.conformanceLogCreateCheckId = to.params.fileId;
|
||||||
|
|||||||
@@ -137,7 +137,6 @@
|
|||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import { storeToRefs, mapActions, } from 'pinia';
|
import { storeToRefs, mapActions, } from 'pinia';
|
||||||
import axios from 'axios';
|
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import LoadingStore from '@/stores/loading.js';
|
import LoadingStore from '@/stores/loading.js';
|
||||||
import PerformanceStore from '@/stores/performance.js';
|
import PerformanceStore from '@/stores/performance.js';
|
||||||
@@ -152,7 +151,6 @@ import { simpleTimeLabel, followTimeLabel,
|
|||||||
} from '@/module/timeLabel.js';
|
} from '@/module/timeLabel.js';
|
||||||
import FreqChart from './FreqChart.vue';
|
import FreqChart from './FreqChart.vue';
|
||||||
import { PRIME_VUE_TICKS_LIMIT } from '../../../constants/constants.js';
|
import { PRIME_VUE_TICKS_LIMIT } from '../../../constants/constants.js';
|
||||||
import { getCookie } from "@/utils/cookieUtil.js";
|
|
||||||
|
|
||||||
const primeVueTicksLimit = PRIME_VUE_TICKS_LIMIT;
|
const primeVueTicksLimit = PRIME_VUE_TICKS_LIMIT;
|
||||||
|
|
||||||
@@ -921,10 +919,6 @@ export default {
|
|||||||
|
|
||||||
if (isCheckPage) {
|
if (isCheckPage) {
|
||||||
const conformanceStore = ConformanceStore();
|
const conformanceStore = ConformanceStore();
|
||||||
// Save token in Headers.
|
|
||||||
const token = getCookie('luciaToken');
|
|
||||||
|
|
||||||
axios.defaults.headers.common['Authorization'] = `Bearer ${token}`;
|
|
||||||
switch (to.params.type) {
|
switch (to.params.type) {
|
||||||
case 'log':
|
case 'log':
|
||||||
conformanceStore.conformanceLogCreateCheckId = to.params.fileId;
|
conformanceStore.conformanceLogCreateCheckId = to.params.fileId;
|
||||||
|
|||||||
@@ -85,11 +85,6 @@ export default {
|
|||||||
'refreshToken',
|
'refreshToken',
|
||||||
],),
|
],),
|
||||||
},
|
},
|
||||||
created() {
|
|
||||||
// Save token in Headers.
|
|
||||||
const token = getCookie('luciaToken');
|
|
||||||
this.$http.defaults.headers.common['Authorization'] = `Bearer ${token}`;
|
|
||||||
},
|
|
||||||
// 重新整理畫面以及第一次進入網頁時,beforeRouteEnter這個hook會被執行,然而beforeRouteUpdate不會被執行
|
// 重新整理畫面以及第一次進入網頁時,beforeRouteEnter這個hook會被執行,然而beforeRouteUpdate不會被執行
|
||||||
// PSEUDOCODE
|
// PSEUDOCODE
|
||||||
// if (not logged in) {
|
// if (not logged in) {
|
||||||
|
|||||||
@@ -5,6 +5,13 @@ vi.mock('@/module/apiError.js', () => ({
|
|||||||
default: vi.fn(),
|
default: vi.fn(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const { mockGet, mockPost, mockPut, mockDelete } = vi.hoisted(() => ({
|
||||||
|
mockGet: vi.fn(), mockPost: vi.fn(), mockPut: vi.fn(), mockDelete: vi.fn(),
|
||||||
|
}));
|
||||||
|
vi.mock('@/api/client.js', () => ({
|
||||||
|
default: { get: mockGet, post: mockPost, put: mockPut, delete: mockDelete },
|
||||||
|
}));
|
||||||
|
|
||||||
// Mock login store to avoid its side effects
|
// Mock login store to avoid its side effects
|
||||||
vi.mock('@/stores/login.ts', () => {
|
vi.mock('@/stores/login.ts', () => {
|
||||||
const { defineStore } = require('pinia');
|
const { defineStore } = require('pinia');
|
||||||
@@ -24,17 +31,10 @@ import useAcctMgmtStore from '@/stores/acctMgmt.ts';
|
|||||||
|
|
||||||
describe('acctMgmtStore', () => {
|
describe('acctMgmtStore', () => {
|
||||||
let store;
|
let store;
|
||||||
const mockAxios = {
|
|
||||||
get: vi.fn(),
|
|
||||||
post: vi.fn(),
|
|
||||||
put: vi.fn(),
|
|
||||||
delete: vi.fn(),
|
|
||||||
};
|
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
setActivePinia(createPinia());
|
setActivePinia(createPinia());
|
||||||
store = useAcctMgmtStore();
|
store = useAcctMgmtStore();
|
||||||
store.$axios = mockAxios;
|
|
||||||
vi.clearAllMocks();
|
vi.clearAllMocks();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -84,12 +84,12 @@ describe('acctMgmtStore', () => {
|
|||||||
|
|
||||||
describe('createNewAccount', () => {
|
describe('createNewAccount', () => {
|
||||||
it('posts to /api/users and sets flag on success', async () => {
|
it('posts to /api/users and sets flag on success', async () => {
|
||||||
mockAxios.post.mockResolvedValue({ status: 200 });
|
mockPost.mockResolvedValue({ status: 200 });
|
||||||
const user = { username: 'newuser', password: 'pass' };
|
const user = { username: 'newuser', password: 'pass' };
|
||||||
|
|
||||||
await store.createNewAccount(user);
|
await store.createNewAccount(user);
|
||||||
|
|
||||||
expect(mockAxios.post).toHaveBeenCalledWith(
|
expect(mockPost).toHaveBeenCalledWith(
|
||||||
'/api/users', user,
|
'/api/users', user,
|
||||||
);
|
);
|
||||||
expect(store.isOneAccountJustCreate).toBe(true);
|
expect(store.isOneAccountJustCreate).toBe(true);
|
||||||
@@ -99,18 +99,18 @@ describe('acctMgmtStore', () => {
|
|||||||
|
|
||||||
describe('deleteAccount', () => {
|
describe('deleteAccount', () => {
|
||||||
it('returns true on success', async () => {
|
it('returns true on success', async () => {
|
||||||
mockAxios.delete.mockResolvedValue({ status: 200 });
|
mockDelete.mockResolvedValue({ status: 200 });
|
||||||
|
|
||||||
const result = await store.deleteAccount('alice');
|
const result = await store.deleteAccount('alice');
|
||||||
|
|
||||||
expect(mockAxios.delete).toHaveBeenCalledWith(
|
expect(mockDelete).toHaveBeenCalledWith(
|
||||||
'/api/users/alice',
|
'/api/users/alice',
|
||||||
);
|
);
|
||||||
expect(result).toBe(true);
|
expect(result).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns false on error', async () => {
|
it('returns false on error', async () => {
|
||||||
mockAxios.delete.mockRejectedValue(new Error('fail'));
|
mockDelete.mockRejectedValue(new Error('fail'));
|
||||||
|
|
||||||
const result = await store.deleteAccount('alice');
|
const result = await store.deleteAccount('alice');
|
||||||
|
|
||||||
@@ -120,7 +120,7 @@ describe('acctMgmtStore', () => {
|
|||||||
|
|
||||||
describe('editAccount', () => {
|
describe('editAccount', () => {
|
||||||
it('puts edited data', async () => {
|
it('puts edited data', async () => {
|
||||||
mockAxios.put.mockResolvedValue({ status: 200 });
|
mockPut.mockResolvedValue({ status: 200 });
|
||||||
const detail = {
|
const detail = {
|
||||||
username: 'alice',
|
username: 'alice',
|
||||||
password: 'newpw',
|
password: 'newpw',
|
||||||
@@ -130,7 +130,7 @@ describe('acctMgmtStore', () => {
|
|||||||
|
|
||||||
const result = await store.editAccount('alice', detail);
|
const result = await store.editAccount('alice', detail);
|
||||||
|
|
||||||
expect(mockAxios.put).toHaveBeenCalledWith(
|
expect(mockPut).toHaveBeenCalledWith(
|
||||||
'/api/users/alice',
|
'/api/users/alice',
|
||||||
expect.objectContaining({ password: 'newpw' }),
|
expect.objectContaining({ password: 'newpw' }),
|
||||||
);
|
);
|
||||||
@@ -140,11 +140,11 @@ describe('acctMgmtStore', () => {
|
|||||||
|
|
||||||
describe('addRoleToUser', () => {
|
describe('addRoleToUser', () => {
|
||||||
it('puts role assignment', async () => {
|
it('puts role assignment', async () => {
|
||||||
mockAxios.put.mockResolvedValue({ status: 200 });
|
mockPut.mockResolvedValue({ status: 200 });
|
||||||
|
|
||||||
const result = await store.addRoleToUser('alice', 'admin');
|
const result = await store.addRoleToUser('alice', 'admin');
|
||||||
|
|
||||||
expect(mockAxios.put).toHaveBeenCalledWith(
|
expect(mockPut).toHaveBeenCalledWith(
|
||||||
'/api/users/alice/roles/admin',
|
'/api/users/alice/roles/admin',
|
||||||
);
|
);
|
||||||
expect(result).toBe(true);
|
expect(result).toBe(true);
|
||||||
@@ -153,11 +153,11 @@ describe('acctMgmtStore', () => {
|
|||||||
|
|
||||||
describe('deleteRoleToUser', () => {
|
describe('deleteRoleToUser', () => {
|
||||||
it('deletes role', async () => {
|
it('deletes role', async () => {
|
||||||
mockAxios.delete.mockResolvedValue({ status: 200 });
|
mockDelete.mockResolvedValue({ status: 200 });
|
||||||
|
|
||||||
const result = await store.deleteRoleToUser('alice', 'admin');
|
const result = await store.deleteRoleToUser('alice', 'admin');
|
||||||
|
|
||||||
expect(mockAxios.delete).toHaveBeenCalledWith(
|
expect(mockDelete).toHaveBeenCalledWith(
|
||||||
'/api/users/alice/roles/admin',
|
'/api/users/alice/roles/admin',
|
||||||
);
|
);
|
||||||
expect(result).toBe(true);
|
expect(result).toBe(true);
|
||||||
@@ -166,7 +166,7 @@ describe('acctMgmtStore', () => {
|
|||||||
|
|
||||||
describe('getUserDetail', () => {
|
describe('getUserDetail', () => {
|
||||||
it('fetches user and sets admin flag', async () => {
|
it('fetches user and sets admin flag', async () => {
|
||||||
mockAxios.get.mockResolvedValue({
|
mockGet.mockResolvedValue({
|
||||||
status: 200,
|
status: 200,
|
||||||
data: {
|
data: {
|
||||||
username: 'alice',
|
username: 'alice',
|
||||||
@@ -181,7 +181,7 @@ describe('acctMgmtStore', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('returns false on error', async () => {
|
it('returns false on error', async () => {
|
||||||
mockAxios.get.mockRejectedValue(new Error('not found'));
|
mockGet.mockRejectedValue(new Error('not found'));
|
||||||
|
|
||||||
const result = await store.getUserDetail('ghost');
|
const result = await store.getUserDetail('ghost');
|
||||||
|
|
||||||
|
|||||||
@@ -5,20 +5,21 @@ vi.mock('@/module/apiError.js', () => ({
|
|||||||
default: vi.fn(),
|
default: vi.fn(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const { mockGet, mockPost, mockPut } = vi.hoisted(() => ({
|
||||||
|
mockGet: vi.fn(), mockPost: vi.fn(), mockPut: vi.fn(),
|
||||||
|
}));
|
||||||
|
vi.mock('@/api/client.js', () => ({
|
||||||
|
default: { get: mockGet, post: mockPost, put: mockPut },
|
||||||
|
}));
|
||||||
|
|
||||||
import useAllMapDataStore from '@/stores/allMapData.js';
|
import useAllMapDataStore from '@/stores/allMapData.js';
|
||||||
|
|
||||||
describe('allMapDataStore', () => {
|
describe('allMapDataStore', () => {
|
||||||
let store;
|
let store;
|
||||||
const mockAxios = {
|
|
||||||
get: vi.fn(),
|
|
||||||
post: vi.fn(),
|
|
||||||
put: vi.fn(),
|
|
||||||
};
|
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
setActivePinia(createPinia());
|
setActivePinia(createPinia());
|
||||||
store = useAllMapDataStore();
|
store = useAllMapDataStore();
|
||||||
store.$axios = mockAxios;
|
|
||||||
vi.clearAllMocks();
|
vi.clearAllMocks();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -37,11 +38,11 @@ describe('allMapDataStore', () => {
|
|||||||
stats: { cases: 10 },
|
stats: { cases: 10 },
|
||||||
insights: {},
|
insights: {},
|
||||||
};
|
};
|
||||||
mockAxios.get.mockResolvedValue({ data: mockData });
|
mockGet.mockResolvedValue({ data: mockData });
|
||||||
|
|
||||||
await store.getAllMapData();
|
await store.getAllMapData();
|
||||||
|
|
||||||
expect(mockAxios.get).toHaveBeenCalledWith(
|
expect(mockGet).toHaveBeenCalledWith(
|
||||||
'/api/logs/1/discover',
|
'/api/logs/1/discover',
|
||||||
);
|
);
|
||||||
expect(store.allProcessMap).toEqual({ nodes: [] });
|
expect(store.allProcessMap).toEqual({ nodes: [] });
|
||||||
@@ -51,7 +52,7 @@ describe('allMapDataStore', () => {
|
|||||||
it('fetches temp filter discover data when set', async () => {
|
it('fetches temp filter discover data when set', async () => {
|
||||||
store.logId = 1;
|
store.logId = 1;
|
||||||
store.tempFilterId = 5;
|
store.tempFilterId = 5;
|
||||||
mockAxios.get.mockResolvedValue({
|
mockGet.mockResolvedValue({
|
||||||
data: {
|
data: {
|
||||||
process_map: {},
|
process_map: {},
|
||||||
bpmn: {},
|
bpmn: {},
|
||||||
@@ -62,7 +63,7 @@ describe('allMapDataStore', () => {
|
|||||||
|
|
||||||
await store.getAllMapData();
|
await store.getAllMapData();
|
||||||
|
|
||||||
expect(mockAxios.get).toHaveBeenCalledWith(
|
expect(mockGet).toHaveBeenCalledWith(
|
||||||
'/api/temp-filters/5/discover',
|
'/api/temp-filters/5/discover',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -70,7 +71,7 @@ describe('allMapDataStore', () => {
|
|||||||
it('fetches created filter discover data', async () => {
|
it('fetches created filter discover data', async () => {
|
||||||
store.logId = 1;
|
store.logId = 1;
|
||||||
store.createFilterId = 3;
|
store.createFilterId = 3;
|
||||||
mockAxios.get.mockResolvedValue({
|
mockGet.mockResolvedValue({
|
||||||
data: {
|
data: {
|
||||||
process_map: {},
|
process_map: {},
|
||||||
bpmn: {},
|
bpmn: {},
|
||||||
@@ -81,14 +82,14 @@ describe('allMapDataStore', () => {
|
|||||||
|
|
||||||
await store.getAllMapData();
|
await store.getAllMapData();
|
||||||
|
|
||||||
expect(mockAxios.get).toHaveBeenCalledWith(
|
expect(mockGet).toHaveBeenCalledWith(
|
||||||
'/api/filters/3/discover',
|
'/api/filters/3/discover',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not throw on API failure', async () => {
|
it('does not throw on API failure', async () => {
|
||||||
store.logId = 1;
|
store.logId = 1;
|
||||||
mockAxios.get.mockRejectedValue(new Error('fail'));
|
mockGet.mockRejectedValue(new Error('fail'));
|
||||||
|
|
||||||
await expect(store.getAllMapData())
|
await expect(store.getAllMapData())
|
||||||
.resolves.not.toThrow();
|
.resolves.not.toThrow();
|
||||||
@@ -111,11 +112,11 @@ describe('allMapDataStore', () => {
|
|||||||
trace: [],
|
trace: [],
|
||||||
attrs: [],
|
attrs: [],
|
||||||
};
|
};
|
||||||
mockAxios.get.mockResolvedValue({ data: mockData });
|
mockGet.mockResolvedValue({ data: mockData });
|
||||||
|
|
||||||
await store.getFilterParams();
|
await store.getFilterParams();
|
||||||
|
|
||||||
expect(mockAxios.get).toHaveBeenCalledWith(
|
expect(mockGet).toHaveBeenCalledWith(
|
||||||
'/api/filters/params?log_id=1',
|
'/api/filters/params?log_id=1',
|
||||||
);
|
);
|
||||||
expect(store.allFilterTask).toEqual(['A', 'B']);
|
expect(store.allFilterTask).toEqual(['A', 'B']);
|
||||||
@@ -129,13 +130,13 @@ describe('allMapDataStore', () => {
|
|||||||
it('posts rule data and stores result', async () => {
|
it('posts rule data and stores result', async () => {
|
||||||
store.logId = 1;
|
store.logId = 1;
|
||||||
store.postRuleData = [{ type: 'task' }];
|
store.postRuleData = [{ type: 'task' }];
|
||||||
mockAxios.post.mockResolvedValue({
|
mockPost.mockResolvedValue({
|
||||||
data: { result: true },
|
data: { result: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
await store.checkHasResult();
|
await store.checkHasResult();
|
||||||
|
|
||||||
expect(mockAxios.post).toHaveBeenCalledWith(
|
expect(mockPost).toHaveBeenCalledWith(
|
||||||
'/api/filters/has-result?log_id=1',
|
'/api/filters/has-result?log_id=1',
|
||||||
[{ type: 'task' }],
|
[{ type: 'task' }],
|
||||||
);
|
);
|
||||||
@@ -147,7 +148,7 @@ describe('allMapDataStore', () => {
|
|||||||
it('creates temp filter and stores id', async () => {
|
it('creates temp filter and stores id', async () => {
|
||||||
store.logId = 1;
|
store.logId = 1;
|
||||||
store.postRuleData = [];
|
store.postRuleData = [];
|
||||||
mockAxios.post.mockResolvedValue({ data: { id: 77 } });
|
mockPost.mockResolvedValue({ data: { id: 77 } });
|
||||||
|
|
||||||
await store.addTempFilterId();
|
await store.addTempFilterId();
|
||||||
|
|
||||||
@@ -160,11 +161,11 @@ describe('allMapDataStore', () => {
|
|||||||
store.logId = 1;
|
store.logId = 1;
|
||||||
store.tempFilterId = 77;
|
store.tempFilterId = 77;
|
||||||
store.postRuleData = [{ type: 'rule' }];
|
store.postRuleData = [{ type: 'rule' }];
|
||||||
mockAxios.post.mockResolvedValue({ data: { id: 88 } });
|
mockPost.mockResolvedValue({ data: { id: 88 } });
|
||||||
|
|
||||||
await store.addFilterId('myFilter');
|
await store.addFilterId('myFilter');
|
||||||
|
|
||||||
expect(mockAxios.post).toHaveBeenCalledWith(
|
expect(mockPost).toHaveBeenCalledWith(
|
||||||
'/api/filters?log_id=1',
|
'/api/filters?log_id=1',
|
||||||
{ name: 'myFilter', rules: [{ type: 'rule' }] },
|
{ name: 'myFilter', rules: [{ type: 'rule' }] },
|
||||||
);
|
);
|
||||||
@@ -178,11 +179,11 @@ describe('allMapDataStore', () => {
|
|||||||
store.createFilterId = 88;
|
store.createFilterId = 88;
|
||||||
store.tempFilterId = 77;
|
store.tempFilterId = 77;
|
||||||
store.postRuleData = [{ type: 'updated' }];
|
store.postRuleData = [{ type: 'updated' }];
|
||||||
mockAxios.put.mockResolvedValue({ status: 200 });
|
mockPut.mockResolvedValue({ status: 200 });
|
||||||
|
|
||||||
await store.updateFilter();
|
await store.updateFilter();
|
||||||
|
|
||||||
expect(mockAxios.put).toHaveBeenCalledWith(
|
expect(mockPut).toHaveBeenCalledWith(
|
||||||
'/api/filters/88',
|
'/api/filters/88',
|
||||||
[{ type: 'updated' }],
|
[{ type: 'updated' }],
|
||||||
);
|
);
|
||||||
@@ -195,7 +196,7 @@ describe('allMapDataStore', () => {
|
|||||||
it('does not crash when baseLogId is falsy', async () => {
|
it('does not crash when baseLogId is falsy', async () => {
|
||||||
store.logId = 1;
|
store.logId = 1;
|
||||||
store.baseLogId = null;
|
store.baseLogId = null;
|
||||||
mockAxios.get.mockResolvedValue({ data: [{ id: 1 }] });
|
mockGet.mockResolvedValue({ data: [{ id: 1 }] });
|
||||||
|
|
||||||
await store.getAllTrace();
|
await store.getAllTrace();
|
||||||
|
|
||||||
|
|||||||
@@ -5,18 +5,19 @@ vi.mock('@/module/apiError.js', () => ({
|
|||||||
default: vi.fn(),
|
default: vi.fn(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const { mockGet } = vi.hoisted(() => ({ mockGet: vi.fn() }));
|
||||||
|
vi.mock('@/api/client.js', () => ({
|
||||||
|
default: { get: mockGet },
|
||||||
|
}));
|
||||||
|
|
||||||
import useCompareStore from '@/stores/compare.js';
|
import useCompareStore from '@/stores/compare.js';
|
||||||
|
|
||||||
describe('compareStore', () => {
|
describe('compareStore', () => {
|
||||||
let store;
|
let store;
|
||||||
const mockAxios = {
|
|
||||||
get: vi.fn(),
|
|
||||||
};
|
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
setActivePinia(createPinia());
|
setActivePinia(createPinia());
|
||||||
store = useCompareStore();
|
store = useCompareStore();
|
||||||
store.$axios = mockAxios;
|
|
||||||
vi.clearAllMocks();
|
vi.clearAllMocks();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -33,19 +34,19 @@ describe('compareStore', () => {
|
|||||||
it('fetches compare data with encoded params', async () => {
|
it('fetches compare data with encoded params', async () => {
|
||||||
const params = [{ type: 'log', id: 1 }];
|
const params = [{ type: 'log', id: 1 }];
|
||||||
const mockData = { time: {}, freq: {} };
|
const mockData = { time: {}, freq: {} };
|
||||||
mockAxios.get.mockResolvedValue({ data: mockData });
|
mockGet.mockResolvedValue({ data: mockData });
|
||||||
|
|
||||||
await store.getCompare(params);
|
await store.getCompare(params);
|
||||||
|
|
||||||
const encoded = encodeURIComponent(JSON.stringify(params));
|
const encoded = encodeURIComponent(JSON.stringify(params));
|
||||||
expect(mockAxios.get).toHaveBeenCalledWith(
|
expect(mockGet).toHaveBeenCalledWith(
|
||||||
`/api/compare?datasets=${encoded}`,
|
`/api/compare?datasets=${encoded}`,
|
||||||
);
|
);
|
||||||
expect(store.allCompareDashboardData).toEqual(mockData);
|
expect(store.allCompareDashboardData).toEqual(mockData);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not throw on API failure', async () => {
|
it('does not throw on API failure', async () => {
|
||||||
mockAxios.get.mockRejectedValue(new Error('fail'));
|
mockGet.mockRejectedValue(new Error('fail'));
|
||||||
|
|
||||||
await expect(store.getCompare([]))
|
await expect(store.getCompare([]))
|
||||||
.resolves.not.toThrow();
|
.resolves.not.toThrow();
|
||||||
@@ -54,26 +55,26 @@ describe('compareStore', () => {
|
|||||||
|
|
||||||
describe('getStateData', () => {
|
describe('getStateData', () => {
|
||||||
it('fetches log discover stats', async () => {
|
it('fetches log discover stats', async () => {
|
||||||
mockAxios.get.mockResolvedValue({
|
mockGet.mockResolvedValue({
|
||||||
data: { stats: { cases: 100 } },
|
data: { stats: { cases: 100 } },
|
||||||
});
|
});
|
||||||
|
|
||||||
const result = await store.getStateData('log', 1);
|
const result = await store.getStateData('log', 1);
|
||||||
|
|
||||||
expect(mockAxios.get).toHaveBeenCalledWith(
|
expect(mockGet).toHaveBeenCalledWith(
|
||||||
'/api/logs/1/discover',
|
'/api/logs/1/discover',
|
||||||
);
|
);
|
||||||
expect(result).toEqual({ cases: 100 });
|
expect(result).toEqual({ cases: 100 });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('fetches filter discover stats', async () => {
|
it('fetches filter discover stats', async () => {
|
||||||
mockAxios.get.mockResolvedValue({
|
mockGet.mockResolvedValue({
|
||||||
data: { stats: { cases: 50 } },
|
data: { stats: { cases: 50 } },
|
||||||
});
|
});
|
||||||
|
|
||||||
const result = await store.getStateData('filter', 3);
|
const result = await store.getStateData('filter', 3);
|
||||||
|
|
||||||
expect(mockAxios.get).toHaveBeenCalledWith(
|
expect(mockGet).toHaveBeenCalledWith(
|
||||||
'/api/filters/3/discover',
|
'/api/filters/3/discover',
|
||||||
);
|
);
|
||||||
expect(result).toEqual({ cases: 50 });
|
expect(result).toEqual({ cases: 50 });
|
||||||
@@ -82,7 +83,7 @@ describe('compareStore', () => {
|
|||||||
|
|
||||||
describe('getFileName', () => {
|
describe('getFileName', () => {
|
||||||
it('finds file name by id', async () => {
|
it('finds file name by id', async () => {
|
||||||
mockAxios.get.mockResolvedValue({
|
mockGet.mockResolvedValue({
|
||||||
data: [
|
data: [
|
||||||
{ id: 1, name: 'file1.csv' },
|
{ id: 1, name: 'file1.csv' },
|
||||||
{ id: 2, name: 'file2.csv' },
|
{ id: 2, name: 'file2.csv' },
|
||||||
@@ -95,7 +96,7 @@ describe('compareStore', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('returns undefined for non-existent id', async () => {
|
it('returns undefined for non-existent id', async () => {
|
||||||
mockAxios.get.mockResolvedValue({
|
mockGet.mockResolvedValue({
|
||||||
data: [{ id: 1, name: 'file1.csv' }],
|
data: [{ id: 1, name: 'file1.csv' }],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -5,21 +5,22 @@ vi.mock('@/module/apiError.js', () => ({
|
|||||||
default: vi.fn(),
|
default: vi.fn(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const { mockGet, mockPost, mockPut } = vi.hoisted(() => ({
|
||||||
|
mockGet: vi.fn(), mockPost: vi.fn(), mockPut: vi.fn(),
|
||||||
|
}));
|
||||||
|
vi.mock('@/api/client.js', () => ({
|
||||||
|
default: { get: mockGet, post: mockPost, put: mockPut },
|
||||||
|
}));
|
||||||
|
|
||||||
import apiError from '@/module/apiError.js';
|
import apiError from '@/module/apiError.js';
|
||||||
import useConformanceStore from '@/stores/conformance.js';
|
import useConformanceStore from '@/stores/conformance.js';
|
||||||
|
|
||||||
describe('conformanceStore', () => {
|
describe('conformanceStore', () => {
|
||||||
let store;
|
let store;
|
||||||
const mockAxios = {
|
|
||||||
get: vi.fn(),
|
|
||||||
post: vi.fn(),
|
|
||||||
put: vi.fn(),
|
|
||||||
};
|
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
setActivePinia(createPinia());
|
setActivePinia(createPinia());
|
||||||
store = useConformanceStore();
|
store = useConformanceStore();
|
||||||
store.$axios = mockAxios;
|
|
||||||
vi.clearAllMocks();
|
vi.clearAllMocks();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -42,11 +43,11 @@ describe('conformanceStore', () => {
|
|||||||
waiting_time: {},
|
waiting_time: {},
|
||||||
cycle_time: {},
|
cycle_time: {},
|
||||||
};
|
};
|
||||||
mockAxios.get.mockResolvedValue({ data: mockData });
|
mockGet.mockResolvedValue({ data: mockData });
|
||||||
|
|
||||||
await store.getConformanceParams();
|
await store.getConformanceParams();
|
||||||
|
|
||||||
expect(mockAxios.get).toHaveBeenCalledWith(
|
expect(mockGet).toHaveBeenCalledWith(
|
||||||
'/api/log-checks/params?log_id=1',
|
'/api/log-checks/params?log_id=1',
|
||||||
);
|
);
|
||||||
expect(store.allConformanceTask).toEqual([{ label: 'A' }]);
|
expect(store.allConformanceTask).toEqual([{ label: 'A' }]);
|
||||||
@@ -63,11 +64,11 @@ describe('conformanceStore', () => {
|
|||||||
waiting_time: {},
|
waiting_time: {},
|
||||||
cycle_time: {},
|
cycle_time: {},
|
||||||
};
|
};
|
||||||
mockAxios.get.mockResolvedValue({ data: mockData });
|
mockGet.mockResolvedValue({ data: mockData });
|
||||||
|
|
||||||
await store.getConformanceParams();
|
await store.getConformanceParams();
|
||||||
|
|
||||||
expect(mockAxios.get).toHaveBeenCalledWith(
|
expect(mockGet).toHaveBeenCalledWith(
|
||||||
'/api/filter-checks/params?filter_id=5',
|
'/api/filter-checks/params?filter_id=5',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -77,11 +78,11 @@ describe('conformanceStore', () => {
|
|||||||
it('posts to log temp-check and stores id', async () => {
|
it('posts to log temp-check and stores id', async () => {
|
||||||
store.conformanceLogId = 1;
|
store.conformanceLogId = 1;
|
||||||
store.conformanceFilterId = null;
|
store.conformanceFilterId = null;
|
||||||
mockAxios.post.mockResolvedValue({ data: { id: 42 } });
|
mockPost.mockResolvedValue({ data: { id: 42 } });
|
||||||
|
|
||||||
await store.addConformanceCheckId({ rule: 'test' });
|
await store.addConformanceCheckId({ rule: 'test' });
|
||||||
|
|
||||||
expect(mockAxios.post).toHaveBeenCalledWith(
|
expect(mockPost).toHaveBeenCalledWith(
|
||||||
'/api/temp-log-checks?log_id=1',
|
'/api/temp-log-checks?log_id=1',
|
||||||
{ rule: 'test' },
|
{ rule: 'test' },
|
||||||
);
|
);
|
||||||
@@ -90,11 +91,11 @@ describe('conformanceStore', () => {
|
|||||||
|
|
||||||
it('posts to filter temp-check when filter set', async () => {
|
it('posts to filter temp-check when filter set', async () => {
|
||||||
store.conformanceFilterId = 3;
|
store.conformanceFilterId = 3;
|
||||||
mockAxios.post.mockResolvedValue({ data: { id: 99 } });
|
mockPost.mockResolvedValue({ data: { id: 99 } });
|
||||||
|
|
||||||
await store.addConformanceCheckId({ rule: 'test' });
|
await store.addConformanceCheckId({ rule: 'test' });
|
||||||
|
|
||||||
expect(mockAxios.post).toHaveBeenCalledWith(
|
expect(mockPost).toHaveBeenCalledWith(
|
||||||
'/api/temp-filter-checks?filter_id=3',
|
'/api/temp-filter-checks?filter_id=3',
|
||||||
{ rule: 'test' },
|
{ rule: 'test' },
|
||||||
);
|
);
|
||||||
@@ -106,11 +107,11 @@ describe('conformanceStore', () => {
|
|||||||
it('fetches temp log check report', async () => {
|
it('fetches temp log check report', async () => {
|
||||||
store.conformanceLogTempCheckId = 10;
|
store.conformanceLogTempCheckId = 10;
|
||||||
const mockData = { file: {}, charts: {} };
|
const mockData = { file: {}, charts: {} };
|
||||||
mockAxios.get.mockResolvedValue({ data: mockData });
|
mockGet.mockResolvedValue({ data: mockData });
|
||||||
|
|
||||||
await store.getConformanceReport();
|
await store.getConformanceReport();
|
||||||
|
|
||||||
expect(mockAxios.get).toHaveBeenCalledWith(
|
expect(mockGet).toHaveBeenCalledWith(
|
||||||
'/api/temp-log-checks/10',
|
'/api/temp-log-checks/10',
|
||||||
);
|
);
|
||||||
expect(store.allConformanceTempReportData).toEqual(mockData);
|
expect(store.allConformanceTempReportData).toEqual(mockData);
|
||||||
@@ -119,7 +120,7 @@ describe('conformanceStore', () => {
|
|||||||
it('stores routeFile when getRouteFile=true', async () => {
|
it('stores routeFile when getRouteFile=true', async () => {
|
||||||
store.conformanceLogTempCheckId = 10;
|
store.conformanceLogTempCheckId = 10;
|
||||||
const mockData = { file: { name: 'test.csv' } };
|
const mockData = { file: { name: 'test.csv' } };
|
||||||
mockAxios.get.mockResolvedValue({ data: mockData });
|
mockGet.mockResolvedValue({ data: mockData });
|
||||||
|
|
||||||
await store.getConformanceReport(true);
|
await store.getConformanceReport(true);
|
||||||
|
|
||||||
@@ -134,11 +135,11 @@ describe('conformanceStore', () => {
|
|||||||
store.conformanceFilterId = null;
|
store.conformanceFilterId = null;
|
||||||
store.conformanceLogTempCheckId = 10;
|
store.conformanceLogTempCheckId = 10;
|
||||||
store.conformanceRuleData = { type: 'test' };
|
store.conformanceRuleData = { type: 'test' };
|
||||||
mockAxios.post.mockResolvedValue({ data: { id: 100 } });
|
mockPost.mockResolvedValue({ data: { id: 100 } });
|
||||||
|
|
||||||
await store.addConformanceCreateCheckId('myRule');
|
await store.addConformanceCreateCheckId('myRule');
|
||||||
|
|
||||||
expect(mockAxios.post).toHaveBeenCalledWith(
|
expect(mockPost).toHaveBeenCalledWith(
|
||||||
'/api/log-checks?log_id=1',
|
'/api/log-checks?log_id=1',
|
||||||
{ name: 'myRule', rule: { type: 'test' } },
|
{ name: 'myRule', rule: { type: 'test' } },
|
||||||
);
|
);
|
||||||
@@ -151,11 +152,11 @@ describe('conformanceStore', () => {
|
|||||||
it('updates existing log check', async () => {
|
it('updates existing log check', async () => {
|
||||||
store.conformanceLogCreateCheckId = 50;
|
store.conformanceLogCreateCheckId = 50;
|
||||||
store.conformanceRuleData = { type: 'updated' };
|
store.conformanceRuleData = { type: 'updated' };
|
||||||
mockAxios.put.mockResolvedValue({ status: 200 });
|
mockPut.mockResolvedValue({ status: 200 });
|
||||||
|
|
||||||
await store.updateConformance();
|
await store.updateConformance();
|
||||||
|
|
||||||
expect(mockAxios.put).toHaveBeenCalledWith(
|
expect(mockPut).toHaveBeenCalledWith(
|
||||||
'/api/log-checks/50',
|
'/api/log-checks/50',
|
||||||
{ type: 'updated' },
|
{ type: 'updated' },
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -21,13 +21,14 @@ vi.mock('@/router/index.ts', () => ({
|
|||||||
default: { push: vi.fn(), currentRoute: { value: { path: '/' } } },
|
default: { push: vi.fn(), currentRoute: { value: { path: '/' } } },
|
||||||
}));
|
}));
|
||||||
|
|
||||||
import axios from 'axios';
|
const { mockGet, mockPost, mockPut, mockDelete } = vi.hoisted(() => ({
|
||||||
import useFilesStore from '@/stores/files.js';
|
mockGet: vi.fn(), mockPost: vi.fn(), mockPut: vi.fn(), mockDelete: vi.fn(),
|
||||||
|
}));
|
||||||
|
vi.mock('@/api/client.js', () => ({
|
||||||
|
default: { get: mockGet, post: mockPost, put: mockPut, delete: mockDelete },
|
||||||
|
}));
|
||||||
|
|
||||||
vi.spyOn(axios, 'get').mockImplementation(vi.fn());
|
import useFilesStore from '@/stores/files.js';
|
||||||
vi.spyOn(axios, 'post').mockImplementation(vi.fn());
|
|
||||||
vi.spyOn(axios, 'put').mockImplementation(vi.fn());
|
|
||||||
vi.spyOn(axios, 'delete').mockImplementation(vi.fn());
|
|
||||||
|
|
||||||
describe('filesStore', () => {
|
describe('filesStore', () => {
|
||||||
let store;
|
let store;
|
||||||
@@ -63,7 +64,7 @@ describe('filesStore', () => {
|
|||||||
|
|
||||||
describe('fetchAllFiles', () => {
|
describe('fetchAllFiles', () => {
|
||||||
it('fetches and transforms file data', async () => {
|
it('fetches and transforms file data', async () => {
|
||||||
axios.get.mockResolvedValue({
|
mockGet.mockResolvedValue({
|
||||||
data: [
|
data: [
|
||||||
{
|
{
|
||||||
type: 'log',
|
type: 'log',
|
||||||
@@ -85,7 +86,7 @@ describe('filesStore', () => {
|
|||||||
|
|
||||||
await store.fetchAllFiles();
|
await store.fetchAllFiles();
|
||||||
|
|
||||||
expect(axios.get).toHaveBeenCalledWith('/api/files');
|
expect(mockGet).toHaveBeenCalledWith('/api/files');
|
||||||
expect(store.allEventFiles).toHaveLength(2);
|
expect(store.allEventFiles).toHaveLength(2);
|
||||||
expect(store.allEventFiles[0].fileType).toBe('Log');
|
expect(store.allEventFiles[0].fileType).toBe('Log');
|
||||||
expect(store.allEventFiles[0].icon).toBe('work_history');
|
expect(store.allEventFiles[0].icon).toBe('work_history');
|
||||||
@@ -96,19 +97,19 @@ describe('filesStore', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('does not throw on API failure', async () => {
|
it('does not throw on API failure', async () => {
|
||||||
axios.get.mockRejectedValue(new Error('Network error'));
|
mockGet.mockRejectedValue(new Error('Network error'));
|
||||||
await expect(store.fetchAllFiles()).resolves.toBeUndefined();
|
await expect(store.fetchAllFiles()).resolves.toBeUndefined();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('upload', () => {
|
describe('upload', () => {
|
||||||
it('uploads file and navigates to Upload page', async () => {
|
it('uploads file and navigates to Upload page', async () => {
|
||||||
axios.post.mockResolvedValue({ data: { id: 42 } });
|
mockPost.mockResolvedValue({ data: { id: 42 } });
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
|
|
||||||
await store.upload(formData);
|
await store.upload(formData);
|
||||||
|
|
||||||
expect(axios.post).toHaveBeenCalledWith(
|
expect(mockPost).toHaveBeenCalledWith(
|
||||||
'/api/logs/csv-uploads',
|
'/api/logs/csv-uploads',
|
||||||
formData,
|
formData,
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
@@ -123,25 +124,25 @@ describe('filesStore', () => {
|
|||||||
describe('getUploadDetail', () => {
|
describe('getUploadDetail', () => {
|
||||||
it('fetches upload preview', async () => {
|
it('fetches upload preview', async () => {
|
||||||
store.uploadId = 10;
|
store.uploadId = 10;
|
||||||
axios.get.mockResolvedValue({
|
mockGet.mockResolvedValue({
|
||||||
data: { preview: { columns: ['a', 'b'] } },
|
data: { preview: { columns: ['a', 'b'] } },
|
||||||
});
|
});
|
||||||
|
|
||||||
await store.getUploadDetail();
|
await store.getUploadDetail();
|
||||||
|
|
||||||
expect(axios.get).toHaveBeenCalledWith('/api/logs/csv-uploads/10');
|
expect(mockGet).toHaveBeenCalledWith('/api/logs/csv-uploads/10');
|
||||||
expect(store.allUploadDetail).toEqual({ columns: ['a', 'b'] });
|
expect(store.allUploadDetail).toEqual({ columns: ['a', 'b'] });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('rename', () => {
|
describe('rename', () => {
|
||||||
it('renames a log file', async () => {
|
it('renames a log file', async () => {
|
||||||
axios.put.mockResolvedValue({});
|
mockPut.mockResolvedValue({});
|
||||||
axios.get.mockResolvedValue({ data: [] });
|
mockGet.mockResolvedValue({ data: [] });
|
||||||
|
|
||||||
await store.rename('log', 5, 'new-name');
|
await store.rename('log', 5, 'new-name');
|
||||||
|
|
||||||
expect(axios.put).toHaveBeenCalledWith('/api/logs/5/name', {
|
expect(mockPut).toHaveBeenCalledWith('/api/logs/5/name', {
|
||||||
name: 'new-name',
|
name: 'new-name',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -149,30 +150,30 @@ describe('filesStore', () => {
|
|||||||
|
|
||||||
describe('getDependents', () => {
|
describe('getDependents', () => {
|
||||||
it('fetches dependents for a log', async () => {
|
it('fetches dependents for a log', async () => {
|
||||||
axios.get.mockResolvedValue({ data: [{ id: 1 }, { id: 2 }] });
|
mockGet.mockResolvedValue({ data: [{ id: 1 }, { id: 2 }] });
|
||||||
|
|
||||||
await store.getDependents('log', 7);
|
await store.getDependents('log', 7);
|
||||||
|
|
||||||
expect(axios.get).toHaveBeenCalledWith('/api/logs/7/dependents');
|
expect(mockGet).toHaveBeenCalledWith('/api/logs/7/dependents');
|
||||||
expect(store.allDependentsData).toEqual([{ id: 1 }, { id: 2 }]);
|
expect(store.allDependentsData).toEqual([{ id: 1 }, { id: 2 }]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('deleteFile', () => {
|
describe('deleteFile', () => {
|
||||||
it('calls axios.delete before fetchAllFiles', async () => {
|
it('calls mockDelete before fetchAllFiles', async () => {
|
||||||
const callOrder = [];
|
const callOrder = [];
|
||||||
axios.delete.mockImplementation(async () => {
|
mockDelete.mockImplementation(async () => {
|
||||||
callOrder.push('delete');
|
callOrder.push('delete');
|
||||||
return {};
|
return {};
|
||||||
});
|
});
|
||||||
axios.get.mockImplementation(async () => {
|
mockGet.mockImplementation(async () => {
|
||||||
callOrder.push('get');
|
callOrder.push('get');
|
||||||
return { data: [] };
|
return { data: [] };
|
||||||
});
|
});
|
||||||
|
|
||||||
await store.deleteFile('log', 1);
|
await store.deleteFile('log', 1);
|
||||||
|
|
||||||
expect(axios.delete).toHaveBeenCalledWith('/api/logs/1');
|
expect(mockDelete).toHaveBeenCalledWith('/api/logs/1');
|
||||||
expect(callOrder.indexOf('delete')).toBeLessThan(
|
expect(callOrder.indexOf('delete')).toBeLessThan(
|
||||||
callOrder.indexOf('get'),
|
callOrder.indexOf('get'),
|
||||||
);
|
);
|
||||||
@@ -183,37 +184,37 @@ describe('filesStore', () => {
|
|||||||
store.deleteFile('log', null),
|
store.deleteFile('log', null),
|
||||||
).resolves.toBeUndefined();
|
).resolves.toBeUndefined();
|
||||||
|
|
||||||
expect(axios.delete).not.toHaveBeenCalled();
|
expect(mockDelete).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('deletionRecord', () => {
|
describe('deletionRecord', () => {
|
||||||
it('deletes a deletion record', async () => {
|
it('deletes a deletion record', async () => {
|
||||||
axios.delete.mockResolvedValue({});
|
mockDelete.mockResolvedValue({});
|
||||||
|
|
||||||
await store.deletionRecord(5);
|
await store.deletionRecord(5);
|
||||||
|
|
||||||
expect(axios.delete).toHaveBeenCalledWith('/api/deletion/5');
|
expect(mockDelete).toHaveBeenCalledWith('/api/deletion/5');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('downloadFileCSV', () => {
|
describe('downloadFileCSV', () => {
|
||||||
it('downloads CSV for a log', async () => {
|
it('downloads CSV for a log', async () => {
|
||||||
axios.get.mockResolvedValue({ data: 'col1,col2\na,b' });
|
mockGet.mockResolvedValue({ data: 'col1,col2\na,b' });
|
||||||
|
|
||||||
window.URL.createObjectURL = vi.fn().mockReturnValue('blob:test');
|
window.URL.createObjectURL = vi.fn().mockReturnValue('blob:test');
|
||||||
window.URL.revokeObjectURL = vi.fn();
|
window.URL.revokeObjectURL = vi.fn();
|
||||||
|
|
||||||
await store.downloadFileCSV('log', 3, 'my-file');
|
await store.downloadFileCSV('log', 3, 'my-file');
|
||||||
|
|
||||||
expect(axios.get).toHaveBeenCalledWith('/api/logs/3/csv');
|
expect(mockGet).toHaveBeenCalledWith('/api/logs/3/csv');
|
||||||
expect(window.URL.revokeObjectURL).toHaveBeenCalledWith('blob:test');
|
expect(window.URL.revokeObjectURL).toHaveBeenCalledWith('blob:test');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns early for unsupported type', async () => {
|
it('returns early for unsupported type', async () => {
|
||||||
await store.downloadFileCSV('log-check', 3, 'file');
|
await store.downloadFileCSV('log-check', 3, 'file');
|
||||||
|
|
||||||
expect(axios.get).not.toHaveBeenCalled();
|
expect(mockGet).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -7,11 +7,16 @@ vi.mock('@/module/apiError.js', () => ({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
|
||||||
|
const { mockClientGet } = vi.hoisted(() => ({ mockClientGet: vi.fn() }));
|
||||||
|
vi.mock('@/api/client.js', () => ({
|
||||||
|
default: { get: mockClientGet },
|
||||||
|
}));
|
||||||
|
|
||||||
import useLoginStore from '@/stores/login.ts';
|
import useLoginStore from '@/stores/login.ts';
|
||||||
|
|
||||||
// Mock axios methods
|
// Mock axios methods (used for signIn/refreshToken which call plain axios)
|
||||||
vi.spyOn(axios, 'post').mockImplementation(vi.fn());
|
vi.spyOn(axios, 'post').mockImplementation(vi.fn());
|
||||||
vi.spyOn(axios, 'get').mockImplementation(vi.fn());
|
|
||||||
|
|
||||||
describe('loginStore', () => {
|
describe('loginStore', () => {
|
||||||
let store;
|
let store;
|
||||||
@@ -118,13 +123,13 @@ describe('loginStore', () => {
|
|||||||
|
|
||||||
describe('getUserData', () => {
|
describe('getUserData', () => {
|
||||||
it('stores user data on success', async () => {
|
it('stores user data on success', async () => {
|
||||||
axios.get.mockResolvedValue({
|
mockClientGet.mockResolvedValue({
|
||||||
data: { username: 'testuser', name: 'Test User' },
|
data: { username: 'testuser', name: 'Test User' },
|
||||||
});
|
});
|
||||||
|
|
||||||
await store.getUserData();
|
await store.getUserData();
|
||||||
|
|
||||||
expect(axios.get).toHaveBeenCalledWith('/api/my-account');
|
expect(mockClientGet).toHaveBeenCalledWith('/api/my-account');
|
||||||
expect(store.userData).toEqual({
|
expect(store.userData).toEqual({
|
||||||
username: 'testuser',
|
username: 'testuser',
|
||||||
name: 'Test User',
|
name: 'Test User',
|
||||||
@@ -134,7 +139,7 @@ describe('loginStore', () => {
|
|||||||
|
|
||||||
describe('checkLogin', () => {
|
describe('checkLogin', () => {
|
||||||
it('does not redirect on success', async () => {
|
it('does not redirect on success', async () => {
|
||||||
axios.get.mockResolvedValue({ data: {} });
|
mockClientGet.mockResolvedValue({ data: {} });
|
||||||
|
|
||||||
await store.checkLogin();
|
await store.checkLogin();
|
||||||
|
|
||||||
@@ -142,7 +147,7 @@ describe('loginStore', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('redirects to login on error', async () => {
|
it('redirects to login on error', async () => {
|
||||||
axios.get.mockRejectedValue(new Error('401'));
|
mockClientGet.mockRejectedValue(new Error('401'));
|
||||||
|
|
||||||
await store.checkLogin();
|
await store.checkLogin();
|
||||||
|
|
||||||
@@ -186,10 +191,6 @@ describe('loginStore', () => {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Should update axios default Authorization header
|
|
||||||
expect(axios.defaults.headers.common['Authorization'])
|
|
||||||
.toBe('Bearer new-access-token');
|
|
||||||
|
|
||||||
// Verify cookies were set with Secure flag
|
// Verify cookies were set with Secure flag
|
||||||
const cookieSetter = vi.spyOn(document, 'cookie', 'set');
|
const cookieSetter = vi.spyOn(document, 'cookie', 'set');
|
||||||
vi.clearAllMocks();
|
vi.clearAllMocks();
|
||||||
|
|||||||
@@ -5,18 +5,19 @@ vi.mock('@/module/apiError.js', () => ({
|
|||||||
default: vi.fn(),
|
default: vi.fn(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const { mockGet } = vi.hoisted(() => ({ mockGet: vi.fn() }));
|
||||||
|
vi.mock('@/api/client.js', () => ({
|
||||||
|
default: { get: mockGet },
|
||||||
|
}));
|
||||||
|
|
||||||
import usePerformanceStore from '@/stores/performance.js';
|
import usePerformanceStore from '@/stores/performance.js';
|
||||||
|
|
||||||
describe('performanceStore', () => {
|
describe('performanceStore', () => {
|
||||||
let store;
|
let store;
|
||||||
const mockAxios = {
|
|
||||||
get: vi.fn(),
|
|
||||||
};
|
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
setActivePinia(createPinia());
|
setActivePinia(createPinia());
|
||||||
store = usePerformanceStore();
|
store = usePerformanceStore();
|
||||||
store.$axios = mockAxios;
|
|
||||||
vi.clearAllMocks();
|
vi.clearAllMocks();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -33,28 +34,28 @@ describe('performanceStore', () => {
|
|||||||
describe('getPerformance', () => {
|
describe('getPerformance', () => {
|
||||||
it('fetches log performance data', async () => {
|
it('fetches log performance data', async () => {
|
||||||
const mockData = { time: { charts: [] }, freq: { charts: [] } };
|
const mockData = { time: { charts: [] }, freq: { charts: [] } };
|
||||||
mockAxios.get.mockResolvedValue({ data: mockData });
|
mockGet.mockResolvedValue({ data: mockData });
|
||||||
|
|
||||||
await store.getPerformance('log', 1);
|
await store.getPerformance('log', 1);
|
||||||
|
|
||||||
expect(mockAxios.get).toHaveBeenCalledWith(
|
expect(mockGet).toHaveBeenCalledWith(
|
||||||
'/api/logs/1/performance',
|
'/api/logs/1/performance',
|
||||||
);
|
);
|
||||||
expect(store.allPerformanceData).toEqual(mockData);
|
expect(store.allPerformanceData).toEqual(mockData);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('fetches filter performance data', async () => {
|
it('fetches filter performance data', async () => {
|
||||||
mockAxios.get.mockResolvedValue({ data: { time: {} } });
|
mockGet.mockResolvedValue({ data: { time: {} } });
|
||||||
|
|
||||||
await store.getPerformance('filter', 5);
|
await store.getPerformance('filter', 5);
|
||||||
|
|
||||||
expect(mockAxios.get).toHaveBeenCalledWith(
|
expect(mockGet).toHaveBeenCalledWith(
|
||||||
'/api/filters/5/performance',
|
'/api/filters/5/performance',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not throw on API failure', async () => {
|
it('does not throw on API failure', async () => {
|
||||||
mockAxios.get.mockRejectedValue(new Error('Network error'));
|
mockGet.mockRejectedValue(new Error('Network error'));
|
||||||
|
|
||||||
// Should not throw - apiError handles it
|
// Should not throw - apiError handles it
|
||||||
await expect(store.getPerformance('log', 1))
|
await expect(store.getPerformance('log', 1))
|
||||||
|
|||||||
Reference in New Issue
Block a user