123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411 |
- // Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
- import { getByRole } from '@testing-library/vue'
- import { flushPromises } from '@vue/test-utils'
- import { keyBy } from 'lodash-es'
- import { renderComponent } from '#tests/support/components/index.ts'
- import { mockApplicationConfig } from '#tests/support/mock-applicationConfig.ts'
- import { mockPermissions } from '#tests/support/mock-permissions.ts'
- import { i18n } from '#shared/i18n.ts'
- import ObjectAttributes from '../ObjectAttributes.vue'
- import attributes from './attributes.json'
- vi.hoisted(() => {
- vi.setSystemTime('2021-04-09T10:11:12Z')
- })
- const attributesByKey = keyBy(attributes, 'name')
- describe('common object attributes interface', () => {
- beforeEach(() => {
- mockApplicationConfig({
- pretty_date_format: 'absolute',
- })
- })
- test('renders all available attributes', () => {
- mockPermissions(['admin.user', 'ticket.agent'])
- const object = {
- login: 'some_object',
- address: 'Berlin, Street, House',
- vip: true,
- note: 'note',
- active: true,
- invisible: 'invisible',
- objectAttributeValues: [
- {
- attribute: attributesByKey.date_attribute,
- value: '2022-08-19',
- __typename: 'ObjectAttributeValue',
- },
- {
- attribute: attributesByKey.textarea_field,
- value: 'textarea text',
- },
- {
- attribute: attributesByKey.integer_field,
- value: 600,
- },
- {
- attribute: attributesByKey.date_time_field,
- value: '2022-08-11T05:00:00.000Z',
- },
- {
- attribute: attributesByKey.single_select,
- value: 'key1',
- },
- {
- attribute: attributesByKey.multi_select_field,
- value: ['key1', 'key2'],
- },
- {
- attribute: attributesByKey.single_tree_select,
- value: 'key1::key1_child1',
- },
- {
- attribute: attributesByKey.multi_tree_select,
- value: ['key1', 'key2', 'key2::key2_child1'],
- },
- {
- attribute: attributesByKey.some_url,
- value: 'https://url.com',
- },
- {
- attribute: attributesByKey.some_email,
- value: 'email@email.com',
- },
- {
- attribute: attributesByKey.phone,
- value: '+49 123456789',
- },
- {
- attribute: attributesByKey.external_attribute,
- value: { value: 1, label: 'Display External' },
- },
- ],
- }
- i18n.setTranslationMap(
- new Map([
- ['FORMAT_DATE', 'dd/mm/yyyy'],
- ['FORMAT_DATETIME', 'dd/mm/yyyy HH:MM'],
- ]),
- )
- const view = renderComponent(ObjectAttributes, {
- props: {
- object,
- attributes,
- },
- router: true,
- store: true,
- })
- const getRegion = (name: string) => view.getByRole('region', { name })
- expect(getRegion('Login')).toHaveTextContent(object.login)
- expect(getRegion('Address')).toHaveTextContent(object.address)
- expect(getRegion('VIP')).toHaveTextContent('yes')
- expect(getRegion('Note')).toHaveTextContent(object.note)
- expect(getRegion('Active')).toHaveTextContent('yes')
- expect(getRegion('Date Attribute')).toHaveTextContent(/19\/08\/2022$/)
- expect(getRegion('Textarea Field')).toHaveTextContent('textarea text')
- expect(getRegion('Integer Field')).toHaveTextContent('600')
- expect(getRegion('DateTime Field')).toHaveTextContent('11/08/2022 05:00')
- expect(getRegion('Single Select Field')).toHaveTextContent('Display1')
- expect(getRegion('Multi Select Field')).toHaveTextContent(
- 'Display1, Display2',
- )
- expect(getRegion('Single Tree Select Field')).toHaveTextContent(
- 'key1::key1_child1',
- )
- expect(getRegion('Multi Tree Select Field')).toHaveTextContent(
- 'key1, key2, key2::key2_child1',
- )
- expect(getRegion('External Attribute')).toHaveTextContent(
- 'Display External',
- )
- expect(
- getByRole(getRegion('Phone'), 'link', { name: '+49 123456789' }),
- ).toHaveAttribute('href', 'tel:+49123456789')
- expect(
- getByRole(getRegion('Email'), 'link', { name: 'email@email.com' }),
- ).toHaveAttribute('href', 'mailto:email@email.com')
- expect(
- getByRole(getRegion('Url'), 'link', { name: 'https://url.com' }),
- ).toHaveAttribute('href', 'https://url.com')
- expect(
- view.queryByRole('region', { name: 'Invisible' }),
- ).not.toBeInTheDocument()
- expect(
- view.queryByRole('region', { name: 'Hidden Boolean' }),
- ).not.toBeInTheDocument()
- })
- test('hides attributes without permission', () => {
- mockPermissions([])
- const object = {
- active: true,
- }
- const view = renderComponent(ObjectAttributes, {
- props: {
- object,
- attributes: [attributesByKey.active],
- },
- })
- expect(view.queryAllByRole('region')).toHaveLength(0)
- })
- test("don't show empty fields", () => {
- const object = {
- login: '',
- objectAttributesValues: [
- {
- attribute: attributesByKey.integer_field,
- value: 0,
- },
- {
- attribute: attributesByKey.multi_select_field,
- value: [],
- },
- ],
- }
- const view = renderComponent(ObjectAttributes, {
- props: {
- object,
- attributes: [attributesByKey.login],
- },
- })
- expect(view.queryAllByRole('region')).toHaveLength(0)
- })
- test('show default, if not defined', () => {
- const object = {
- login: '',
- }
- const attribute = {
- ...attributesByKey.login,
- name: 'login',
- display: 'Login',
- }
- const view = renderComponent(ObjectAttributes, {
- props: {
- object,
- attributes: [
- {
- ...attribute,
- dataOption: { ...attribute.dataOption, default: 'default' },
- },
- ],
- },
- })
- expect(view.getByRole('region', { name: 'Login' })).toHaveTextContent(
- 'default',
- )
- })
- it('translates translatable', () => {
- mockPermissions(['admin.user', 'ticket.agent'])
- const object = {
- vip: true,
- single_select: 'key1',
- multi_select_field: ['key1', 'key2'],
- single_tree_select: 'key1::key1_child1',
- multi_tree_select: ['key1', 'key1::key1_child1'],
- }
- const translatable = (attr: any) => ({
- ...attr,
- dataOption: {
- ...attr.dataOption,
- translate: true,
- },
- })
- const attributes = [
- translatable(attributesByKey.vip),
- translatable(attributesByKey.single_select),
- translatable(attributesByKey.multi_select_field),
- translatable(attributesByKey.single_tree_select),
- translatable(attributesByKey.multi_tree_select),
- ]
- i18n.setTranslationMap(
- new Map([
- ['yes', 'sí'],
- ['Display1', 'Monitor1'],
- ['Display2', 'Monitor2'],
- ['key1', 'llave1'],
- ['key2', 'llave2'],
- ['key1_child1', 'llave1_niño1'],
- ]),
- )
- const view = renderComponent(ObjectAttributes, {
- props: {
- object,
- attributes,
- },
- router: true,
- })
- const getRegion = (name: string) => view.getByRole('region', { name })
- const vip = getRegion('VIP')
- const singleSelect = getRegion('Single Select Field')
- const multiSelect = getRegion('Multi Select Field')
- const singleTreeSelect = getRegion('Single Tree Select Field')
- const multiTreeSelect = getRegion('Multi Tree Select Field')
- expect(vip).toHaveTextContent('sí')
- expect(singleSelect).toHaveTextContent('Monitor1')
- expect(multiSelect).toHaveTextContent('Monitor1, Monitor2')
- expect(singleTreeSelect).toHaveTextContent('llave1::llave1_niño1')
- expect(multiTreeSelect).toHaveTextContent('llave1, llave1::llave1_niño1')
- })
- it('renders different dates', async () => {
- const object = {
- now: '2021-04-09T10:11:12Z',
- past: '2021-02-09T10:11:12Z',
- future: '2021-10-09T10:11:12Z',
- }
- const attributes = [
- { ...attributesByKey.date_time_field, name: 'now', display: 'now' },
- { ...attributesByKey.date_time_field, name: 'past', display: 'past' },
- { ...attributesByKey.date_time_field, name: 'future', display: 'future' },
- ]
- const view = renderComponent(ObjectAttributes, {
- props: {
- object,
- attributes,
- },
- router: true,
- })
- const getRegion = (time: string) => view.getByRole('region', { name: time })
- expect(getRegion('now')).toHaveTextContent('2021-04-09 10:11')
- expect(getRegion('past')).toHaveTextContent('2021-02-09 10:11')
- expect(getRegion('future')).toHaveTextContent('2021-10-09 10:11')
- mockApplicationConfig({
- pretty_date_format: 'relative',
- })
- await flushPromises()
- expect(getRegion('now')).toHaveTextContent('just now')
- expect(getRegion('past')).toHaveTextContent('1 month ago')
- expect(getRegion('future')).toHaveTextContent('in 6 months')
- })
- it('doesnt render skipped attributes', () => {
- const object = {
- skip: 'skip',
- show: 'show',
- }
- const attributes = [
- { ...attributesByKey.address, name: 'skip', display: 'skip' },
- { ...attributesByKey.address, name: 'show', display: 'show' },
- ]
- const view = renderComponent(ObjectAttributes, {
- props: {
- object,
- attributes,
- skipAttributes: ['skip'],
- },
- router: true,
- })
- expect(view.getByRole('region', { name: 'show' })).toBeInTheDocument()
- expect(view.queryByRole('region', { name: 'skip' })).not.toBeInTheDocument()
- })
- it('renders links', () => {
- const object = {
- objectAttributeValues: [
- {
- attribute: {
- ...attributesByKey.integer_field,
- dataOption: {
- ...attributesByKey.integer_field.dataOption,
- linktemplate: 'https://integer.com/#{render}',
- },
- },
- value: 600,
- renderedLink: 'https://integer.com/rendered',
- },
- {
- attribute: attributesByKey.some_url,
- value: 'https://url.com',
- },
- {
- attribute: {
- ...attributesByKey.some_email,
- dataOption: {
- ...attributesByKey.integer_field.dataOption,
- linktemplate: 'https://email.com/#{render}',
- },
- },
- value: 'email@email.com',
- renderedLink: 'https://email.com/rendered',
- },
- {
- attribute: {
- ...attributesByKey.phone,
- dataOption: {
- ...attributesByKey.integer_field.dataOption,
- linktemplate: 'https://phone.com/#{render}',
- },
- },
- value: '+49 123456789',
- renderedLink: 'https://phone.com/rendered',
- },
- ],
- }
- const attributes = object.objectAttributeValues.map((v) => v.attribute)
- const view = renderComponent(ObjectAttributes, {
- props: {
- object,
- attributes,
- skipAttributes: ['skip'],
- },
- router: true,
- })
- const getRegion = (name: string) => view.getByRole('region', { name })
- expect(
- getByRole(getRegion('Integer Field'), 'link', { name: '600' }),
- ).toHaveAttribute('href', 'https://integer.com/rendered')
- expect(
- getByRole(getRegion('Phone'), 'link', { name: '+49 123456789' }),
- ).toHaveAttribute('href', 'https://phone.com/rendered')
- expect(
- getByRole(getRegion('Email'), 'link', { name: 'email@email.com' }),
- ).toHaveAttribute('href', 'https://email.com/rendered')
- expect(
- getByRole(getRegion('Url'), 'link', { name: 'https://url.com' }),
- ).toHaveAttribute('href', 'https://url.com')
- })
- })
|