feat: Add new sidebar for Chatwoot V4 (#10291)
This PR has the initial version of the new sidebar targeted for the next major redesign of the app. This PR includes the following changes - Components in the `layouts-next` and `base-next` directories in `dashboard/components` - Two generic components `Avatar` and `Icon` - `SidebarGroup` component to manage expandable sidebar groups with nested navigation items. This includes handling active states, transitions, and permissions. - `SidebarGroupHeader` component to display the header of each navigation group with optional icons and active state indication. - `SidebarGroupLeaf` component for individual navigation items within a group, supporting icons and active state. - `SidebarGroupSeparator` component to visually separate nested navigation items. (They look a lot like header) - `SidebarGroupEmptyLeaf` component to render empty state of any navigation groups. ---- Co-authored-by: Pranav <pranav@chatwoot.com> Co-authored-by: Pranav <pranavrajs@gmail.com>
This commit is contained in:
@@ -1,6 +1,38 @@
|
||||
import { defineComponent, h } from 'vue';
|
||||
import { createStore } from 'vuex';
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
import { useAccount } from '../useAccount';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { mount } from '@vue/test-utils';
|
||||
|
||||
const store = createStore({
|
||||
modules: {
|
||||
auth: {
|
||||
namespaced: false,
|
||||
getters: {
|
||||
getCurrentAccountId: () => 1,
|
||||
getCurrentUser: () => ({
|
||||
accounts: [
|
||||
{ id: 1, name: 'Chatwoot', role: 'administrator' },
|
||||
{ id: 2, name: 'GitX', role: 'agent' },
|
||||
],
|
||||
}),
|
||||
},
|
||||
},
|
||||
accounts: {
|
||||
namespaced: true,
|
||||
getters: {
|
||||
getAccount: () => id => ({ id, name: 'Chatwoot' }),
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const mountParams = {
|
||||
global: {
|
||||
plugins: [store],
|
||||
},
|
||||
};
|
||||
|
||||
vi.mock('vue-router');
|
||||
|
||||
@@ -8,31 +40,77 @@ describe('useAccount', () => {
|
||||
beforeEach(() => {
|
||||
useRoute.mockReturnValue({
|
||||
params: {
|
||||
accountId: 123,
|
||||
accountId: '123',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
const createComponent = () =>
|
||||
defineComponent({
|
||||
setup() {
|
||||
return useAccount();
|
||||
},
|
||||
render() {
|
||||
return h('div'); // Dummy render to satisfy mount
|
||||
},
|
||||
});
|
||||
|
||||
it('returns accountId as a computed property', () => {
|
||||
const { accountId } = useAccount();
|
||||
expect(accountId.value).toBe(123);
|
||||
const wrapper = mount(createComponent(), mountParams);
|
||||
const { accountId } = wrapper.vm;
|
||||
expect(accountId).toBe(123);
|
||||
});
|
||||
|
||||
it('generates account-scoped URLs correctly', () => {
|
||||
const { accountScopedUrl } = useAccount();
|
||||
const wrapper = mount(createComponent(), mountParams);
|
||||
const { accountScopedUrl } = wrapper.vm;
|
||||
const result = accountScopedUrl('settings/inbox/new');
|
||||
expect(result).toBe('/app/accounts/123/settings/inbox/new');
|
||||
});
|
||||
|
||||
it('handles URLs with leading slash', () => {
|
||||
const { accountScopedUrl } = useAccount();
|
||||
const wrapper = mount(createComponent(), mountParams);
|
||||
const { accountScopedUrl } = wrapper.vm;
|
||||
const result = accountScopedUrl('users');
|
||||
expect(result).toBe('/app/accounts/123/users');
|
||||
expect(result).toBe('/app/accounts/123/users'); // Ensures no double slashes
|
||||
});
|
||||
|
||||
it('handles empty URL', () => {
|
||||
const { accountScopedUrl } = useAccount();
|
||||
const wrapper = mount(createComponent(), mountParams);
|
||||
const { accountScopedUrl } = wrapper.vm;
|
||||
const result = accountScopedUrl('');
|
||||
expect(result).toBe('/app/accounts/123/');
|
||||
});
|
||||
|
||||
it('returns current account based on accountId', () => {
|
||||
const wrapper = mount(createComponent(), mountParams);
|
||||
const { currentAccount } = wrapper.vm;
|
||||
expect(currentAccount).toEqual({ id: 123, name: 'Chatwoot' });
|
||||
});
|
||||
|
||||
it('returns an account-scoped route', () => {
|
||||
const wrapper = mount(createComponent(), mountParams);
|
||||
const { accountScopedRoute } = wrapper.vm;
|
||||
const result = accountScopedRoute('accountDetail', { userId: 456 });
|
||||
expect(result).toEqual({
|
||||
name: 'accountDetail',
|
||||
params: { accountId: 123, userId: 456 },
|
||||
});
|
||||
});
|
||||
|
||||
it('returns route with correct params', () => {
|
||||
const wrapper = mount(createComponent(), mountParams);
|
||||
const { route } = wrapper.vm;
|
||||
expect(route.params).toEqual({ accountId: '123' });
|
||||
});
|
||||
|
||||
it('handles non-numeric accountId gracefully', async () => {
|
||||
useRoute.mockReturnValueOnce({
|
||||
params: { accountId: 'abc' },
|
||||
});
|
||||
|
||||
const wrapper = mount(createComponent(), mountParams);
|
||||
const { accountId } = wrapper.vm;
|
||||
expect(accountId).toBeNaN(); // Handles invalid numeric conversion
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user