123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271 |
- // Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
- import {
- fireEvent,
- getAllByRole,
- getByLabelText,
- getByRole,
- } from '@testing-library/vue'
- import { visitView } from '#tests/support/components/visitView.ts'
- import { mockPermissions } from '#tests/support/mock-permissions.ts'
- import { mockUserCurrent } from '#tests/support/mock-userCurrent.ts'
- import { mockLogoutMutation } from '#shared/graphql/mutations/logout.mocks.ts'
- describe('Left sidebar', () => {
- beforeEach(() => {
- mockUserCurrent({
- id: 'gid://zammad/User/999',
- firstname: 'Nicole',
- lastname: 'Braun',
- fullname: 'Nicole Braun',
- preferences: {},
- })
- })
- afterEach(() => {
- localStorage.clear()
- })
- describe('width handling', () => {
- it('renders initially with the default width', async () => {
- const view = await visitView('/')
- const aside = view.getByRole('complementary')
- expect(aside.parentElement).toHaveStyle({
- gridTemplateColumns: '260px 1fr',
- })
- })
- it('restores stored width', async () => {
- localStorage.setItem('gid://zammad/User/999-left-sidebar-width', '216')
- const view = await visitView('/')
- const aside = view.getByRole('complementary')
- expect(aside.parentElement).toHaveStyle({
- gridTemplateColumns: '216px 1fr',
- })
- })
- it('supports collapsing/expanding', async () => {
- const view = await visitView('/')
- const aside = view.getByRole('complementary')
- const collapseButton = getByRole(aside, 'button', {
- name: 'Collapse sidebar',
- })
- await view.events.click(collapseButton)
- expect(aside.parentElement).toHaveStyle({
- gridTemplateColumns: '56px 1fr',
- })
- const expandButton = getByRole(aside, 'button', {
- name: 'Expand sidebar',
- })
- await view.events.click(expandButton)
- expect(aside.parentElement).toHaveStyle({
- gridTemplateColumns: '260px 1fr',
- })
- })
- it('restores collapsed state width', async () => {
- localStorage.setItem(
- 'gid://zammad/User/999-left-sidebar-collapsed',
- 'true',
- )
- const view = await visitView('/')
- const aside = view.getByRole('complementary')
- expect(aside.parentElement).toHaveStyle({
- gridTemplateColumns: '56px 1fr',
- })
- })
- it('supports resizing', async () => {
- const view = await visitView('/')
- const aside = view.getByRole('complementary')
- const resizeHandle = getByLabelText(aside, 'Resize sidebar')
- await fireEvent.mouseDown(resizeHandle, { clientX: 260 })
- await fireEvent.mouseMove(document, { clientX: 216 })
- await fireEvent.mouseUp(document, { clientX: 216 })
- expect(aside.parentElement).toHaveStyle({
- gridTemplateColumns: '216px 1fr',
- })
- })
- it('supports resetting', async () => {
- localStorage.setItem('gid://zammad/User/999-left-sidebar-width', '216')
- const view = await visitView('/')
- const aside = view.getByRole('complementary')
- const resizeHandle = getByLabelText(aside, 'Resize sidebar')
- await view.events.dblClick(resizeHandle)
- expect(aside.parentElement).toHaveStyle({
- gridTemplateColumns: '260px 1fr',
- })
- })
- })
- describe('User menu', () => {
- afterEach(() => {
- vi.clearAllMocks()
- })
- it.each([{ collapsed: false }, { collapsed: true }])(
- 'shows menu popover on click (collapsed: $collapsed)',
- async ({ collapsed }) => {
- localStorage.setItem(
- 'gid://zammad/User/999-left-sidebar-collapsed',
- String(collapsed),
- )
- const view = await visitView('/')
- const aside = view.getByRole('complementary')
- const avatarButton = getByRole(aside, 'button', {
- name: 'Nicole Braun',
- })
- expect(avatarButton).toHaveTextContent('NB')
- await view.events.click(avatarButton)
- const popover = view.getByRole('region', { name: 'Nicole Braun' })
- expect(popover).toHaveTextContent('Nicole Braun')
- const menu = getByRole(popover, 'menu')
- const menuItems = getAllByRole(menu, 'menuitem')
- expect(menuItems).toHaveLength(4)
- },
- )
- it('supports cycling appearance state', async () => {
- mockPermissions(['user_preferences.appearance'])
- const view = await visitView('/')
- const aside = view.getByRole('complementary')
- const avatarButton = getByRole(aside, 'button', { name: 'Nicole Braun' })
- await view.events.click(avatarButton)
- const appearanceButton = view.getByRole('button', { name: 'Appearance' })
- const appearanceSwitch = view.getByRole('checkbox', { name: 'Dark Mode' })
- expect(appearanceSwitch).toBePartiallyChecked()
- await view.events.click(appearanceSwitch)
- expect(appearanceSwitch).toBeChecked()
- await view.events.click(appearanceButton)
- expect(appearanceSwitch).not.toBeChecked()
- await view.events.click(appearanceSwitch)
- expect(appearanceSwitch).toBePartiallyChecked()
- })
- it('supports navigating to playground', async () => {
- const view = await visitView('/')
- const aside = view.getByRole('complementary')
- const avatarButton = getByRole(aside, 'button', { name: 'Nicole Braun' })
- await view.events.click(avatarButton)
- const playgroundLink = view.getByRole('link', {
- name: 'Playground',
- })
- await view.events.click(playgroundLink)
- await vi.waitFor(() => {
- expect(view, 'correctly redirects to playground page').toHaveCurrentUrl(
- '/playground',
- )
- })
- expect(
- view.queryByRole('region', { name: 'User menu' }),
- ).not.toBeInTheDocument()
- })
- // TODO: Cover keyboard shortcuts menu item when ready.
- it('supports navigating to personal settings', async () => {
- const view = await visitView('/')
- const aside = view.getByRole('complementary')
- const avatarButton = getByRole(aside, 'button', { name: 'Nicole Braun' })
- await view.events.click(avatarButton)
- const personalSettingsLink = view.getByRole('link', {
- name: 'Profile settings',
- })
- await view.events.click(personalSettingsLink)
- await vi.waitFor(() => {
- expect(
- view,
- 'correctly redirects to personal settings page',
- ).toHaveCurrentUrl('/personal-setting/appearance')
- })
- expect(
- view.queryByRole('region', { name: 'User menu' }),
- ).not.toBeInTheDocument()
- })
- it('supports signing out', async () => {
- const view = await visitView('/')
- const aside = view.getByRole('complementary')
- const avatarButton = getByRole(aside, 'button', { name: 'Nicole Braun' })
- await view.events.click(avatarButton)
- const logoutLink = view.getByRole('link', { name: 'Sign out' })
- mockLogoutMutation({
- logout: {
- success: true,
- externalLogoutUrl: null,
- },
- })
- await view.events.click(logoutLink)
- await vi.waitFor(() => {
- expect(view, 'correctly redirects to login page').toHaveCurrentUrl(
- '/login',
- )
- })
- expect(
- view.queryByRole('region', { name: 'User menu' }),
- ).not.toBeInTheDocument()
- })
- })
- })
|