Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CHATS-2333] - Increase tests coverage #214

Merged
merged 9 commits into from
Dec 30, 2024
7 changes: 6 additions & 1 deletion src/components/insights/Layout/HeaderDashboardSettings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,21 @@
type="secondary"
size="large"
iconCenter="tune"
data-testid="options-dashboard-button"
/>
</template>
<UnnnicDropdownItem @click="showEditDashboard = true">
<UnnnicDropdownItem
data-testid="edit-dashboard-button"
@click="showEditDashboard = true"
>
{{ $t('edit_dashboard.title') }}
</UnnnicDropdownItem>
</UnnnicDropdown>
<DrawerDashboardConfig
v-if="showEditDashboard"
v-model="showEditDashboard"
:dashboard="currentDashboard"
data-testid="edit-dashboard-drawer"
@close="showEditDashboard = false"
/>
</template>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { describe, it, expect, beforeEach } from 'vitest';
import { mount } from '@vue/test-utils';
import { createStore } from 'vuex';
import HeaderDashboardSettings from '../HeaderDashboardSettings.vue';
import DrawerDashboardConfig from '../../dashboards/DrawerDashboardConfig.vue';

describe('HeaderDashboardSettings.vue', () => {
let store;
let wrapper;

beforeEach(() => {
store = createStore({
modules: {
dashboards: {
namespaced: true,
state: {
currentDashboard: {
uuid: '123',
name: 'Dashboard 1',
is_editable: true,
},
},
},
},
});
wrapper = mount(HeaderDashboardSettings, {
global: {
plugins: [store],
components: { DrawerDashboardConfig },
},
});
});

it('renders dropdown trigger when dashboard is editable', () => {
const dropdownTrigger = wrapper.findComponent({ name: 'UnnnicButton' });
expect(dropdownTrigger.exists()).toBe(true);
});

it('shows DrawerDashboardConfig when "showEditDashboard" is true', async () => {
expect(
wrapper.findComponent('[data-testid="edit-dashboard-drawer"]').exists(),
).toBe(false);

const optionMenuButton = wrapper.findComponent(
'[data-testid="options-dashboard-button"]',
);

await optionMenuButton.trigger('click');

const dropdownItem = wrapper.findComponent(
'[data-testid="edit-dashboard-button"]',
);

await dropdownItem.trigger('click');

expect(wrapper.vm.showEditDashboard).toBe(true);
});

it('closes DrawerDashboardConfig when close event is emitted', async () => {
const optionMenuButton = wrapper.findComponent(
'[data-testid="options-dashboard-button"]',
);

await optionMenuButton.trigger('click');

const dropdownItem = wrapper.findComponent(
'[data-testid="edit-dashboard-button"]',
);

await dropdownItem.trigger('click');

expect(wrapper.findComponent(DrawerDashboardConfig).exists()).toBe(true);

const drawerConfig = wrapper.findComponent(DrawerDashboardConfig);
await drawerConfig.vm.$emit('close');

expect(wrapper.findComponent(DrawerDashboardConfig).exists()).toBe(false);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { describe, it, expect } from 'vitest';

import { mount, config } from '@vue/test-utils';

import { createI18n } from 'vue-i18n';
import en from '@/locales/en.json';
import UnnnicSystem from '@/utils/plugins/UnnnicSystem';

const i18n = createI18n({
legacy: false,
locale: 'en',
messages: { en },
fallbackWarn: false,
missingWarn: false,
});

config.global.plugins = [i18n, UnnnicSystem];

import SkeletonHorizontalBarChart from '../SkeletonHorizontalBarChart.vue';

describe('SkeletonHorizontalBarChart', () => {
const BAR_HEIGHT = 48;

it('renders correctly when props are valid', () => {
const wrapper = mount(SkeletonHorizontalBarChart, {
props: { width: 300, height: 480 },
});

const totalBars = Math.floor(480 / BAR_HEIGHT);
expect(wrapper.findAll('.skeleton-h-bar-container__bar')).toHaveLength(
totalBars,
);
});

it('applies the correct styles and structure', () => {
const wrapper = mount(SkeletonHorizontalBarChart, {
props: { width: 300, height: 480 },
});

expect(wrapper.classes()).toContain('skeleton-h-bar-container');
expect(
wrapper.findAll('.skeleton-h-bar-container__bar').length,
).toBeGreaterThan(0);

expect(
wrapper.findComponent({ name: 'UnnnicSkeletonLoading' }).exists(),
).toBe(true);
});
});
7 changes: 6 additions & 1 deletion src/components/insights/dashboards/ModalDeleteDashboard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,21 @@
showActionsDivider
showCloseIcon
size="sm"
data-testid="modal-delete-dashboard"
@update:model-value="!$event ? close() : {}"
@primary-button-click="deleteDashboard"
>
<p class="delete-notice">
<p
class="delete-notice"
data-testid="delete-notice"
>
{{ $t('delete_dashboard.notice') }}
</p>
<UnnnicLabel :label="$t('confirmation')" />
<UnnnicInput
v-model="dashboardName"
:placeholder="dashboard.name"
data-testid="input-dashboard-name"
/>
</UnnnicModalDialog>
</template>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { mount } from '@vue/test-utils';
import Dashboards from '@/services/api/resources/dashboards';
import { createStore } from 'vuex';

import unnnic from '@weni/unnnic-system';

import ModalDeleteDashboard from '../ModalDeleteDashboard.vue';

vi.mock('@/services/api/resources/dashboards');

describe('ModalDeleteDashboard', () => {
let store;
let wrapper;
const mockDashboard = {
uuid: '123',
name: 'Test Dashboard',
};

beforeEach(() => {
store = createStore({
modules: {
dashboards: {
namespaced: true,
state: {
dashboards: [mockDashboard],
},
getters: {
dashboardDefault: () => mockDashboard,
},
mutations: {
SET_DASHBOARDS: vi.fn(),
},
},
},
});

Dashboards.deleteDashboard.mockResolvedValue();

wrapper = mount(ModalDeleteDashboard, {
props: { modelValue: true, dashboard: mockDashboard },
global: { plugins: [store] },
});
});

it('renders correctly with required props', () => {
expect(wrapper.find('[data-testid="delete-notice"]').text()).toContain(
wrapper.vm.$t('delete_dashboard.notice'),
);
expect(
wrapper.findComponent('[data-testid="modal-delete-dashboard"]').exists(),
).toBe(true);
});

it('enables primary button only if dashboard name matches', async () => {
const input = wrapper.findComponent('[data-testid="input-dashboard-name"]');

const deleteButton = wrapper.find('[data-testid="primary-button"]');

expect(deleteButton.attributes('disabled')).toBeDefined();

await input.setValue('Test Dashboard');

expect(deleteButton.attributes('disabled')).toBeUndefined();
});

it('calls deleteDashboard on primary button click', async () => {
const input = wrapper.findComponent('[data-testid="input-dashboard-name"]');
const deleteButton = wrapper.find('[data-testid="primary-button"]');

await input.setValue('Test Dashboard');
await deleteButton.trigger('click');

expect(Dashboards.deleteDashboard).toHaveBeenCalledWith(mockDashboard.uuid);
});

it('shows success alert and updates state on successful deletion', async () => {
const setDashboards = vi.spyOn(wrapper.vm, 'setDashboards');

const input = wrapper.findComponent('[data-testid="input-dashboard-name"]');
const deleteButton = wrapper.find('[data-testid="primary-button"]');

await input.setValue('Test Dashboard');
await deleteButton.trigger('click');

expect(setDashboards).toHaveBeenCalledWith([]);
});

it('shows error alert on failed deletion', async () => {
const callAlertSpy = vi.spyOn(unnnic, 'unnnicCallAlert');
Dashboards.deleteDashboard.mockRejectedValueOnce(new Error('Failed'));

const input = wrapper.findComponent('[data-testid="input-dashboard-name"]');
const deleteButton = wrapper.find('[data-testid="primary-button"]');

await input.setValue('Test Dashboard');
await deleteButton.trigger('click');

expect(Dashboards.deleteDashboard).toHaveBeenCalled();

expect(callAlertSpy).toHaveBeenCalledWith({
props: {
text: wrapper.vm.$t('delete_dashboard.alert.error'),
type: 'error',
},
seconds: 5,
});
});

it('closes modal and emits close event when secondary button is clicked', async () => {
const cancelButton = wrapper.find('[data-testid="secondary-button"]');

await cancelButton.trigger('click');

expect(wrapper.emitted('close')).toBeTruthy();
});
});
2 changes: 2 additions & 0 deletions src/components/insights/drawers/DrawerConfigContentCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

<component
:is="currentFormComponent"
:data-testid="`form-${type}`"
v-on="currentFormEvents"
/>

Expand All @@ -21,6 +22,7 @@
:text="$t('drawers.reset_widget')"
type="tertiary"
:disabled="disableResetWidgetButton"
data-testid="reset-widget-button"
@click="$emit('reset-widget')"
/>
</template>
Expand Down
Loading
Loading