Просмотр исходного кода

Feature: Mobile - Add "phone" article type

Vladimir Sheremet 2 лет назад
Родитель
Сommit
60409bd3af

+ 1 - 0
app/frontend/shared/components/Form/fields/FieldFile/FieldFileInput.vue

@@ -159,6 +159,7 @@ const { showImage } = useImageViewer(uploadFiles)
     ref="fileInput"
     data-test-id="fileInput"
     type="file"
+    :name="context.id"
     class="hidden"
     aria-hidden="true"
     :accept="props.context.accept"

+ 22 - 0
app/frontend/shared/entities/ticket-article/action/plugins/__tests__/action-phone.spec.ts

@@ -0,0 +1,22 @@
+// Copyright (C) 2012-2023 Zammad Foundation, https://zammad-foundation.org/
+
+import { defaultTicket } from '@mobile/pages/ticket/__tests__/mocks/detail-view'
+import { setupView } from '@tests/support/mock-user'
+import { createTestArticleTypes } from './utils'
+
+describe('phone type', () => {
+  it('customer cannot use phone type', () => {
+    setupView('customer')
+    const { ticket } = defaultTicket()
+    const actions = createTestArticleTypes(ticket)
+    expect(actions.find((a) => a.value === 'phone')).toBeUndefined()
+  })
+
+  it('agents can use phone type', () => {
+    setupView('agent')
+    const { ticket } = defaultTicket()
+    ticket.policy.update = true
+    const actions = createTestArticleTypes(ticket)
+    expect(actions.find((a) => a.value === 'phone')).toBeDefined()
+  })
+})

+ 6 - 2
app/frontend/shared/entities/ticket-article/action/plugins/__tests__/utils.ts

@@ -2,6 +2,7 @@
 
 import { defaultArticles } from '@mobile/pages/ticket/__tests__/mocks/detail-view'
 import type { TicketArticle, TicketById } from '@shared/entities/ticket/types'
+import type { AppName } from '@shared/types/app'
 import { initializeStore } from '@tests/support/components/initializeStore'
 import { createArticleActions, createArticleTypes } from '../index'
 import type { TicketActionAddOptions } from '../types'
@@ -28,7 +29,10 @@ export const createTestArticleActions = (
   return createArticleActions(ticket, article, 'mobile', options)
 }
 
