123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555 |
- # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
- require 'rails_helper'
- RSpec.describe Gql::Queries::ObjectManager::FrontendAttributes, type: :graphql do
- context 'when fetching frontend attributes' do
- let(:query) do
- <<~QUERY
- query objectManagerFrontendAttributes(
- $object: EnumObjectManagerObjects!
- ) {
- objectManagerFrontendAttributes(
- object: $object
- ) {
- attributes {
- name
- display
- dataType
- dataOption
- isInternal
- }
- screens {
- name
- attributes
- }
- }
- }
- QUERY
- end
- let(:variables) { { object: object } }
- let(:expected_result_agent) { nil }
- let(:expected_result_customer) { nil }
- shared_context 'when fetching frontend attributes as agent and customer' do
- context 'with an agent', authenticated_as: :user, db_strategy: :reset do
- let(:user) { create(:admin) }
- let(:object_attribute) do
- create(:object_manager_attribute_text, object_name: object, screens: { 'edit' => {
- 'ticket.agent' => {
- 'shown' => true,
- 'required' => true,
- },
- 'admin.organization' => {
- 'shown' => true,
- 'required' => true,
- }
- } }).tap do
- ObjectManager::Attribute.migration_execute
- end
- end
- it 'returns frontend object attributes' do
- gql.execute(query, variables: variables)
- expect(gql.result.data).to eq(expected_result_agent)
- end
- context 'with a shown attribute' do
- before do
- object_attribute
- gql.execute(query, variables: variables)
- end
- it 'does contain the shown attribute' do
- edit_screen_attributes = gql.result.data['screens'].find { |screen| screen['name'] == 'edit' }['attributes']
- expect(edit_screen_attributes).to include(object_attribute.name)
- end
- it 'does contain shown attribute which is not internal' do
- frontend_object_attribute = gql.result.data['attributes'].find { |attribute| attribute['name'] == object_attribute.name }
- expect(frontend_object_attribute['isInternal']).to be(false)
- end
- end
- context 'with a hidden attribute' do
- before do
- object_attribute
- object_attribute.update!(screens: { 'edit' => {
- 'ticket.agent' => {
- 'shown' => false,
- 'required' => false,
- },
- 'admin.organization' => {
- 'shown' => false,
- 'required' => false,
- }
- },
- 'view' => {
- 'ticket.agent' => {
- 'shown' => false,
- 'required' => false,
- },
- 'admin.organization' => {
- 'shown' => false,
- 'required' => false,
- }
- } })
- gql.execute(query, variables: variables)
- end
- it 'does contain also the hidden attribute because core workflow is active for the screen (edit)' do
- edit_screen_attributes = gql.result.data['screens'].find { |screen| screen['name'] == 'edit' }['attributes']
- expect(edit_screen_attributes).to include(object_attribute.name)
- end
- it 'does not contain the hidden attribute because for the screen (view)' do
- edit_screen_attributes = gql.result.data['screens'].find { |screen| screen['name'] == 'view' }['attributes']
- expect(edit_screen_attributes).not_to include(object_attribute.name)
- end
- end
- end
- context 'with a customer', authenticated_as: :user do
- let(:user) { create(:customer) }
- it 'returns all object manager attributes' do
- gql.execute(query, variables: variables)
- expect(gql.result.data).to eq(expected_result_customer)
- end
- end
- end
- context 'with object "Organization"' do
- let(:object) { 'Organization' }
- let(:expected_result_agent) do
- {
- 'attributes' => [
- {
- 'name' => 'name',
- 'display' => 'Name',
- 'dataType' => 'input',
- 'dataOption' => { 'type' => 'text',
- 'maxlength' => 150,
- 'null' => false,
- 'item_class' => 'formGroup--halfSize' },
- 'isInternal' => true,
- },
- {
- 'name' => 'shared',
- 'display' => 'Shared organization',
- 'dataType' => 'boolean',
- 'dataOption' => { 'null' => true,
- 'default' => true,
- 'note' => "Customers in the organization can view each other's items.",
- 'item_class' => 'formGroup--halfSize',
- 'options' => { 'true' => 'yes',
- 'false' => 'no' },
- 'translate' => true,
- 'permission' => ['admin.organization'] },
- 'isInternal' => true,
- },
- {
- 'name' => 'domain_assignment',
- 'display' => 'Domain based assignment',
- 'dataType' => 'boolean',
- 'dataOption' => { 'null' => true,
- 'default' => false,
- 'note' => 'Assign users based on user domain.',
- 'item_class' => 'formGroup--halfSize',
- 'options' => { 'true' => 'yes',
- 'false' => 'no' },
- 'translate' => true,
- 'permission' => ['admin.organization'] },
- 'isInternal' => true,
- },
- {
- 'name' => 'domain',
- 'display' => 'Domain',
- 'dataType' => 'input',
- 'dataOption' => { 'type' => 'text',
- 'maxlength' => 150,
- 'null' => true,
- 'item_class' => 'formGroup--halfSize' },
- 'isInternal' => true,
- },
- {
- 'name' => 'vip',
- 'display' => 'VIP',
- 'dataType' => 'boolean',
- 'dataOption' => { 'null' => true,
- 'default' => false,
- 'options' => { 'false' => 'no', 'true' => 'yes' },
- 'translate' => true,
- 'permission' => ['admin.organization'],
- 'item_class' => 'formGroup--halfSize' },
- 'isInternal' => true,
- },
- {
- 'name' => 'note',
- 'display' => 'Note',
- 'dataType' => 'richtext',
- 'dataOption' => { 'type' => 'text',
- 'maxlength' => 5000,
- 'no_images' => true,
- 'null' => true,
- 'note' => 'Notes are visible to agents only, never to customers.' },
- 'isInternal' => true,
- },
- {
- 'name' => 'active',
- 'display' => 'Active',
- 'dataType' => 'active',
- 'dataOption' => { 'null' => true,
- 'default' => true,
- 'permission' => ['admin.organization'] },
- 'isInternal' => true,
- }
- ],
- 'screens' => [
- {
- 'name' => 'edit',
- 'attributes' => %w[name shared domain_assignment domain vip note active],
- },
- {
- 'name' => 'create',
- 'attributes' => %w[name shared domain_assignment domain vip note active],
- },
- {
- 'name' => 'view',
- 'attributes' => %w[name shared domain_assignment domain note],
- }
- ],
- }
- end
- let(:expected_result_customer) do
- {
- 'attributes' => [
- {
- 'name' => 'name',
- 'display' => 'Name',
- 'dataType' => 'input',
- 'dataOption' => { 'type' => 'text',
- 'maxlength' => 150,
- 'null' => false,
- 'item_class' => 'formGroup--halfSize' },
- 'isInternal' => true,
- },
- {
- 'name' => 'domain',
- 'display' => 'Domain',
- 'dataType' => 'input',
- 'dataOption' => { 'type' => 'text',
- 'maxlength' => 150,
- 'null' => true,
- 'item_class' => 'formGroup--halfSize' },
- 'isInternal' => true,
- },
- {
- 'name' => 'note',
- 'display' => 'Note',
- 'dataType' => 'richtext',
- 'dataOption' => { 'type' => 'text',
- 'maxlength' => 5000,
- 'no_images' => true,
- 'null' => true,
- 'note' => 'Notes are visible to agents only, never to customers.' },
- 'isInternal' => true,
- },
- ],
- 'screens' => [
- {
- 'name' => 'edit',
- 'attributes' => %w[name domain note],
- },
- {
- 'name' => 'create',
- 'attributes' => %w[name domain note],
- },
- {
- 'name' => 'view',
- 'attributes' => %w[name],
- }
- ]
- }
- end
- include_context 'when fetching frontend attributes as agent and customer'
- end
- context 'with object "Ticket"' do
- let(:object) { 'Ticket' }
- let(:expected_result_agent) do
- {
- 'attributes' => [
- {
- 'name' => 'title',
- 'display' => 'Title',
- 'dataType' => 'input',
- 'dataOption' => {
- 'type' => 'text',
- 'maxlength' => 200,
- 'null' => false,
- 'translate' => false
- },
- 'isInternal' => true,
- },
- {
- 'name' => 'customer_id',
- 'display' => 'Customer',
- 'dataType' => 'user_autocompletion',
- 'dataOption' => {
- 'relation' => 'User',
- 'autocapitalize' => false,
- 'multiple' => false,
- 'guess' => true,
- 'null' => false,
- 'limit' => 200,
- 'placeholder' => 'Enter Person or Organization/Company',
- 'minLengt' => 2,
- 'translate' => false,
- 'permission' => ['ticket.agent'],
- 'belongs_to' => 'customer',
- },
- 'isInternal' => true,
- },
- {
- 'name' => 'organization_id',
- 'display' => 'Organization',
- 'dataType' => 'autocompletion_ajax_customer_organization',
- 'dataOption' => {
- 'relation' => 'Organization',
- 'autocapitalize' => false,
- 'multiple' => false,
- 'null' => true,
- 'translate' => false,
- 'permission' => ['ticket.agent', 'ticket.customer'],
- 'belongs_to' => 'organization',
- },
- 'isInternal' => true,
- },
- {
- 'name' => 'group_id',
- 'display' => 'Group',
- 'dataType' => 'tree_select',
- 'dataOption' => {
- 'default' => '',
- 'relation' => 'Group',
- 'relation_condition' => { 'access'=>'full' },
- 'nulloption' => true,
- 'multiple' => false,
- 'null' => false,
- 'translate' => false,
- 'only_shown_if_selectable' => true,
- 'permission' => ['ticket.agent', 'ticket.customer'],
- 'maxlength' => 255,
- 'belongs_to' => 'group',
- },
- 'isInternal' => true,
- },
- {
- 'name' => 'owner_id',
- 'display' => 'Owner',
- 'dataType' => 'select',
- 'dataOption' => {
- 'default' => '',
- 'relation' => 'User',
- 'relation_condition' => { 'roles'=>'Agent' },
- 'nulloption' => true,
- 'multiple' => false,
- 'null' => true,
- 'translate' => false,
- 'permission' => ['ticket.agent'],
- 'maxlength' => 255,
- 'belongs_to' => 'owner',
- },
- 'isInternal' => true,
- },
- {
- 'name' => 'state_id',
- 'display' => 'State',
- 'dataType' => 'select',
- 'dataOption' => {
- 'relation' => 'TicketState',
- 'nulloption' => true,
- 'multiple' => false,
- 'null' => false,
- 'default' => 2,
- 'translate' => true,
- 'filter' => Ticket::State.where(active: true).by_category_ids(:viewable),
- 'maxlength' => 255,
- 'belongs_to' => 'state',
- },
- 'isInternal' => true,
- },
- {
- 'name' => 'pending_time',
- 'display' => 'Pending till',
- 'dataType' => 'datetime',
- 'dataOption' => {
- 'future' => true,
- 'past' => false,
- 'diff' => nil,
- 'null' => true,
- 'translate' => true,
- 'permission' => ['ticket.agent'],
- },
- 'isInternal' => true,
- },
- {
- 'name' => 'priority_id',
- 'display' => 'Priority',
- 'dataType' => 'select',
- 'dataOption' => {
- 'relation' => 'TicketPriority',
- 'nulloption' => false,
- 'multiple' => false,
- 'null' => false,
- 'default' => 2,
- 'translate' => true,
- 'maxlength' => 255,
- 'belongs_to' => 'priority',
- },
- 'isInternal' => true,
- },
- {
- 'name' => 'tags',
- 'display' => 'Tags',
- 'dataType' => 'tag',
- 'dataOption' => {
- 'type' => 'text',
- 'null' => true,
- 'translate' => false
- },
- 'isInternal' => true,
- }
- ],
- 'screens' => [
- {
- 'attributes' => %w[title customer_id organization_id],
- 'name' => 'create_top'
- },
- {
- 'attributes' => %w[group_id owner_id state_id pending_time priority_id],
- 'name' => 'edit'
- },
- {
- 'attributes' => %w[group_id owner_id state_id pending_time priority_id],
- 'name' => 'create_middle'
- },
- { 'attributes' => %w[group_id owner_id state_id pending_time priority_id], 'name' => 'overview_bulk' },
- {
- 'attributes' => ['tags'],
- 'name' => 'create_bottom'
- }
- ]
- }
- end
- let(:expected_result_customer) do
- {
- 'attributes' => [
- {
- 'name' => 'title',
- 'display' => 'Title',
- 'dataType' => 'input',
- 'dataOption' => {
- 'type' => 'text',
- 'maxlength' => 200,
- 'null' => false,
- 'translate' => false
- },
- 'isInternal' => true,
- },
- {
- 'name' => 'organization_id',
- 'display' => 'Organization',
- 'dataType' => 'autocompletion_ajax_customer_organization',
- 'dataOption' => {
- 'relation' => 'Organization',
- 'autocapitalize' => false,
- 'multiple' => false,
- 'null' => true,
- 'translate' => false,
- 'permission' => ['ticket.agent', 'ticket.customer'],
- 'belongs_to' => 'organization',
- },
- 'isInternal' => true,
- },
- {
- 'name' => 'group_id',
- 'display' => 'Group',
- 'dataType' => 'tree_select',
- 'dataOption' => {
- 'default' => '',
- 'relation' => 'Group',
- 'relation_condition' => { 'access'=>'full' },
- 'nulloption' => true,
- 'multiple' => false,
- 'null' => false,
- 'translate' => false,
- 'only_shown_if_selectable' => true,
- 'permission' => ['ticket.agent', 'ticket.customer'],
- 'maxlength' => 255,
- 'belongs_to' => 'group',
- },
- 'isInternal' => true,
- },
- {
- 'name' => 'state_id',
- 'display' => 'State',
- 'dataType' => 'select',
- 'dataOption' => {
- 'relation' => 'TicketState',
- 'nulloption' => true,
- 'multiple' => false,
- 'null' => false,
- 'default' => 2,
- 'translate' => true,
- 'filter' => Ticket::State.where(active: true).by_category_ids(:viewable),
- 'maxlength' => 255,
- 'belongs_to' => 'state',
- },
- 'isInternal' => true,
- },
- ],
- 'screens' => [
- {
- 'attributes' => %w[title organization_id],
- 'name' => 'create_top'
- },
- {
- 'attributes' => ['state_id'],
- 'name' => 'edit'
- },
- {
- 'attributes' => %w[group_id state_id],
- 'name' => 'create_middle'
- },
- { 'attributes' => [], 'name' => 'overview_bulk' },
- {
- 'attributes' => [],
- 'name' => 'create_bottom'
- }
- ]
- }
- end
- include_context 'when fetching frontend attributes as agent and customer'
- end
- end
- end
|