chore: fix circleci on vite build (#10214)
- Switch to pnpm based build - Switch circleci from docker to machine to have more memory - Fix frontend and backend tests Fixes https://linear.app/chatwoot/issue/CW-3610/fix-circle-ci-for-vite-build --------- Co-authored-by: Shivam Mishra <scm.mymail@gmail.com> Co-authored-by: Pranav <pranavrajs@gmail.com> Co-authored-by: Pranav <pranav@chatwoot.com>
This commit is contained in:
@@ -1,16 +1,15 @@
|
||||
import { shallowMount, createLocalVue } from '@vue/test-utils';
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
import { createStore } from 'vuex';
|
||||
import { createRouter, createWebHistory } from 'vue-router';
|
||||
import portalMixin from '../portalMixin';
|
||||
import Vuex from 'vuex';
|
||||
import VueRouter from 'vue-router';
|
||||
const localVue = createLocalVue();
|
||||
localVue.use(Vuex);
|
||||
localVue.use(VueRouter);
|
||||
import ListAllArticles from '../../pages/portals/ListAllPortals.vue';
|
||||
|
||||
const router = new VueRouter({
|
||||
// Create router instance
|
||||
const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
routes: [
|
||||
{
|
||||
path: ':portalSlug/:locale/articles',
|
||||
path: '/:portalSlug/:locale/articles', // Add leading "/"
|
||||
name: 'list_all_locale_articles',
|
||||
component: ListAllArticles,
|
||||
},
|
||||
@@ -30,18 +29,21 @@ describe('portalMixin', () => {
|
||||
render() {},
|
||||
title: 'TestComponent',
|
||||
mixins: [portalMixin],
|
||||
router,
|
||||
};
|
||||
store = new Vuex.Store({ getters });
|
||||
wrapper = shallowMount(Component, { store, localVue });
|
||||
store = createStore({ getters });
|
||||
wrapper = shallowMount(Component, {
|
||||
global: {
|
||||
plugins: [store, router],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('return account id', () => {
|
||||
it('returns account id', () => {
|
||||
expect(wrapper.vm.accountId).toBe(1);
|
||||
});
|
||||
|
||||
it('returns article url', () => {
|
||||
router.push({
|
||||
it('returns article url', async () => {
|
||||
await router.push({
|
||||
name: 'list_all_locale_articles',
|
||||
params: { portalSlug: 'fur-rent', locale: 'en' },
|
||||
});
|
||||
@@ -50,24 +52,24 @@ describe('portalMixin', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('returns portal locale', () => {
|
||||
router.push({
|
||||
it('returns portal locale', async () => {
|
||||
await router.push({
|
||||
name: 'list_all_locale_articles',
|
||||
params: { portalSlug: 'fur-rent', locale: 'es' },
|
||||
});
|
||||
expect(wrapper.vm.portalSlug).toBe('fur-rent');
|
||||
});
|
||||
|
||||
it('returns portal slug', () => {
|
||||
router.push({
|
||||
it('returns portal slug', async () => {
|
||||
await router.push({
|
||||
name: 'list_all_locale_articles',
|
||||
params: { portalSlug: 'campaign', locale: 'es' },
|
||||
});
|
||||
expect(wrapper.vm.portalSlug).toBe('campaign');
|
||||
});
|
||||
|
||||
it('returns locale name', () => {
|
||||
router.push({
|
||||
it('returns locale name', async () => {
|
||||
await router.push({
|
||||
name: 'list_all_locale_articles',
|
||||
params: { portalSlug: 'fur-rent', locale: 'es' },
|
||||
});
|
||||
|
||||
@@ -128,6 +128,7 @@ export default {
|
||||
|
||||
<template>
|
||||
<transition name="popover-animation">
|
||||
<!-- eslint-disable-next-line vue/require-toggle-inside-transition -->
|
||||
<div
|
||||
class="min-w-[15rem] max-w-[22.5rem] p-6 overflow-y-auto border-l rtl:border-r rtl:border-l-0 border-solid border-slate-50 dark:border-slate-700"
|
||||
>
|
||||
|
||||
@@ -19,11 +19,9 @@ defineProps({
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- eslint-disable vue/no-unused-refs -->
|
||||
<!-- Added ref for writing specs -->
|
||||
<template>
|
||||
<div
|
||||
ref="reportMetricContainer"
|
||||
data-test-id="reportMetricContainer"
|
||||
class="p-4 m-0"
|
||||
:class="{
|
||||
'grayscale pointer-events-none opacity-30': disabled,
|
||||
@@ -32,17 +30,17 @@ defineProps({
|
||||
<h3
|
||||
class="flex items-center m-0 text-sm font-medium text-slate-800 dark:text-slate-100"
|
||||
>
|
||||
<span ref="reportMetricLabel">{{ label }}</span>
|
||||
<span data-test-id="reportMetricLabel">{{ label }}</span>
|
||||
<fluent-icon
|
||||
ref="reportMetricInfo"
|
||||
v-tooltip="infoText"
|
||||
data-test-id="reportMetricInfo"
|
||||
size="14"
|
||||
icon="info"
|
||||
class="text-slate-500 dark:text-slate-200 my-0 mx-1 mt-0.5"
|
||||
/>
|
||||
</h3>
|
||||
<h4
|
||||
ref="reportMetricValue"
|
||||
data-test-id="reportMetricValue"
|
||||
class="mt-1 mb-0 text-3xl font-thin text-slate-700 dark:text-slate-100"
|
||||
>
|
||||
{{ value }}
|
||||
|
||||
@@ -1,17 +1,7 @@
|
||||
import { shallowMount, createLocalVue } from '@vue/test-utils';
|
||||
import Vuex from 'vuex';
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
import { createStore } from 'vuex';
|
||||
import CsatMetrics from '../CsatMetrics.vue';
|
||||
|
||||
const localVue = createLocalVue();
|
||||
localVue.use(Vuex);
|
||||
|
||||
const mountParams = {
|
||||
mocks: {
|
||||
$t: msg => msg,
|
||||
},
|
||||
stubs: ['csat-metric-card', 'woot-horizontal-bar'],
|
||||
};
|
||||
|
||||
describe('CsatMetrics.vue', () => {
|
||||
let getters;
|
||||
let store;
|
||||
@@ -21,20 +11,33 @@ describe('CsatMetrics.vue', () => {
|
||||
beforeEach(() => {
|
||||
getters = {
|
||||
'csat/getMetrics': () => ({ totalResponseCount: 100 }),
|
||||
'csat/getRatingPercentage': () => ({ 1: 10, 2: 20, 3: 30, 4: 30, 5: 10 }),
|
||||
'csat/getRatingPercentage': () => ({
|
||||
1: 10,
|
||||
2: 20,
|
||||
3: 30,
|
||||
4: 30,
|
||||
5: 10,
|
||||
}),
|
||||
'csat/getSatisfactionScore': () => 85,
|
||||
'csat/getResponseRate': () => 90,
|
||||
};
|
||||
|
||||
store = new Vuex.Store({
|
||||
store = createStore({
|
||||
getters,
|
||||
});
|
||||
|
||||
wrapper = shallowMount(CsatMetrics, {
|
||||
store,
|
||||
localVue,
|
||||
propsData: { filters },
|
||||
...mountParams,
|
||||
global: {
|
||||
plugins: [store], // Ensure the store is injected here
|
||||
mocks: {
|
||||
$t: msg => msg, // mock translation function
|
||||
},
|
||||
stubs: {
|
||||
CsatMetricCard: '<csat-metric-card/>',
|
||||
BarChart: '<woot-horizontal-bar/>',
|
||||
},
|
||||
},
|
||||
props: { filters },
|
||||
});
|
||||
});
|
||||
|
||||
@@ -54,13 +57,11 @@ describe('CsatMetrics.vue', () => {
|
||||
});
|
||||
|
||||
it('hides report card if rating filter is enabled', () => {
|
||||
expect(wrapper.find({ ref: 'csatHorizontalBarChart' }).exists()).toBe(
|
||||
false
|
||||
);
|
||||
expect(wrapper.html()).not.toContain('bar-chart-stub');
|
||||
});
|
||||
|
||||
it('shows report card if rating filter is not enabled', async () => {
|
||||
await wrapper.setProps({ filters: {} });
|
||||
expect(wrapper.find({ ref: 'csatHorizontalBarChart' }).exists()).toBe(true);
|
||||
expect(wrapper.html()).toContain('bar-chart-stub');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
import { shallowMount, createLocalVue } from '@vue/test-utils';
|
||||
import Vuex from 'vuex';
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
import { createStore } from 'vuex';
|
||||
import ReportsFiltersAgents from '../../Filters/Agents.vue';
|
||||
|
||||
const localVue = createLocalVue();
|
||||
localVue.use(Vuex);
|
||||
|
||||
const mockStore = new Vuex.Store({
|
||||
const mockStore = createStore({
|
||||
modules: {
|
||||
agents: {
|
||||
namespaced: true,
|
||||
@@ -23,25 +20,26 @@ const mockStore = new Vuex.Store({
|
||||
});
|
||||
|
||||
const mountParams = {
|
||||
localVue,
|
||||
store: mockStore,
|
||||
mocks: {
|
||||
$t: msg => msg,
|
||||
global: {
|
||||
plugins: [mockStore],
|
||||
mocks: {
|
||||
$t: msg => msg,
|
||||
},
|
||||
stubs: ['multiselect'],
|
||||
},
|
||||
stubs: ['multiselect'],
|
||||
};
|
||||
|
||||
describe('ReportsFiltersAgents.vue', () => {
|
||||
it('emits "agents-filter-selection" event when handleInput is called', () => {
|
||||
it('emits "agents-filter-selection" event when handleInput is called', async () => {
|
||||
const wrapper = shallowMount(ReportsFiltersAgents, mountParams);
|
||||
|
||||
const selectedAgents = [
|
||||
{ id: 1, name: 'Agent 1' },
|
||||
{ id: 2, name: 'Agent 2' },
|
||||
];
|
||||
wrapper.setData({ selectedOptions: selectedAgents });
|
||||
await wrapper.setData({ selectedOptions: selectedAgents });
|
||||
|
||||
wrapper.vm.handleInput();
|
||||
await wrapper.vm.handleInput();
|
||||
|
||||
expect(wrapper.emitted('agentsFilterSelection')).toBeTruthy();
|
||||
expect(wrapper.emitted('agentsFilterSelection')[0]).toEqual([
|
||||
|
||||
@@ -3,10 +3,12 @@ import ReportsFiltersDateGroupBy from '../../Filters/DateGroupBy.vue';
|
||||
import { GROUP_BY_OPTIONS } from '../../../constants';
|
||||
|
||||
const mountParams = {
|
||||
mocks: {
|
||||
$t: msg => msg,
|
||||
global: {
|
||||
mocks: {
|
||||
$t: msg => msg,
|
||||
},
|
||||
stubs: ['multiselect'],
|
||||
},
|
||||
stubs: ['multiselect'],
|
||||
};
|
||||
|
||||
describe('ReportsFiltersDateGroupBy.vue', () => {
|
||||
|
||||
@@ -3,10 +3,12 @@ import ReportFiltersDateRange from '../../Filters/DateRange.vue';
|
||||
import { DATE_RANGE_OPTIONS } from '../../../constants';
|
||||
|
||||
const mountParams = {
|
||||
mocks: {
|
||||
$t: msg => msg,
|
||||
global: {
|
||||
mocks: {
|
||||
$t: msg => msg,
|
||||
},
|
||||
stubs: ['multiselect'],
|
||||
},
|
||||
stubs: ['multiselect'],
|
||||
};
|
||||
|
||||
describe('ReportFiltersDateRange.vue', () => {
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
import { shallowMount, createLocalVue } from '@vue/test-utils';
|
||||
import Vuex from 'vuex';
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
import { createStore } from 'vuex';
|
||||
import ReportsFiltersInboxes from '../../Filters/Inboxes.vue';
|
||||
|
||||
const localVue = createLocalVue();
|
||||
localVue.use(Vuex);
|
||||
|
||||
const mountParams = {
|
||||
mocks: {
|
||||
$t: msg => msg,
|
||||
global: {
|
||||
mocks: {
|
||||
$t: msg => msg,
|
||||
},
|
||||
stubs: ['multiselect'],
|
||||
},
|
||||
stubs: ['multiselect'],
|
||||
};
|
||||
|
||||
describe('ReportsFiltersInboxes.vue', () => {
|
||||
@@ -30,7 +29,7 @@ describe('ReportsFiltersInboxes.vue', () => {
|
||||
},
|
||||
};
|
||||
|
||||
store = new Vuex.Store({
|
||||
store = createStore({
|
||||
modules: {
|
||||
inboxes: inboxesModule,
|
||||
},
|
||||
@@ -39,24 +38,26 @@ describe('ReportsFiltersInboxes.vue', () => {
|
||||
|
||||
it('dispatches "inboxes/get" action when component is mounted', () => {
|
||||
shallowMount(ReportsFiltersInboxes, {
|
||||
store,
|
||||
localVue,
|
||||
...mountParams,
|
||||
global: {
|
||||
plugins: [store],
|
||||
...mountParams.global,
|
||||
},
|
||||
});
|
||||
expect(inboxesModule.actions.get).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('emits "inbox-filter-selection" event when handleInput is called', () => {
|
||||
it('emits "inbox-filter-selection" event when handleInput is called', async () => {
|
||||
const wrapper = shallowMount(ReportsFiltersInboxes, {
|
||||
store,
|
||||
localVue,
|
||||
...mountParams,
|
||||
global: {
|
||||
plugins: [store],
|
||||
...mountParams.global,
|
||||
},
|
||||
});
|
||||
|
||||
const selectedInbox = { id: 1, name: 'Inbox 1' };
|
||||
wrapper.setData({ selectedOption: selectedInbox });
|
||||
await wrapper.setData({ selectedOption: selectedInbox });
|
||||
|
||||
wrapper.vm.handleInput();
|
||||
await wrapper.vm.handleInput();
|
||||
|
||||
expect(wrapper.emitted('inboxFilterSelection')).toBeTruthy();
|
||||
expect(wrapper.emitted('inboxFilterSelection')[0]).toEqual([selectedInbox]);
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
import { shallowMount, createLocalVue } from '@vue/test-utils';
|
||||
import Vuex from 'vuex';
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
import { createStore } from 'vuex';
|
||||
import ReportsFiltersLabels from '../../Filters/Labels.vue';
|
||||
|
||||
const localVue = createLocalVue();
|
||||
localVue.use(Vuex);
|
||||
|
||||
const mountParams = {
|
||||
mocks: {
|
||||
$t: msg => msg,
|
||||
global: {
|
||||
mocks: {
|
||||
$t: msg => msg,
|
||||
},
|
||||
stubs: ['multiselect'],
|
||||
},
|
||||
stubs: ['multiselect'],
|
||||
};
|
||||
|
||||
describe('ReportsFiltersLabels.vue', () => {
|
||||
@@ -30,7 +29,7 @@ describe('ReportsFiltersLabels.vue', () => {
|
||||
},
|
||||
};
|
||||
|
||||
store = new Vuex.Store({
|
||||
store = createStore({
|
||||
modules: {
|
||||
labels: labelsModule,
|
||||
},
|
||||
@@ -39,24 +38,26 @@ describe('ReportsFiltersLabels.vue', () => {
|
||||
|
||||
it('dispatches "labels/get" action when component is mounted', () => {
|
||||
shallowMount(ReportsFiltersLabels, {
|
||||
store,
|
||||
localVue,
|
||||
...mountParams,
|
||||
global: {
|
||||
plugins: [store],
|
||||
...mountParams.global,
|
||||
},
|
||||
});
|
||||
expect(labelsModule.actions.get).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('emits "labels-filter-selection" event when handleInput is called', () => {
|
||||
it('emits "labels-filter-selection" event when handleInput is called', async () => {
|
||||
const wrapper = shallowMount(ReportsFiltersLabels, {
|
||||
store,
|
||||
localVue,
|
||||
...mountParams,
|
||||
global: {
|
||||
plugins: [store],
|
||||
...mountParams.global,
|
||||
},
|
||||
});
|
||||
|
||||
const selectedLabel = { id: 1, title: 'Label 1', color: 'red' };
|
||||
wrapper.setData({ selectedOption: selectedLabel });
|
||||
await wrapper.setData({ selectedOption: selectedLabel });
|
||||
|
||||
wrapper.vm.handleInput();
|
||||
await wrapper.vm.handleInput();
|
||||
|
||||
expect(wrapper.emitted('labelsFilterSelection')).toBeTruthy();
|
||||
expect(wrapper.emitted('labelsFilterSelection')[0]).toEqual([
|
||||
|
||||
@@ -1,27 +1,26 @@
|
||||
import { shallowMount, createLocalVue } from '@vue/test-utils';
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
import ReportFiltersRatings from '../../Filters/Ratings.vue';
|
||||
import { CSAT_RATINGS } from 'shared/constants/messages';
|
||||
|
||||
const mountParams = {
|
||||
mocks: {
|
||||
$t: msg => msg,
|
||||
global: {
|
||||
mocks: {
|
||||
$t: msg => msg,
|
||||
},
|
||||
stubs: ['multiselect'],
|
||||
},
|
||||
stubs: ['multiselect'],
|
||||
};
|
||||
|
||||
const localVue = createLocalVue();
|
||||
|
||||
describe('ReportFiltersRatings.vue', () => {
|
||||
it('emits "rating-filter-selection" event when handleInput is called', () => {
|
||||
it('emits "rating-filter-selection" event when handleInput is called', async () => {
|
||||
const wrapper = shallowMount(ReportFiltersRatings, {
|
||||
localVue,
|
||||
...mountParams,
|
||||
});
|
||||
|
||||
const selectedRating = { value: 1, label: 'Rating 1' };
|
||||
wrapper.setData({ selectedOption: selectedRating });
|
||||
await wrapper.setData({ selectedOption: selectedRating });
|
||||
|
||||
wrapper.vm.handleInput(selectedRating);
|
||||
await wrapper.vm.handleInput(selectedRating);
|
||||
|
||||
expect(wrapper.emitted('ratingFilterSelection')).toBeTruthy();
|
||||
expect(wrapper.emitted('ratingFilterSelection')[0]).toEqual([
|
||||
@@ -31,7 +30,6 @@ describe('ReportFiltersRatings.vue', () => {
|
||||
|
||||
it('initializes options correctly', () => {
|
||||
const wrapper = shallowMount(ReportFiltersRatings, {
|
||||
localVue,
|
||||
...mountParams,
|
||||
});
|
||||
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
import { shallowMount, createLocalVue } from '@vue/test-utils';
|
||||
import Vuex from 'vuex';
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
import { createStore } from 'vuex';
|
||||
import ReportsFiltersTeams from '../../Filters/Teams.vue';
|
||||
|
||||
const localVue = createLocalVue();
|
||||
localVue.use(Vuex);
|
||||
|
||||
const mountParams = {
|
||||
mocks: {
|
||||
$t: msg => msg,
|
||||
global: {
|
||||
mocks: {
|
||||
$t: msg => msg,
|
||||
},
|
||||
stubs: ['multiselect'],
|
||||
},
|
||||
stubs: ['multiselect'],
|
||||
};
|
||||
|
||||
describe('ReportsFiltersTeams.vue', () => {
|
||||
@@ -30,7 +29,7 @@ describe('ReportsFiltersTeams.vue', () => {
|
||||
},
|
||||
};
|
||||
|
||||
store = new Vuex.Store({
|
||||
store = createStore({
|
||||
modules: {
|
||||
teams: teamsModule,
|
||||
},
|
||||
@@ -39,21 +38,25 @@ describe('ReportsFiltersTeams.vue', () => {
|
||||
|
||||
it('dispatches "teams/get" action when component is mounted', () => {
|
||||
shallowMount(ReportsFiltersTeams, {
|
||||
store,
|
||||
localVue,
|
||||
...mountParams,
|
||||
global: {
|
||||
plugins: [store],
|
||||
...mountParams,
|
||||
},
|
||||
});
|
||||
expect(teamsModule.actions.get).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('emits "team-filter-selection" event when handleInput is called', () => {
|
||||
it('emits "team-filter-selection" event when handleInput is called', async () => {
|
||||
const wrapper = shallowMount(ReportsFiltersTeams, {
|
||||
store,
|
||||
localVue,
|
||||
...mountParams,
|
||||
global: {
|
||||
plugins: [store],
|
||||
...mountParams,
|
||||
},
|
||||
});
|
||||
wrapper.setData({ selectedOption: { id: 1, name: 'Team 1' } });
|
||||
wrapper.vm.handleInput();
|
||||
|
||||
await wrapper.setData({ selectedOption: { id: 1, name: 'Team 1' } });
|
||||
await wrapper.vm.handleInput();
|
||||
|
||||
expect(wrapper.emitted('teamFilterSelection')).toBeTruthy();
|
||||
expect(wrapper.emitted('teamFilterSelection')[0]).toEqual([
|
||||
{ id: 1, name: 'Team 1' },
|
||||
|
||||
@@ -1,34 +1,36 @@
|
||||
import { createLocalVue, shallowMount } from '@vue/test-utils';
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
import ReportMetricCard from '../ReportMetricCard.vue';
|
||||
|
||||
import FloatingVue from 'floating-vue';
|
||||
|
||||
const localVue = createLocalVue();
|
||||
localVue.use(FloatingVue);
|
||||
|
||||
describe('ReportMetricCard.vue', () => {
|
||||
const globalConfig = {
|
||||
global: {
|
||||
stubs: {
|
||||
'fluent-icon': true, // Replace FluentIcon with a stub
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
it('renders props correctly', () => {
|
||||
const label = 'Total Responses';
|
||||
const value = '100';
|
||||
const infoText = 'Total number of responses';
|
||||
const wrapper = shallowMount(ReportMetricCard, {
|
||||
propsData: { label, value, infoText },
|
||||
localVue,
|
||||
stubs: ['fluent-icon'],
|
||||
props: { label, value, infoText },
|
||||
...globalConfig,
|
||||
});
|
||||
|
||||
expect(wrapper.find({ ref: 'reportMetricLabel' }).text()).toMatch(label);
|
||||
expect(wrapper.find({ ref: 'reportMetricValue' }).text()).toMatch(value);
|
||||
expect(wrapper.find({ ref: 'reportMetricInfo' }).classes()).toContain(
|
||||
'has-tooltip'
|
||||
expect(wrapper.find('[data-test-id="reportMetricLabel"]').text()).toMatch(
|
||||
label
|
||||
);
|
||||
expect(wrapper.find('[data-test-id="reportMetricValue"]').text()).toMatch(
|
||||
value
|
||||
);
|
||||
});
|
||||
|
||||
it('adds disabled class when disabled prop is true', () => {
|
||||
const wrapper = shallowMount(ReportMetricCard, {
|
||||
propsData: { label: '', value: '', infoText: '', disabled: true },
|
||||
localVue,
|
||||
stubs: ['fluent-icon'],
|
||||
props: { label: '', value: '', infoText: '', disabled: true },
|
||||
...globalConfig,
|
||||
});
|
||||
|
||||
expect(wrapper.classes().join(' ')).toContain(
|
||||
@@ -38,13 +40,12 @@ describe('ReportMetricCard.vue', () => {
|
||||
|
||||
it('does not add disabled class when disabled prop is false', () => {
|
||||
const wrapper = shallowMount(ReportMetricCard, {
|
||||
propsData: { label: '', value: '', infoText: '', disabled: false },
|
||||
localVue,
|
||||
stubs: ['fluent-icon'],
|
||||
props: { label: '', value: '', infoText: '', disabled: false },
|
||||
...globalConfig,
|
||||
});
|
||||
|
||||
expect(
|
||||
wrapper.find({ ref: 'reportMetricContainer' }).classes().join(' ')
|
||||
wrapper.find('[data-test-id="reportMetricContainer"]').classes().join(' ')
|
||||
).not.toContain('grayscale pointer-events-none opacity-30');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
exports[`CsatMetrics.vue > computes response count correctly 1`] = `
|
||||
"<div class="flex-col lg:flex-row flex flex-wrap mx-0 bg-white dark:bg-slate-800 rounded-[4px] p-4 mb-5 border border-solid border-slate-75 dark:border-slate-700">
|
||||
<csatmetriccard-stub label="CSAT_REPORTS.METRIC.TOTAL_RESPONSES.LABEL" value="100" infotext="CSAT_REPORTS.METRIC.TOTAL_RESPONSES.TOOLTIP" class="xs:w-full sm:max-w-[50%] lg:w-1/6 lg:max-w-[16%]"></csatmetriccard-stub>
|
||||
<csatmetriccard-stub label="CSAT_REPORTS.METRIC.SATISFACTION_SCORE.LABEL" value="--" infotext="CSAT_REPORTS.METRIC.SATISFACTION_SCORE.TOOLTIP" disabled="true" class="xs:w-full sm:max-w-[50%] lg:w-1/6 lg:max-w-[16%]"></csatmetriccard-stub>
|
||||
<csatmetriccard-stub label="CSAT_REPORTS.METRIC.RESPONSE_RATE.LABEL" value="90%" infotext="CSAT_REPORTS.METRIC.RESPONSE_RATE.TOOLTIP" class="xs:w-full sm:max-w-[50%] lg:w-1/6 lg:max-w-[16%]"></csatmetriccard-stub>
|
||||
<!---->
|
||||
<csat-metric-card-stub label="CSAT_REPORTS.METRIC.TOTAL_RESPONSES.LABEL" infotext="CSAT_REPORTS.METRIC.TOTAL_RESPONSES.TOOLTIP" disabled="false" class="xs:w-full sm:max-w-[50%] lg:w-1/6 lg:max-w-[16%]" value="100"></csat-metric-card-stub>
|
||||
<csat-metric-card-stub label="CSAT_REPORTS.METRIC.SATISFACTION_SCORE.LABEL" infotext="CSAT_REPORTS.METRIC.SATISFACTION_SCORE.TOOLTIP" disabled="true" class="xs:w-full sm:max-w-[50%] lg:w-1/6 lg:max-w-[16%]" value="--"></csat-metric-card-stub>
|
||||
<csat-metric-card-stub label="CSAT_REPORTS.METRIC.RESPONSE_RATE.LABEL" infotext="CSAT_REPORTS.METRIC.RESPONSE_RATE.TOOLTIP" disabled="false" class="xs:w-full sm:max-w-[50%] lg:w-1/6 lg:max-w-[16%]" value="90%"></csat-metric-card-stub>
|
||||
<!--v-if-->
|
||||
</div>"
|
||||
`;
|
||||
|
||||
@@ -2,7 +2,7 @@ import { createRouter, createWebHistory } from 'vue-router';
|
||||
|
||||
import { frontendURL } from '../helper/URLHelper';
|
||||
import dashboard from './dashboard/dashboard.routes';
|
||||
import store from '../store';
|
||||
import store from 'dashboard/store';
|
||||
import { validateLoggedInRoutes } from '../helper/routeHelpers';
|
||||
import AnalyticsHelper from '../helper/AnalyticsHelper';
|
||||
import { buildPermissionsFromRouter } from '../helper/permissionsHelper';
|
||||
@@ -16,8 +16,8 @@ export const validateAuthenticateRoutePermission = (to, next) => {
|
||||
const { isLoggedIn, getCurrentUser: user } = store.getters;
|
||||
|
||||
if (!isLoggedIn) {
|
||||
window.location = '/app/login';
|
||||
return '/app/login';
|
||||
window.location.assign('/app/login');
|
||||
return '';
|
||||
}
|
||||
|
||||
if (!to.name) {
|
||||
|
||||
@@ -1,79 +1,105 @@
|
||||
import { validateAuthenticateRoutePermission } from './index';
|
||||
import store from '../store'; // This import will be mocked
|
||||
import { vi } from 'vitest';
|
||||
|
||||
// Mock the store module
|
||||
vi.mock('../store', () => ({
|
||||
default: {
|
||||
getters: {
|
||||
isLoggedIn: false,
|
||||
getCurrentUser: {
|
||||
account_id: null,
|
||||
id: null,
|
||||
accounts: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
describe('#validateAuthenticateRoutePermission', () => {
|
||||
describe(`when route is protected`, () => {
|
||||
describe(`when user not logged in`, () => {
|
||||
it(`should redirect to login`, () => {
|
||||
const to = { name: 'some-protected-route', params: { accountId: 1 } };
|
||||
const next = vi.fn();
|
||||
const getters = {
|
||||
isLoggedIn: false,
|
||||
getCurrentUser: {
|
||||
account_id: null,
|
||||
id: null,
|
||||
accounts: [],
|
||||
let next;
|
||||
|
||||
beforeEach(() => {
|
||||
next = vi.fn(); // Mock the next function
|
||||
});
|
||||
|
||||
describe('when user is not logged in', () => {
|
||||
it('should redirect to login', () => {
|
||||
const to = { name: 'some-protected-route', params: { accountId: 1 } };
|
||||
|
||||
// Mock the store to simulate user not logged in
|
||||
store.getters.isLoggedIn = false;
|
||||
|
||||
// Mock window.location.assign
|
||||
const mockAssign = vi.fn();
|
||||
delete window.location;
|
||||
window.location = { assign: mockAssign };
|
||||
|
||||
validateAuthenticateRoutePermission(to, next);
|
||||
|
||||
expect(mockAssign).toHaveBeenCalledWith('/app/login');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when user is logged in', () => {
|
||||
beforeEach(() => {
|
||||
// Mock the store's getter for a logged-in user
|
||||
store.getters.isLoggedIn = true;
|
||||
store.getters.getCurrentUser = {
|
||||
account_id: 1,
|
||||
id: 1,
|
||||
accounts: [
|
||||
{
|
||||
id: 1,
|
||||
role: 'agent',
|
||||
permissions: ['agent'],
|
||||
status: 'active',
|
||||
},
|
||||
],
|
||||
};
|
||||
});
|
||||
|
||||
describe('when route is not accessible to current user', () => {
|
||||
it('should redirect to dashboard', () => {
|
||||
const to = {
|
||||
name: 'general_settings_index',
|
||||
params: { accountId: 1 },
|
||||
meta: { permissions: ['administrator'] },
|
||||
};
|
||||
|
||||
expect(validateAuthenticateRoutePermission(to, next, { getters })).toBe(
|
||||
'/app/login'
|
||||
);
|
||||
validateAuthenticateRoutePermission(to, next);
|
||||
|
||||
expect(next).toHaveBeenCalledWith('/app/accounts/1/dashboard');
|
||||
});
|
||||
});
|
||||
describe(`when user is logged in`, () => {
|
||||
describe(`when route is not accessible to current user`, () => {
|
||||
it(`should redirect to dashboard`, () => {
|
||||
const to = {
|
||||
name: 'general_settings_index',
|
||||
params: { accountId: 1 },
|
||||
meta: { permissions: ['administrator'] },
|
||||
};
|
||||
const next = vi.fn();
|
||||
const getters = {
|
||||
isLoggedIn: true,
|
||||
getCurrentUser: {
|
||||
account_id: 1,
|
||||
|
||||
describe('when route is accessible to current user', () => {
|
||||
beforeEach(() => {
|
||||
// Adjust store getters to reflect the user has admin permissions
|
||||
store.getters.getCurrentUser = {
|
||||
account_id: 1,
|
||||
id: 1,
|
||||
accounts: [
|
||||
{
|
||||
id: 1,
|
||||
accounts: [
|
||||
{
|
||||
permissions: ['agent'],
|
||||
id: 1,
|
||||
role: 'agent',
|
||||
status: 'active',
|
||||
},
|
||||
],
|
||||
role: 'administrator',
|
||||
permissions: ['administrator'],
|
||||
status: 'active',
|
||||
},
|
||||
};
|
||||
validateAuthenticateRoutePermission(to, next, { getters });
|
||||
expect(next).toHaveBeenCalledWith('/app/accounts/1/dashboard');
|
||||
});
|
||||
],
|
||||
};
|
||||
});
|
||||
describe(`when route is accessible to current user`, () => {
|
||||
it(`should go there`, () => {
|
||||
const to = {
|
||||
name: 'general_settings_index',
|
||||
params: { accountId: 1 },
|
||||
meta: { permissions: ['administrator'] },
|
||||
};
|
||||
const next = vi.fn();
|
||||
const getters = {
|
||||
isLoggedIn: true,
|
||||
getCurrentUser: {
|
||||
account_id: 1,
|
||||
id: 1,
|
||||
accounts: [
|
||||
{
|
||||
id: 1,
|
||||
role: 'administrator',
|
||||
permissions: ['administrator'],
|
||||
status: 'active',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
validateAuthenticateRoutePermission(to, next, { getters });
|
||||
expect(next).toHaveBeenCalledWith();
|
||||
});
|
||||
|
||||
it('should go to the intended route', () => {
|
||||
const to = {
|
||||
name: 'general_settings_index',
|
||||
params: { accountId: 1 },
|
||||
meta: { permissions: ['administrator'] },
|
||||
};
|
||||
|
||||
validateAuthenticateRoutePermission(to, next);
|
||||
|
||||
expect(next).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user