-export const createTestArticleTypes = (ticket: TicketById) => {
+export const createTestArticleTypes = (
+  ticket: TicketById,
+  app: AppName = 'mobile',
+) => {
   initializeStore()
-  return createArticleTypes(ticket, 'mobile')
+  return createArticleTypes(ticket, app)
 }

+ 26 - 0
app/frontend/shared/entities/ticket-article/action/plugins/phone.ts

@@ -0,0 +1,26 @@
+// Copyright (C) 2012-2023 Zammad Foundation, https://zammad-foundation.org/
+
+import type { TicketArticleActionPlugin, TicketArticleType } from './types'
+
+const actionPlugin: TicketArticleActionPlugin = {
+  order: 100,
+
+  addTypes() {
+    const type: TicketArticleType = {
+      apps: ['mobile'],
+      value: 'phone',
+      label: __('Phone'),
+      icon: {
+        mobile: 'mobile-phone',
+      },
+      view: {
+        agent: ['change'],
+      },
+      attributes: ['attachments'],
+      internal: false,
+    }
+    return [type]
+  },
+}
+
+export default actionPlugin

+ 8 - 0
app/frontend/tests/support/mock-user.ts

@@ -0,0 +1,8 @@
+// Copyright (C) 2012-2023 Zammad Foundation, https://zammad-foundation.org/
+
+import { mockPermissions } from './mock-permissions'
+
+// If we change handling, we can improve it here in one function
+export const setupView = (view: 'agent' | 'customer') => {
+  mockPermissions([`ticket.${view}`])
+}

+ 1 - 0
i18n/zammad.pot

@@ -7958,6 +7958,7 @@ msgid "Personal overview order was reset."
 msgstr ""
 
 #: app/assets/javascripts/app/controllers/cti.coffee
+#: app/frontend/shared/entities/ticket-article/action/plugins/phone.ts
 #: db/seeds/object_manager_attributes.rb
 msgid "Phone"
 msgstr ""

BIN
spec/fixtures/files/image/small.png


+ 64 - 15
spec/system/apps/mobile/tickets/ticket_create_article_spec.rb

@@ -13,10 +13,21 @@ RSpec.describe 'Mobile > Ticket > Create article', app: :mobile, authenticated_a
     wait_for_gql('apps/mobile/pages/ticket/graphql/mutations/update.graphql')
   end
 
+  def save_article()
+    find_button('Done').click
+    find_button('Save ticket').click
+
+    wait_for_ticket_edit
+  end
+
+  def open_article_dialog()
+    visit "/tickets/#{ticket.id}"
+    find_button('Add reply').click
+  end
+
   context 'when creating a new article as an agent', authenticated_as: :agent do
     it 'creates an internal note (default)' do
-      visit "/tickets/#{ticket.id}"
-      find_button('Add reply').click
+      open_article_dialog
 
       expect(find_select('Article Type', visible: :all)).to have_selected_option('Note')
       expect(find_select('Visibility', visible: :all)).to have_selected_option('Internal')
@@ -25,10 +36,7 @@ RSpec.describe 'Mobile > Ticket > Create article', app: :mobile, authenticated_a
       expect(text).to have_text_value('', exact: true)
       text.type('This is a note')
 
-      find_button('Done').click
-      find_button('Save ticket').click
-
-      wait_for_ticket_edit
+      save_article
 
       expect(Ticket::Article.last).to have_attributes(
         type_id:  Ticket::Article::Type.lookup(name: 'note').id,
@@ -39,8 +47,7 @@ RSpec.describe 'Mobile > Ticket > Create article', app: :mobile, authenticated_a
     end
 
     it 'creates a public note' do
-      visit "/tickets/#{ticket.id}"
-      find_button('Add reply').click
+      open_article_dialog
 
       find_select('Visibility', visible: :all).select_option('Public')
 
@@ -48,10 +55,7 @@ RSpec.describe 'Mobile > Ticket > Create article', app: :mobile, authenticated_a
       expect(text).to have_text_value('', exact: true)
       text.type('This is a note!')
 
-      find_button('Done').click
-      find_button('Save ticket').click
-
-      wait_for_ticket_edit
+      save_article
 
       expect(Ticket::Article.last).to have_attributes(
         type_id:  Ticket::Article::Type.lookup(name: 'note').id,
@@ -113,9 +117,7 @@ RSpec.describe 'Mobile > Ticket > Create article', app: :mobile, authenticated_a
     end
 
     it 'changes ticket data together with the article' do
-      visit "/tickets/#{ticket.id}"
-
-      find_button('Add reply').click
+      open_article_dialog
 
       find_editor('Text').type('This is a note!')
 
@@ -137,6 +139,53 @@ RSpec.describe 'Mobile > Ticket > Create article', app: :mobile, authenticated_a
       )
     end
 
+    context 'when creating a phone article' do
+      it 'creates a phone article' do
+        open_article_dialog
+
+        find_select('Article Type', visible: :all).select_option('Phone')
+
+        text = find_editor('Text')
+        expect(text).to have_text_value('', exact: true)
+        text.type('This is a note!')
+
+        save_article
+
+        expect(Ticket::Article.last).to have_attributes(
+          type_id:  Ticket::Article::Type.lookup(name: 'phone').id,
+          internal: false,
+          body:     '<p>This is a note!</p>',
+        )
+      end
+
+      it 'creates a phone article with attachments' do
+        open_article_dialog
+
+        find_select('Article Type', visible: :all).select_option('Phone')
+
+        text = find_editor('Text')
+        expect(text).to have_text_value('', exact: true)
+        text.type('This is a note!')
+
+        find_field('attachments', visible: :all).attach_file('spec/fixtures/files/image/small.png')
+
+        # need to wait until the file is uploaded
+        expect(page).to have_text('small.png', wait: 60)
+
+        save_article
+
+        expect(Store.last.filename).to eq('small.png')
+        expect(Ticket::Article.last).to have_attributes(
+          type_id:     Ticket::Article::Type.lookup(name: 'phone').id,
+          internal:    false,
+          body:        '<p>This is a note!</p>',
+          attachments: [
+            Store.last
+          ]
+        )
+      end
+    end
+
     # TODO: test security settings
   end
 end