123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399 |
- // Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
- import { getByRole } from '@testing-library/vue'
- import { visitView } from '#tests/support/components/visitView.ts'
- import { mockUserCurrent } from '#tests/support/mock-userCurrent.ts'
- import { nullableMock, waitForNextTick } from '#tests/support/utils.ts'
- import {
- mockAutocompleteSearchAgentQuery,
- waitForAutocompleteSearchAgentQueryCalls,
- } from '#shared/components/Form/fields/FieldAgent/graphql/queries/autocompleteSearch/agent.mocks.ts'
- import type { AutocompleteSearchUserEntry } from '#shared/graphql/types.ts'
- import { convertToGraphQLId } from '#shared/graphql/utils.ts'
- import { waitForUserCurrentOutOfOfficeMutationCalls } from '../graphql/mutations/userCurrentOutOfOffice.mocks.ts'
- const agentAutocompleteOptions = [
- {
- __typename: 'AutocompleteSearchUserEntry',
- value: 1,
- label: 'foo',
- disabled: false,
- user: nullableMock({
- id: convertToGraphQLId('User', 1),
- internalId: 1,
- fullname: 'sample 1',
- }),
- },
- {
- __typename: 'AutocompleteSearchUserEntry',
- value: 2,
- label: 'bar',
- disabled: false,
- user: nullableMock({
- id: convertToGraphQLId('User', 2),
- internalId: 2,
- fullname: 'sample 1',
- }),
- },
- ] as AutocompleteSearchUserEntry[]
- describe('Out of Office page', () => {
- describe('when enabled', () => {
- beforeEach(() => {
- mockUserCurrent({
- id: '123',
- internalId: 1,
- firstname: 'John',
- lastname: 'Doe',
- outOfOffice: true,
- preferences: { out_of_office_text: 'OOF holiday' },
- outOfOfficeStartAt: '2024-03-01',
- outOfOfficeEndAt: '2024-04-01',
- outOfOfficeReplacement: {
- id: convertToGraphQLId('User', 256),
- internalId: 256,
- fullname: 'Example Agent',
- },
- })
- })
- it('loads current Out of Office settings', async () => {
- const view = await visitView('/personal-setting/out-of-office')
- expect(view.getByLabelText('Reason for absence')).toHaveValue(
- 'OOF holiday',
- )
- expect(view.getByLabelText('Start and end date')).toHaveValue(
- '2024-03-01 - 2024-04-01',
- )
- expect(view.getByLabelText('Replacement agent')).toHaveValue(
- 'Example Agent',
- )
- expect(view.getByLabelText('Active')).toBeChecked()
- })
- it('loads data updated elsewhere', async () => {
- const view = await visitView('/personal-setting/out-of-office')
- expect(view.getByLabelText('Reason for absence')).toHaveValue(
- 'OOF holiday',
- )
- mockUserCurrent({
- firstname: 'John',
- lastname: 'Doe',
- outOfOffice: true,
- preferences: { out_of_office_text: '' },
- outOfOfficeStartAt: '2024-03-01',
- outOfOfficeEndAt: '2024-04-01',
- outOfOfficeReplacement: {
- id: convertToGraphQLId('User', 256),
- internalId: 256,
- fullname: 'Example Agent',
- },
- })
- await waitForNextTick()
- expect(view.getByLabelText('Reason for absence')).toHaveValue('')
- })
- it('does not reset form if unrelated data was updated', async () => {
- const view = await visitView('/personal-setting/out-of-office')
- expect(view.getByLabelText('Reason for absence')).toHaveValue(
- 'OOF holiday',
- )
- const input = view.getByLabelText('Reason for absence')
- await view.events.clear(input)
- await view.events.type(input, 'new label')
- mockUserCurrent({
- firstname: 'John II',
- lastname: 'Doe',
- outOfOffice: true,
- preferences: { out_of_office_text: 'OOF holiday' },
- outOfOfficeStartAt: '2024-03-01',
- outOfOfficeEndAt: '2024-04-01',
- outOfOfficeReplacement: {
- id: convertToGraphQLId('User', 256),
- internalId: 256,
- fullname: 'Example Agent',
- },
- })
- await waitForNextTick()
- expect(view.getByLabelText('Reason for absence')).toHaveValue('new label')
- })
- it('shows success notification', async () => {
- const view = await visitView('/personal-setting/out-of-office')
- await view.events.click(view.getByText('Save Out of Office'))
- expect(
- view.getByText('Out of Office settings have been saved successfully'),
- ).toBeInTheDocument()
- })
- it('can clear label', async () => {
- const view = await visitView('/personal-setting/out-of-office')
- const input = view.getByLabelText('Reason for absence')
- await view.events.clear(input)
- await view.events.click(view.getByText('Save Out of Office'))
- const calls = await waitForUserCurrentOutOfOfficeMutationCalls()
- expect(calls.at(-1)?.variables).toEqual(
- expect.objectContaining({
- input: expect.objectContaining({
- text: '',
- }),
- }),
- )
- })
- it('cannot set date range to blank', async () => {
- const view = await visitView('/personal-setting/out-of-office')
- const input = view.getByLabelText('Start and end date')
- const button = getByRole(input.parentElement!, 'button')
- await view.events.click(button)
- await view.events.click(view.getByText('Save Out of Office'))
- expect(input).toBeDescribedBy('This field is required.')
- })
- it('cannot set replacement agent to blank', async () => {
- const view = await visitView('/personal-setting/out-of-office')
- const input = view.getByLabelText('Replacement agent')
- const button = getByRole(input, 'button')
- await view.events.click(button)
- await view.events.click(view.getByText('Save Out of Office'))
- expect(input).toBeDescribedBy('This field is required.')
- })
- it('cannot set replacement agent to themselves', async () => {
- const view = await visitView('/personal-setting/out-of-office')
- const inputAgent = view.getByLabelText('Replacement agent')
- await view.events.click(inputAgent)
- const filterElement = getByRole(inputAgent, 'searchbox')
- mockAutocompleteSearchAgentQuery({
- autocompleteSearchAgent: agentAutocompleteOptions,
- })
- await view.events.type(filterElement, '*')
- const calls = await waitForAutocompleteSearchAgentQueryCalls()
- expect(calls.at(-1)?.variables).toEqual({
- input: expect.objectContaining({
- exceptInternalId: 1,
- }),
- })
- })
- it('can disable Out of Office', async () => {
- const view = await visitView('/personal-setting/out-of-office')
- const input = view.getByLabelText('Active')
- await view.events.click(input)
- await view.events.click(view.getByText('Save Out of Office'))
- const calls = await waitForUserCurrentOutOfOfficeMutationCalls()
- expect(calls.at(-1)?.variables).toEqual(
- expect.objectContaining({
- input: expect.objectContaining({
- enabled: false,
- }),
- }),
- )
- })
- it('can disable Out of Office and unset settings', async () => {
- const view = await visitView('/personal-setting/out-of-office')
- const inputActivated = view.getByLabelText('Active')
- await view.events.click(inputActivated)
- const inputDate = view.getByLabelText('Start and end date')
- const buttonDate = getByRole(inputDate.parentElement!, 'button')
- await view.events.click(buttonDate)
- const inputLabel = view.getByLabelText('Reason for absence')
- await view.events.clear(inputLabel)
- const inputAgent = view.getByLabelText('Replacement agent')
- const buttonAgent = getByRole(inputAgent, 'button')
- await view.events.click(buttonAgent)
- await view.events.click(view.getByText('Save Out of Office'))
- const calls = await waitForUserCurrentOutOfOfficeMutationCalls()
- expect(calls.at(-1)?.variables).toEqual(
- expect.objectContaining({
- input: expect.objectContaining({
- enabled: false,
- text: '',
- startAt: undefined,
- endAt: undefined,
- replacementId: undefined,
- }),
- }),
- )
- })
- })
- describe('when disabled', () => {
- beforeEach(() => {
- mockUserCurrent({
- firstname: 'John',
- lastname: 'Doe',
- outOfOffice: false,
- outOfOfficeStartAt: '',
- outOfOfficeEndAt: '',
- outOfOfficeReplacement: null,
- })
- })
- it('loads current Out of Office settings', async () => {
- const view = await visitView('/personal-setting/out-of-office')
- expect(view.getByLabelText('Reason for absence')).toHaveValue('')
- expect(view.getByLabelText('Start and end date')).toHaveValue('')
- expect(view.getByLabelText('Replacement agent')).toHaveValue('')
- expect(view.getByLabelText('Active')).not.toBeChecked()
- })
- it('can set date range', async () => {
- const view = await visitView('/personal-setting/out-of-office')
- const input = view.getByLabelText('Start and end date')
- await view.events.type(input, '2024-01-02 - 2024-02-02')
- await view.events.keyboard('{Enter}')
- await view.events.click(view.getByText('Save Out of Office'))
- const calls = await waitForUserCurrentOutOfOfficeMutationCalls()
- expect(calls.at(-1)?.variables).toEqual(
- expect.objectContaining({
- input: expect.objectContaining({
- startAt: '2024-01-02',
- endAt: '2024-02-02',
- }),
- }),
- )
- })
- it('can set replacement agent', async () => {
- const view = await visitView('/personal-setting/out-of-office')
- const inputAgent = view.getByLabelText('Replacement agent')
- await view.events.click(inputAgent)
- const filterElement = getByRole(inputAgent, 'searchbox')
- mockAutocompleteSearchAgentQuery({
- autocompleteSearchAgent: [agentAutocompleteOptions[0]],
- })
- await view.events.type(filterElement, agentAutocompleteOptions[0].label)
- await waitForAutocompleteSearchAgentQueryCalls()
- await view.events.click(view.getAllByRole('option')[0])
- await view.events.click(view.getByText('Save Out of Office'))
- const calls = await waitForUserCurrentOutOfOfficeMutationCalls()
- expect(calls.at(-1)?.variables).toEqual(
- expect.objectContaining({
- input: expect.objectContaining({
- replacementId: convertToGraphQLId(
- 'User',
- agentAutocompleteOptions[0].value,
- ),
- }),
- }),
- )
- })
- it('can enable Out of Office with settings', async () => {
- const view = await visitView('/personal-setting/out-of-office')
- const inputLabel = view.getByLabelText('Active')
- await view.events.click(inputLabel)
- const inputDate = view.getByLabelText('Start and end date')
- await view.events.type(inputDate, '2024-01-02 - 2024-02-02')
- await view.events.keyboard('{Enter}')
- const inputAgent = view.getByLabelText('Replacement agent')
- await view.events.click(inputAgent)
- const filterElement = getByRole(inputAgent, 'searchbox')
- mockAutocompleteSearchAgentQuery({
- autocompleteSearchAgent: [agentAutocompleteOptions[0]],
- })
- await view.events.type(filterElement, agentAutocompleteOptions[0].label)
- await waitForAutocompleteSearchAgentQueryCalls()
- await view.events.click(view.getAllByRole('option')[0])
- await view.events.click(view.getByText('Save Out of Office'))
- const calls = await waitForUserCurrentOutOfOfficeMutationCalls()
- expect(calls.at(-1)?.variables).toEqual(
- expect.objectContaining({
- input: expect.objectContaining({
- startAt: '2024-01-02',
- endAt: '2024-02-02',
- replacementId: convertToGraphQLId(
- 'User',
- agentAutocompleteOptions[0].value,
- ),
- enabled: true,
- }),
- }),
- )
- })
- it('cannot enable Out of Office without date range and replacement agent', async () => {
- const view = await visitView('/personal-setting/out-of-office')
- const input = view.getByLabelText('Active')
- await view.events.click(input)
- await view.events.click(view.getByText('Save Out of Office'))
- const inputDate = view.getByLabelText('Start and end date')
- expect(inputDate).toBeDescribedBy('This field is required.')
- })
- })
- })
|