Maintenance: Refactor Zendesk import tests

This commit is contained in:
Mantas Masalskis 2021-08-26 14:14:40 +02:00 committed by Thorsten Eckel
parent 294e6ba361
commit 6b8655856e
26 changed files with 25545 additions and 689 deletions

View file

@ -5,7 +5,6 @@ include:
- local: '/.gitlab/ci/browser-integration/capybara_ff.yml' - local: '/.gitlab/ci/browser-integration/capybara_ff.yml'
- local: '/.gitlab/ci/browser-integration/idoit_chrome.yml' - local: '/.gitlab/ci/browser-integration/idoit_chrome.yml'
- local: '/.gitlab/ci/browser-integration/otrs_chrome.yml' - local: '/.gitlab/ci/browser-integration/otrs_chrome.yml'
- local: '/.gitlab/ci/browser-integration/zendesk_chrome.yml'
.template_browser-integration_capybara: &template_browser-integration_capybara .template_browser-integration_capybara: &template_browser-integration_capybara
stage: browser-integration stage: browser-integration

View file

@ -1,5 +0,0 @@
zendesk_chrome:
extends:
- .template_browser-integration_import_chrome
variables:
TEST_FILE: "test/integration/zendesk_import_browser_test.rb"

View file

@ -6,7 +6,6 @@ include:
- local: '/.gitlab/ci/integration/otrs.yml' - local: '/.gitlab/ci/integration/otrs.yml'
- local: '/.gitlab/ci/integration/slack.yml' - local: '/.gitlab/ci/integration/slack.yml'
- local: '/.gitlab/ci/integration/user_agent.yml' - local: '/.gitlab/ci/integration/user_agent.yml'
- local: '/.gitlab/ci/integration/zendesk.yml'
.template_integration: &template_integration .template_integration: &template_integration
extends: extends:

View file

@ -1,6 +0,0 @@
zendesk:
extends:
- .template_integration
script:
- bundle exec rake zammad:db:unseeded
- bundle exec rails test test/integration/zendesk_import_test.rb

View file

@ -20,6 +20,10 @@ include:
- bundle exec rake zammad:db:init - bundle exec rake zammad:db:init
- bundle exec rspec --exclude-pattern "spec/{system,integration}/**/*_spec.rb" -t ~searchindex -t db_strategy:reset - bundle exec rspec --exclude-pattern "spec/{system,integration}/**/*_spec.rb" -t ~searchindex -t db_strategy:reset
# RSpec 3rd party integration tests are independent of the database
# therefore we need only one job and choose a random database for each run
# Optionally pass INTEGRATION_TESTS=enabled to run them in private- branch
rspec:integration: rspec:integration:
stage: test stage: test
extends: extends:
@ -28,6 +32,13 @@ rspec:integration:
- .rules_integration_manual_start - .rules_integration_manual_start
variables: variables:
RAILS_ENV: "test" RAILS_ENV: "test"
rules:
- if: $CI_MERGE_REQUEST_ID
when: never
- if: '$CI_COMMIT_BRANCH =~ /^private/ && $INTEGRATION_TESTS != "enabled"'
when: manual
allow_failure: true
- when: always
script: script:
- bundle exec rake zammad:db:init - bundle exec rake zammad:db:init
- bundle exec rspec -t type:integration - bundle exec rspec -t type:integration

View file

@ -15,6 +15,7 @@ class Sequencer
{ {
login: login, login: login,
firstname: resource.name, firstname: resource.name,
lastname: '', # makes sure name guessing is triggered for updating existing users. Which happens when importing a big list of users due to overlapping pagination.
email: resource.email, email: resource.email,
phone: resource.phone, phone: resource.phone,
password: password, password: password,

View file

@ -0,0 +1,71 @@
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
require 'rails_helper'
RSpec.describe 'Zendesk import', type: :integration, use_vcr: true, db_strategy: :reset, required_envs: %w[IMPORT_ZENDESK_ENDPOINT IMPORT_ZENDESK_ENDPOINT_KEY IMPORT_ZENDESK_ENDPOINT_USERNAME] do # rubocop:disable RSpec/DescribeClass
let(:job) { ImportJob.last }
before do
Setting.set('import_zendesk_endpoint', ENV['IMPORT_ZENDESK_ENDPOINT'])
Setting.set('import_zendesk_endpoint_key', ENV['IMPORT_ZENDESK_ENDPOINT_KEY'])
Setting.set('import_zendesk_endpoint_username', ENV['IMPORT_ZENDESK_ENDPOINT_USERNAME'])
Setting.set('import_mode', true)
Setting.set('system_init_done', false)
VCR.use_cassette 'zendesk_import' do
ImportJob.create(name: 'Import::Zendesk').start
end
end
context 'when performing the full Zendesk import' do
let(:job) { ImportJob.last }
let(:expected_stats) do
{
'Groups' => {
'skipped' => 0,
'created' => 2,
'updated' => 0,
'unchanged' => 0,
'failed' => 0,
'deactivated' => 0,
'sum' => 2,
'total' => 2,
},
'Users' => {
'skipped' => 0,
'created' => 142,
'updated' => 1,
'unchanged' => 0,
'failed' => 0,
'deactivated' => 0,
'sum' => 143,
'total' => 143,
},
'Organizations' => {
'skipped' => 0,
'created' => 1,
'updated' => 0,
'unchanged' => 1,
'failed' => 0,
'deactivated' => 0,
'sum' => 2,
'total' => 2,
},
'Tickets' => {
'skipped' => 1,
'created' => 142,
'updated' => 2,
'unchanged' => 0,
'failed' => 0,
'deactivated' => 0,
'sum' => 145,
'total' => 145,
},
}
end
it 'imports the correct number of expected objects' do
expect(job.result).to eq expected_stats
end
end
end

View file

@ -0,0 +1,63 @@
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
require 'rails_helper'
require 'zendesk_api'
RSpec.describe ::Sequencer::Sequence::Import::Zendesk::Group, sequencer: :sequence do
context 'when importing groups from Zendesk' do
let(:base_resource) do
ZendeskAPI::Group.new(
nil,
{
'id' => 24_165_105,
'name' => 'Additional Group',
'description' => '',
'default' => false,
'created_at' => '2015-12-04 13:11:59 UTC',
'updated_at' => '2015-12-04 13:11:59 UTC'
}
)
end
let(:process_payload) do
{
import_job: build_stubbed(:import_job, name: 'Import::Zendesk', payload: {}),
dry_run: false,
resource: resource,
field_map: {},
}
end
context 'with active group' do
let(:resource) do
base_resource.merge('deleted' => false)
end
it 'adds groups' do # rubocop:disable RSpec/MultipleExpectations
expect { process(process_payload) }.to change(Group, :count).by(1)
expect(Group.last).to have_attributes(
name: 'Additional Group',
active: true,
)
end
end
context 'with inactive group' do
let(:resource) do
base_resource.merge('deleted' => true)
end
it 'adds groups' do # rubocop:disable RSpec/MultipleExpectations
expect { process(process_payload) }.to change(Group, :count).by(1)
expect(Group.last).to have_attributes(
name: 'Additional Group',
active: false,
)
end
end
end
end

View file

@ -0,0 +1,44 @@
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
require 'rails_helper'
require 'zendesk_api'
RSpec.describe ::Sequencer::Sequence::Import::Zendesk::OrganizationField, sequencer: :sequence do
context 'when trying to import organization fields from Zendesk', db_strategy: :reset do
let(:process_payload) do
{
import_job: build_stubbed(:import_job, name: 'Import::Zendesk', payload: {}),
dry_run: false,
resource: resource,
field_map: {},
}
end
let(:resource) do
ZendeskAPI::OrganizationField.new(
nil,
{
'id' => 207_489,
'type' => 'text',
'key' => 'api_key',
'title' => 'API Key',
'description' => 'Der API Key für externe Zugriffe.',
'raw_title' => 'API Key',
'raw_description' => 'Der API Key für externe Zugriffe.',
'position' => 0,
'active' => true,
'system' => false,
'regexp_for_validation' => nil,
'created_at' => '2015-12-04 11:24:08 UTC',
'updated_at' => '2015-12-04 11:24:08 UTC'
}
)
end
it 'adds custom fields' do
expect { process(process_payload) }.to change(Organization, :column_names).by(['api_key'])
end
end
end

View file

@ -0,0 +1,78 @@
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
require 'rails_helper'
require 'zendesk_api'
RSpec.describe ::Sequencer::Sequence::Import::Zendesk::Organization, sequencer: :sequence, db_strategy: :reset do
context 'when importing organizations from Zendesk' do
let(:resource) do
ZendeskAPI::Organization.new(
nil,
{
'id' => 154_755_561,
'name' => 'Test Foundation',
'shared_tickets' => false,
'shared_comments' => false,
'external_id' => nil,
'created_at' => '2015-07-19 22:41:40 UTC',
'updated_at' => '2016-05-19 12:24:21 UTC',
'domain_names' => [],
'details' => '',
'notes' => '',
'group_id' => nil,
'tags' => ['b'],
'organization_fields' => {
'api_key' => 'my api öäüß',
'custom_dropdown' => 'b'
},
'deleted_at' => nil
}
)
end
let(:field_map) do
{
'Organization' => {
'api_key' => 'api_key',
'custom_dropdown' => 'custom_dropdown',
}
}
end
let(:process_payload) do
{
import_job: build_stubbed(:import_job, name: 'Import::Zendesk', payload: {}),
dry_run: false,
resource: resource,
field_map: field_map,
}
end
let(:imported_organization) do
{
name: 'Test Foundation',
note: nil,
domain: '',
api_key: 'my api öäüß',
custom_dropdown: 'b'
}
end
before do
create :object_manager_attribute_select, object_name: 'Organization', name: 'custom_dropdown'
create :object_manager_attribute_text, object_name: 'Organization', name: 'api_key'
ObjectManager::Attribute.migration_execute
end
it 'increased organization count' do
expect { process(process_payload) }.to change(Organization, :count).by(1)
end
it 'adds correct organization data' do
process(process_payload)
expect(Organization.last).to have_attributes(imported_organization)
end
end
end

View file

@ -0,0 +1,130 @@
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
require 'rails_helper'
require 'zendesk_api'
RSpec.describe ::Sequencer::Sequence::Import::Zendesk::Ticket::Comment, sequencer: :sequence, db_strategy: :reset, required_envs: %w[IMPORT_ZENDESK_ENDPOINT] do
let(:hostname) { URI.parse(ENV['IMPORT_ZENDESK_ENDPOINT']).hostname }
context 'when importing ticket comments from Zendesk' do
let(:customer) { create(:customer) }
let(:ticket) { create(:ticket) }
let(:resource) do
ZendeskAPI::Ticket::Comment.new(
nil,
{
'id' => 31_964_468_581,
'type' => 'Comment',
'author_id' => 1_150_734_731,
'body' => 'This is the latest comment for this ticket. You also changed the ticket status to Pending.',
'html_body' => '<div class="zd-comment" dir="auto"><p dir="auto">This is the latest comment for this ticket. You also changed the ticket status to Pending.</p></div>',
'plain_body' => 'This is the latest comment for this ticket. You also changed the ticket status to Pending.',
'public' => true,
'attachments' => [
{
'id' => 1_282_310_719,
'file_name' => '1a3496b9-53d9-494d-bbb0-e1d2e22074f8.jpeg',
'content_url' => "https://#{hostname}/attachments/token/khRQTQjm8ODhA0FjbS39i4xOb/?name=1a3496b9-53d9-494d-bbb0-e1d2e22074f8.jpeg",
'mapped_content_url' => "https://#{hostname}/attachments/token/khRQTQjm8ODhA0FjbS39i4xOb/?name=1a3496b9-53d9-494d-bbb0-e1d2e22074f8.jpeg",
'content_type' => 'image/jpeg',
'size' => 164_934,
'width' => 1600,
'height' => 1200,
'inline' => false,
'deleted' => false,
'thumbnails' => []
}
],
'audit_id' => 31_964_468_571,
'via' => {
'channel' => 'email',
'source' => {
'from' => {
'address' => 'john.doe@example.com',
'name' => 'John Doe',
'original_recipients' => [
'zendesk@example.com'
]
},
'to' => {
'name' => 'Znuny',
'address' => 'zendesk@example.com'
},
'rel' => nil
},
},
'created_at' => '2015-07-19 22:41:44 UTC',
'metadata' => {
'system' => {},
'custom' => {}
}
}
)
end
let(:user_map) do
{
1_150_734_731 => customer.id,
}
end
let(:process_payload) do
{
import_job: build_stubbed(:import_job, name: 'Import::Zendesk', payload: {}),
dry_run: false,
instance: ticket,
resource: resource,
user_map: user_map,
}
end
let(:imported_article) do
{
from: 'john.doe@example.com',
to: 'zendesk@example.com',
body: '<div dir="auto"><p dir="auto">This is the latest comment for this ticket. You also changed the ticket status to Pending.</p></div>'
}
end
let(:imported_attachment) do
{
'filename' => '1a3496b9-53d9-494d-bbb0-e1d2e22074f8.jpeg',
'size' => '3',
'preferences' => {
'Content-Type' => 'image/jpeg',
'resizable' => false,
'content_preview' => true,
}
}
end
before do
stub_request(:get, "https://#{hostname}/attachments/token/khRQTQjm8ODhA0FjbS39i4xOb/?name=1a3496b9-53d9-494d-bbb0-e1d2e22074f8.jpeg").to_return(status: 200, body: '123', headers: {})
end
context 'with an email article' do
it 'imports article correctly' do
expect { process(process_payload) }.to change(Ticket::Article, :count).by(1)
end
it 'imports ticket data correctly' do
process(process_payload)
expect(Ticket::Article.last).to have_attributes(imported_article)
end
it 'adds correct number of attachments' do
process(process_payload)
expect(Ticket::Article.last.attachments.size).to eq 1
end
it 'adds attachment content' do
process(process_payload)
expect(Ticket::Article.last.attachments.last).to have_attributes(imported_attachment)
end
end
end
end

View file

@ -0,0 +1,193 @@
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
require 'rails_helper'
require 'zendesk_api'
RSpec.describe ::Sequencer::Sequence::Import::Zendesk::TicketField, sequencer: :sequence do
context 'when trying to import ticket fields from Zendesk', db_strategy: :reset do
let(:process_payload) do
{
import_job: build_stubbed(:import_job, name: 'Import::Zendesk', payload: {}),
dry_run: false,
resource: resource,
field_map: {},
}
end
let(:base_resource) do
{
'id' => 24_656_189,
'raw_title' => 'Custom Decimal',
'description' => 'A custom Decimal field',
'raw_description' => 'A custom Decimal field',
'position' => 7,
'active' => true,
'required' => true,
'collapsed_for_agents' => false,
'regexp_for_validation' => '\\A[-+]?[0-9]*[.,]?[0-9]+\\z',
'title_in_portal' => 'Custom Decimal',
'raw_title_in_portal' => 'Custom Decimal',
'visible_in_portal' => true,
'editable_in_portal' => true,
'required_in_portal' => true,
'tag' => nil,
'created_at' => '2015-12-15 12:08:26 UTC',
'updated_at' => '2015-12-15 12:22:30 UTC',
'removable' => true,
'agent_description' => nil
}
end
context 'when field is a decimal' do
let(:resource) do
ZendeskAPI::TicketField.new(
nil,
base_resource.merge(
{
'title' => 'Custom Decimal',
'type' => 'decimal',
}
)
)
end
it 'adds a custom field' do
expect { process(process_payload) }.to change(Ticket, :column_names).by(['custom_decimal'])
end
end
context 'when field is a checkbox' do
let(:resource) do
ZendeskAPI::TicketField.new(
nil,
base_resource.merge(
{
'title' => 'Custom Checkbox',
'type' => 'checkbox',
}
)
)
end
it 'adds a custom field' do
expect { process(process_payload) }.to change(Ticket, :column_names).by(['custom_checkbox'])
end
end
context 'when field is a date' do
let(:resource) do
ZendeskAPI::TicketField.new(
nil,
base_resource.merge(
{
'title' => 'Custom Date',
'type' => 'date',
}
)
)
end
it 'adds a custom field' do
expect { process(process_payload) }.to change(Ticket, :column_names).by(['custom_date'])
end
end
context 'when field is an integer' do
let(:resource) do
ZendeskAPI::TicketField.new(
nil,
base_resource.merge(
{
'title' => 'Custom Integer',
'type' => 'integer',
}
)
)
end
it 'adds a custom field' do
expect { process(process_payload) }.to change(Ticket, :column_names).by(['custom_integer'])
end
end
context 'when field is a regex' do
let(:resource) do
ZendeskAPI::TicketField.new(
nil,
base_resource.merge(
{
'title' => 'Custom Regex',
'type' => 'regexp',
}
)
)
end
it 'adds a custom field' do
expect { process(process_payload) }.to change(Ticket, :column_names).by(['custom_regex'])
end
end
context 'when field is a dropdown' do
let(:resource) do
ZendeskAPI::TicketField.new(
nil,
base_resource.merge(
{
'title' => 'Custom Dropdown',
'type' => 'dropdown',
'custom_field_options' => [
{
'id' => 28_353_445,
'name' => 'Another Value',
'raw_name' => 'Another Value',
'value' => 'anotherkey',
'default' => false
},
{
'id' => 28_353_425,
'name' => 'Value 1',
'raw_name' => 'Value 1',
'value' => 'key1',
'default' => false
},
{
'id' => 28_353_435,
'name' => 'Value 2',
'raw_name' => 'Value 2',
'value' => 'key2',
'default' => false
}
]
}
)
)
end
it 'adds a custom field' do
expect { process(process_payload) }.to change(Ticket, :column_names).by(['custom_dropdown'])
end
end
context 'when field is unknown' do
let(:resource) do
ZendeskAPI::TicketField.new(
nil,
base_resource.merge(
{
'title' => 'Custom Unknown',
'type' => 'unknown',
}
)
)
end
it 'does not add a custom field' do
expect { process(process_payload) }.not_to change(Ticket, :column_names)
end
end
end
end

View file

@ -0,0 +1,168 @@
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
require 'rails_helper'
require 'zendesk_api'
RSpec.describe ::Sequencer::Sequence::Import::Zendesk::Ticket, sequencer: :sequence, db_strategy: :reset do
context 'when importing tickets from Zendesk' do
let(:group) { create(:group) }
let(:owner) { create(:agent, group_ids: [group.id]) }
let(:customer) { create(:customer) }
let(:resource) do
ZendeskAPI::Ticket.new(
nil,
{
'id' => 2,
'external_id' => nil,
'via' => {
'channel' => 'email',
'source' => {
'from' => {
'address' => 'john.doe@example.com',
'name' => 'John Doe'
},
'to' => {
'name' => 'Zendesk',
'address' => 'zendesk-user@example.com'
},
'rel' => nil
}
},
'created_at' => '2015-07-19 22:44:20 UTC',
'updated_at' => '2016-05-19 14:00:42 UTC',
'type' => 'question',
'subject' => 'test',
'raw_subject' => 'test',
'description' => 'test email',
'priority' => 'urgent',
'status' => 'pending',
'recipient' => 'zendesk-user@example.com',
'requester_id' => 1_202_726_611,
'submitter_id' => 1_147_801_812,
'assignee_id' => 1_150_734_731,
'organization_id' => 154_755_561,
'group_id' => 24_554_931,
'collaborator_ids' => [],
'follower_ids' => [],
'email_cc_ids' => [],
'forum_topic_id' => nil,
'problem_id' => nil,
'has_incidents' => false,
'is_public' => true,
'due_at' => nil,
'tags' => %w[
anothertag
import
key2
newtag
otrs
znuny
],
'custom_fields' => [
{ 'id' => 1001,
'value' => '1.6' },
{ 'id' => 1002,
'value' => true },
],
'satisfaction_rating' => nil,
'sharing_agreement_ids' => [],
'fields' => [
{ 'id' => 1001,
'value' => '1.6' },
{ 'id' => 1002,
'value' => true },
],
'followup_ids' => [],
'brand_id' => 670_701,
'allow_channelback' => false,
'allow_attachments' => true,
'generated_timestamp' => 1_463_666_442
}
)
end
let(:group_map) do
{
24_554_931 => group.id,
}
end
let(:user_map) do
{
1_150_734_731 => owner.id,
1_202_726_611 => customer.id,
}
end
let(:organization_map) do
{}
end
let(:ticket_field_map) do
{
1001 => 'custom_dropdown',
1002 => 'custom_checkbox',
}
end
let(:process_payload) do
{
import_job: build_stubbed(:import_job, name: 'Import::Zendesk', payload: {}),
dry_run: false,
resource: resource,
group_map: group_map,
user_map: user_map,
organization_map: organization_map,
ticket_field_map: ticket_field_map,
}
end
let(:imported_ticket) do
{
title: 'test',
note: nil,
create_article_type_id: 1,
create_article_sender_id: 2,
article_count: nil,
state_id: 3,
group_id: group.id,
priority_id: 3,
owner_id: owner.id,
customer_id: customer.id,
custom_dropdown: '1.6',
custom_checkbox: true,
}
end
before do
create :object_manager_attribute_select, object_name: 'Ticket', name: 'custom_dropdown'
create :object_manager_attribute_boolean, object_name: 'Ticket', name: 'custom_checkbox'
ObjectManager::Attribute.migration_execute
# We only want to test here the Ticket API, so disable other modules in the sequence
# that make their own HTTP requests.
custom_sequence = Sequencer::Sequence::Import::Zendesk::Ticket.sequence.dup
custom_sequence.delete('Import::Zendesk::Ticket::Comments')
custom_sequence.delete('Import::Zendesk::Ticket::Tags')
allow(Sequencer::Sequence::Import::Zendesk::Ticket).to receive(:sequence) { custom_sequence }
end
context 'with email ticket' do
it 'imports user correctly (increased ticket count)' do
expect { process(process_payload) }.to change(Ticket, :count).by(1)
end
it 'imports ticket data correctly' do
process(process_payload)
expect(Ticket.last).to have_attributes(imported_ticket)
end
end
end
end

View file

@ -0,0 +1,46 @@
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
require 'rails_helper'
require 'zendesk_api'
RSpec.describe ::Sequencer::Sequence::Import::Zendesk::UserField, sequencer: :sequence do
context 'when trying to import user fields from Zendesk', db_strategy: :reset do
let(:process_payload) do
{
import_job: build_stubbed(:import_job, name: 'Import::Zendesk', payload: {}),
dry_run: false,
resource: resource,
field_map: {},
}
end
let(:resource) do
ZendeskAPI::UserField.new(
nil,
{
'id' => 206_315,
'type' => 'text',
'key' => 'lieblingstier',
'title' => 'Lieblingstier',
'description' => "Hund,
Katze oder Maus?",
'raw_title' => 'Lieblingstier',
'raw_description' => "Hund,
Katze oder Maus?",
'position' => 0,
'active' => true,
'system' => false,
'regexp_for_validation' => nil,
'created_at' => '2015-12-04 11:05:45 UTC',
'updated_at' => '2015-12-04 11:05:45 UTC'
}
)
end
it 'adds user fields' do
expect { process(process_payload) }.to change(User, :column_names).by(['lieblingstier'])
end
end
end

View file

@ -0,0 +1,148 @@
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
require 'rails_helper'
require 'zendesk_api'
RSpec.describe ::Sequencer::Sequence::Import::Zendesk::User, sequencer: :sequence, db_strategy: :reset do
context 'when importing users from Zendesk' do
let(:groups) do
create_list(:group, 3)
end
let(:merge_resource) do
{}
end
let(:resource) do
ZendeskAPI::User.new(
nil,
{
'id' => 1_150_734_731,
'name' => 'Bob Smith',
'email' => 'zendesk-user@example.com',
'created_at' => '2015-07-19 22:41:41 UTC',
'updated_at' => '2021-08-19 13:40:25 UTC',
'time_zone' => 'Berlin',
'iana_time_zone' => 'Europe/Berlin',
'phone' => '00114124',
'shared_phone_number' => true,
'photo' => nil,
'locale_id' => 1,
'locale' => 'en-US',
'organization_id' => 154_755_561,
'role' => 'admin',
'verified' => true,
'external_id' => nil,
'tags' => ['2'],
'alias' => '',
'active' => true,
'shared' => false,
'shared_agent' => false,
'last_login_at' => '2021-08-19 13:40:25 UTC',
'two_factor_auth_enabled' => false,
'signature' => '',
'details' => '',
'notes' => '',
'role_type' => nil,
'custom_role_id' => nil,
'moderator' => true,
'ticket_restriction' => nil,
'only_private_comments' => false,
'restricted_agent' => false,
'suspended' => false,
'default_group_id' => 1002,
'report_csv' => true,
'user_fields' => {
'custom_dropdown' => '2',
'lieblingstier' => 'Hundä'
}
}.merge(merge_resource)
)
end
let(:group_map) do
{
1001 => groups[0].id,
1002 => groups[1].id,
1003 => groups[2].id,
}
end
let(:user_group_map) do
{
1_150_734_731 => [1001, 1002, 1003]
}
end
let(:organization_map) do
{}
end
let(:process_payload) do
{
import_job: build_stubbed(:import_job, name: 'Import::Zendesk', payload: {}),
dry_run: false,
resource: resource,
group_map: group_map,
user_group_map: user_group_map,
organization_map: organization_map,
}
end
let(:imported_user) do
{
firstname: 'Bob',
lastname: 'Smith',
login: 'zendesk-user@example.com',
email: 'zendesk-user@example.com',
active: true,
last_login: DateTime.parse('2021-08-19T13:40:25Z'),
}
end
before do
create :object_manager_attribute_select, object_name: 'User', name: 'custom_dropdown'
create :object_manager_attribute_text, object_name: 'User', name: 'lieblingstier'
ObjectManager::Attribute.migration_execute
end
context 'with admin user' do
it 'imports user correctly (increased user count)' do
expect { process(process_payload) }.to change(User, :count).by(1)
end
it 'imports user data correctly' do
process(process_payload)
expect(User.last).to have_attributes(imported_user)
end
it 'sets user roles correctly for admin user' do
process(process_payload)
expect(User.last.roles.sort.map(&:name)).to eq %w[Admin Agent]
end
end
context 'with agent user' do
let(:merge_resource) do
{
'role' => 'agent',
'restricted_agent' => true,
}
end
it 'sets user roles correctly for non-admin user' do
process(process_payload)
expect(User.last.roles.sort.map(&:name)).to eq ['Agent']
end
it 'sets user groups correctly ' do
process(process_payload)
expect(User.last.groups_access('full').sort).to eq groups
end
end
end
end

View file

@ -0,0 +1,11 @@
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
VCR.configure do |c|
# The API key is used only inside the base64 encoded Basic Auth string, so mask that as well.
c.filter_sensitive_data('<IMPORT_ZENDESK_ENDPOINT_BASIC_AUTH>') { Base64.encode64("#{ENV['IMPORT_ZENDESK_ENDPOINT_USERNAME']}/token:#{ENV['IMPORT_ZENDESK_ENDPOINT_KEY']}").lines(chomp: true).join }
# The hostname of the Zendesk endpoint URL used as well
if ENV['IMPORT_ZENDESK_ENDPOINT'].present?
c.filter_sensitive_data('<IMPORT_ZENDESK_ENDPOINT_HOSTNAME>') { URI.parse(ENV['IMPORT_ZENDESK_ENDPOINT']).hostname }
end
end

View file

@ -0,0 +1,127 @@
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
require 'rails_helper'
RSpec.describe 'Import Zendesk', type: :system, set_up: false, authenticated_as: false, required_envs: %w[IMPORT_ZENDESK_ENDPOINT IMPORT_ZENDESK_ENDPOINT_KEY IMPORT_ZENDESK_ENDPOINT_USERNAME] do
import_zendesk_url = ENV['IMPORT_ZENDESK_ENDPOINT'].remove(%r{/api/v2/?})
describe 'fields validation', :use_vcr do
before do
visit '#import'
find('.js-zendesk').click
end
let(:url_field) { find('#zendesk-url') }
let(:email_field) { find('#zendesk-email') }
let(:token_field) { find('#zendesk-api-token') }
it 'invalid hostname' do
url_field.fill_in with: 'https://reallybadexample.zendesk.com/'
expect(page).to have_css('.zendesk-url-error', text: 'Hostname not found!')
end
it 'valid hostname' do
url_field.fill_in with: 'https://reallybadexample.zendesk.com/'
# wait for error to appear to validate it's hidden successfully
find('.zendesk-url-error', text: 'Hostname not found!')
url_field.fill_in with: import_zendesk_url
expect(page).to have_no_css('.zendesk-url-error', text: 'Hostname not found!')
end
it 'invalid credentials' do
url_field.fill_in with: import_zendesk_url
find('.js-zendesk-credentials').click
email_field.fill_in with: ENV['IMPORT_ZENDESK_ENDPOINT_USERNAME']
token_field.fill_in with: '1nv4l1dT0K3N'
expect(page).to have_css('.zendesk-api-token-error', text: 'Invalid credentials!')
end
it 'valid credentials' do
url_field.fill_in with: import_zendesk_url
find('.js-zendesk-credentials').click
email_field.fill_in with: ENV['IMPORT_ZENDESK_ENDPOINT_USERNAME']
token_field.fill_in with: '1nv4l1dT0K3N'
# wait for error to appear to validate it's hidden successfully
expect(page).to have_css('.zendesk-api-token-error', text: 'Invalid credentials!')
token_field.fill_in with: ENV['IMPORT_ZENDESK_ENDPOINT_KEY']
expect(page).to have_no_css('.zendesk-api-token-error', text: 'Invalid credentials!')
end
it 'shows start button' do
url_field.fill_in with: import_zendesk_url
find('.js-zendesk-credentials').click
email_field.fill_in with: ENV['IMPORT_ZENDESK_ENDPOINT_USERNAME']
token_field.fill_in with: ENV['IMPORT_ZENDESK_ENDPOINT_KEY']
expect(page).to have_css('.js-migration-start')
end
end
describe 'import progress', :use_vcr do
let(:url_field) { find('#zendesk-url') }
let(:email_field) { find('#zendesk-email') }
let(:token_field) { find('#zendesk-api-token') }
let(:job) { ImportJob.find_by(name: 'Import::Zendesk') }
before do
VCR.use_cassette 'system/import/zendesk/import_progress_setup' do
visit '#import'
find('.js-zendesk').click
url_field.fill_in with: import_zendesk_url
find('.js-zendesk-credentials').click
email_field.fill_in with: ENV['IMPORT_ZENDESK_ENDPOINT_USERNAME']
token_field.fill_in with: ENV['IMPORT_ZENDESK_ENDPOINT_KEY']
find('.js-migration-start').click
await_empty_ajax_queue
end
end
it 'shows groups progress' do
job.update! result: { Groups: { sum: 3, total: 5 } }
expect(page).to have_css('.js-groups .js-done', text: '3')
.and(have_css('.js-groups .js-total', text: '5'))
end
it 'shows users progress' do
job.update! result: { Users: { sum: 5, total: 9 } }
expect(page).to have_css('.js-users .js-done', text: '5')
.and(have_css('.js-users .js-total', text: '9'))
end
it 'shows organizations progress' do
job.update! result: { Organizations: { sum: 3, total: 5 } }
expect(page).to have_css('.js-organizations .js-done', text: '3')
.and(have_css('.js-organizations .js-total', text: '5'))
end
it 'shows tickets progress' do
job.update! result: { Tickets: { sum: 3, total: 5 } }
expect(page).to have_css('.js-tickets .js-done', text: '3')
.and(have_css('.js-tickets .js-total', text: '5'))
end
it 'shows login after import is finished' do
job.update! finished_at: Time.zone.now
Rake::Task['zammad:setup:auto_wizard'].execute
expect(page).to have_text('Login')
end
end
end

View file

@ -0,0 +1,162 @@
---
http_interactions:
- request:
method: get
uri: "<IMPORT_ZENDESK_ENDPOINT>/users/me"
body:
encoding: US-ASCII
string: ''
headers:
Accept-Encoding:
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
Accept:
- "*/*"
User-Agent:
- Zammad User Agent
Host:
- "<IMPORT_ZENDESK_ENDPOINT_HOSTNAME>"
response:
status:
code: 200
message: OK
headers:
Date:
- Fri, 20 Aug 2021 13:25:35 GMT
Content-Type:
- application/json; charset=UTF-8
Transfer-Encoding:
- chunked
Connection:
- keep-alive
X-Zendesk-Api-Version:
- v2
X-Zendesk-Application-Version:
- v9449
X-Frame-Options:
- SAMEORIGIN
Access-Control-Expose-Headers:
- X-Zendesk-API-Warn
Vary:
- origin
X-Rate-Limit:
- '700'
X-Rate-Limit-Remaining:
- '699'
Strict-Transport-Security:
- max-age=31536000;
Etag:
- W/"f78a8c8899c1d69692fccbc4fb2c11b8"
Cache-Control:
- max-age=0, private, must-revalidate
X-Zendesk-Origin-Server:
- classic-app-server-5d8ffc66d-hngbj
X-Request-Id:
- 681bf2d18a85dfbb-FRA
- 681bf2d18a85dfbb-FRA
X-Runtime:
- '0.066324'
X-Zendesk-Zorg:
- 'yes'
X-Content-Type-Options:
- nosniff
Cf-Cache-Status:
- DYNAMIC
Expect-Ct:
- max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
Report-To:
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=vQfoszvrH3gqC%2BwX1TPZPuDzuJGbgeu%2F%2BAa0GOdil%2BJ%2B7OfktRqE65Es5HoX00AO56wvj8JgiJhEPT%2FVcZ47AfyAz3Nl7fRjLcW6qB9wqwqmO656mXQW6R%2BsnBWXjCebrh8Vlx%2FgHA%3D%3D"}],"group":"cf-nel","max_age":604800}'
Nel:
- '{"success_fraction":0,"report_to":"cf-nel","max_age":604800}'
Set-Cookie:
- __cfruid=5f7114429ea2a90d53065f81323c095ba659763c-1629465935; path=/; domain=.<IMPORT_ZENDESK_ENDPOINT_HOSTNAME>;
HttpOnly; Secure; SameSite=None
Server:
- cloudflare
Cf-Ray:
- 681bf2d18a85dfbb-FRA
body:
encoding: ASCII-8BIT
string: '{"user":{"id":null,"url":null,"name":"Nicht registrierter Benutzer","email":"invalid@example.com","created_at":null,"updated_at":null,"time_zone":"Berlin","iana_time_zone":"Europe/Berlin","phone":null,"shared_phone_number":null,"photo":null,"locale_id":8,"locale":"de","organization_id":null,"role":"end-user","verified":false,"authenticity_token":"lncIvg7hwd/fd8WQInmMbDvQXlG5ZFIe5kiXSSp/evt4PmhR+OqhsSSLT0568tvlpsAzQbglbwddFit52KQWBA=="}}'
recorded_at: Fri, 20 Aug 2021 13:25:35 GMT
- request:
method: get
uri: "<IMPORT_ZENDESK_ENDPOINT>/users/me"
body:
encoding: US-ASCII
string: ''
headers:
Accept:
- application/json
Accept-Encoding:
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
User-Agent:
- ZendeskAPI Ruby 1.32.0
Authorization:
- Basic <IMPORT_ZENDESK_ENDPOINT_BASIC_AUTH>
response:
status:
code: 200
message: OK
headers:
Date:
- Fri, 20 Aug 2021 13:25:37 GMT
Content-Type:
- application/json; charset=UTF-8
Transfer-Encoding:
- chunked
Connection:
- keep-alive
X-Zendesk-Api-Version:
- v2
X-Zendesk-Application-Version:
- v9449
X-Frame-Options:
- SAMEORIGIN
Access-Control-Expose-Headers:
- X-Zendesk-API-Warn
Vary:
- origin
X-Rate-Limit:
- '700'
X-Rate-Limit-Remaining:
- '698'
Strict-Transport-Security:
- max-age=31536000;
Etag:
- W/"9e89bffdaf7d59aacb215983a217e728"
Cache-Control:
- max-age=0, private, must-revalidate
X-Zendesk-Origin-Server:
- classic-app-server-5d8ffc66d-hcn9g
X-Request-Id:
- 681bf2dc5e4205dc-FRA
- 681bf2dc5e4205dc-FRA
X-Runtime:
- '0.193922'
X-Zendesk-Zorg:
- 'yes'
Content-Encoding:
- gzip
X-Content-Type-Options:
- nosniff
Cf-Cache-Status:
- DYNAMIC
Expect-Ct:
- max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
Report-To:
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=v%2Fi8h0aIQWVfVGv%2BwX6KxG3FGMTtnsvfI2suZQpUwBkhAcswCkqkS0od18KEtx8dSTeqZiuMPjOnce2oWSX%2FGd4AjGRXl5sCftpeC%2FyvSqEn9xkShmfLrxG4hisfxgokGqb1UwVc5w%3D%3D"}],"group":"cf-nel","max_age":604800}'
Nel:
- '{"success_fraction":0,"report_to":"cf-nel","max_age":604800}'
Set-Cookie:
- __cfruid=9d3985522b245e1dcce78514511401e7c9df0689-1629465937; path=/; domain=.<IMPORT_ZENDESK_ENDPOINT_HOSTNAME>;
HttpOnly; Secure; SameSite=None
Server:
- cloudflare
Cf-Ray:
- 681bf2dc5e4205dc-FRA
body:
encoding: ASCII-8BIT
string: !binary |-
H4sIAAAAAAAAA21T224aMRT8lcqvBfYCG8hKkUqSKm2aIFFIW6WqLC97WFy89tY+hkCUv+mf9Md6zCVJpUo8sPZ4zsx4/Mi8A8vyRyZLlidJFve7vX43aTFvFcvZArFxeRRttdebBaimswVdglt2ZqaORCOjVRoFChe9HO78dEazFtOiBuI4N8WbSS1xQUtQCxl4C1N0XFh7t2MObLQ7syAQSi6QIGmcZO24305Op2ma9xL63RPGN+VrTJq040E7jadJN0/6eToIGJQ18K3Ru+lglQxqpNCCv955761pIHoGNIv9iThOkl6S9uiMWwhLenY7XPu6CFmh9dBitIaG5dor1WLKzIQCvsvw+EWzQbfvJkRjbCW03AqURu9BWa+fZdkJga1RQaYo653KFVg5l0BE+zHC4wI0ypnEDUezBE3gL1V0fn4zHiyXV5PpFGB0nxXT4tfn629wux7ffp34+d2wmKd4e13iw/rt5ejEDa9Hb2/iy3F01eBgOOpiHY2s+zgYf0r98OLi4rQ6OwsX9IBgtVA7mXtzKCrH8u8sZT9aTCgp6IsRVMxQrkj7Xug+KpbPhXIUzyE5UZH450UlHHJlKqmPV/z/61sbPid2Y3mwz0GLQoVIjtyy0gK9DbmRjhKQSnUQpQ3C4W9IluOmIdjeyMw7NDXfrb/Yq00JVtCwoxMKewnILTi0kjxSlw8ERqsNb6xcUQM5VbYmczTsIOt4IBT4H9vOuya8mhcHJcyFV8gra3yz05L2sqx3Gh6ehcZY5DO3OgoK74tTKVRJwx7ZwUZJ7S3NOvQhpRSUhIKKXjmUoaTsg9fln9/s6enpL3LxpM/kAwAA
recorded_at: Fri, 20 Aug 2021 13:25:37 GMT
recorded_with: VCR 6.0.0

View file

@ -0,0 +1,162 @@
---
http_interactions:
- request:
method: get
uri: "<IMPORT_ZENDESK_ENDPOINT>/users/me"
body:
encoding: US-ASCII
string: ''
headers:
Accept-Encoding:
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
Accept:
- "*/*"
User-Agent:
- Zammad User Agent
Host:
- "<IMPORT_ZENDESK_ENDPOINT_HOSTNAME>"
response:
status:
code: 200
message: OK
headers:
Date:
- Fri, 20 Aug 2021 13:25:24 GMT
Content-Type:
- application/json; charset=UTF-8
Transfer-Encoding:
- chunked
Connection:
- keep-alive
X-Zendesk-Api-Version:
- v2
X-Zendesk-Application-Version:
- v9449
X-Frame-Options:
- SAMEORIGIN
Access-Control-Expose-Headers:
- X-Zendesk-API-Warn
Vary:
- origin
X-Rate-Limit:
- '700'
X-Rate-Limit-Remaining:
- '700'
Strict-Transport-Security:
- max-age=31536000;
Etag:
- W/"749965edc1b2129d5f54e5b512b62501"
Cache-Control:
- max-age=0, private, must-revalidate
X-Zendesk-Origin-Server:
- classic-app-server-5d8ffc66d-svgj9
X-Request-Id:
- 681bf28d78e1d729-FRA
- 681bf28d78e1d729-FRA
X-Runtime:
- '0.065455'
X-Zendesk-Zorg:
- 'yes'
X-Content-Type-Options:
- nosniff
Cf-Cache-Status:
- DYNAMIC
Expect-Ct:
- max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
Report-To:
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=JlwvNIAloI78kb6%2B8AEe9aAJRYLLxCv64UJcTvPOt1nfdFn29rsPuEgffb%2BFAAaeAyjJU%2FL%2FP1JCdatvBTdJpJ%2F3G5X992Gi%2F0dZest7pA%2FOCut83zH37Ywdvo3hvNsyOwVViJqvAw%3D%3D"}],"group":"cf-nel","max_age":604800}'
Nel:
- '{"success_fraction":0,"report_to":"cf-nel","max_age":604800}'
Set-Cookie:
- __cfruid=dc67607203007f704575db608632145c6341b1cc-1629465924; path=/; domain=.<IMPORT_ZENDESK_ENDPOINT_HOSTNAME>;
HttpOnly; Secure; SameSite=None
Server:
- cloudflare
Cf-Ray:
- 681bf28d78e1d729-FRA
body:
encoding: ASCII-8BIT
string: '{"user":{"id":null,"url":null,"name":"Nicht registrierter Benutzer","email":"invalid@example.com","created_at":null,"updated_at":null,"time_zone":"Berlin","iana_time_zone":"Europe/Berlin","phone":null,"shared_phone_number":null,"photo":null,"locale_id":8,"locale":"de","organization_id":null,"role":"end-user","verified":false,"authenticity_token":"TN2leefc4AefbsIvqwLlDhuW0UKdRLMxFyDfgGg8hegNBnWKzq5bWZ8AIMo0Wm2LpuNbfpTow5s29LuRokFwyg=="}}'
recorded_at: Fri, 20 Aug 2021 13:25:24 GMT
- request:
method: get
uri: "<IMPORT_ZENDESK_ENDPOINT>/users/me"
body:
encoding: US-ASCII
string: ''
headers:
Accept:
- application/json
Accept-Encoding:
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
User-Agent:
- ZendeskAPI Ruby 1.32.0
Authorization:
- Basic Ym9iLnNtaXRoQHpudW55LmNvbS90b2tlbjoxbnY0bDFkVDBLM04=
response:
status:
code: 200
message: OK
headers:
Date:
- Fri, 20 Aug 2021 13:25:26 GMT
Content-Type:
- application/json; charset=UTF-8
Transfer-Encoding:
- chunked
Connection:
- keep-alive
X-Zendesk-Api-Version:
- v2
X-Zendesk-Application-Version:
- v9449
X-Frame-Options:
- SAMEORIGIN
Access-Control-Expose-Headers:
- X-Zendesk-API-Warn
Vary:
- origin
X-Rate-Limit:
- '700'
X-Rate-Limit-Remaining:
- '700'
Strict-Transport-Security:
- max-age=31536000;
Etag:
- W/"c16a8e7f40dc49f6c7a5779346f3c773"
Cache-Control:
- max-age=0, private, must-revalidate
X-Zendesk-Origin-Server:
- classic-app-server-5d8ffc66d-pzw6f
X-Request-Id:
- 681bf2984c344ab6-FRA
- 681bf2984c344ab6-FRA
X-Runtime:
- '0.066590'
X-Zendesk-Zorg:
- 'yes'
Content-Encoding:
- gzip
X-Content-Type-Options:
- nosniff
Cf-Cache-Status:
- DYNAMIC
Expect-Ct:
- max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
Report-To:
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=cwUvgYEHOGen9rhZ%2BFsLRQZylLWiDDmn1uoAXDaEOX%2BeA3ySRCVYGcsKyQ5n1pSycw62KiJTtcIdzv3gwm7khxw2eg%2F44822OVVF3wvnmjPfqH2R2U5RIlLRzZ80C69NuNo6PsCdOg%3D%3D"}],"group":"cf-nel","max_age":604800}'
Nel:
- '{"success_fraction":0,"report_to":"cf-nel","max_age":604800}'
Set-Cookie:
- __cfruid=7400e1827f504a7a5cfdaa3cdb9f909042030241-1629465926; path=/; domain=.<IMPORT_ZENDESK_ENDPOINT_HOSTNAME>;
HttpOnly; Secure; SameSite=None
Server:
- cloudflare
Cf-Ray:
- 681bf2984c344ab6-FRA
body:
encoding: ASCII-8BIT
string: !binary |-
H4sIAAAAAAAAA12QW0/CQBCF/wrZ53qPxJKQKApqIFUJWMJLM20HOmUvzbJboIT/7raNxPi2c875cmb2yOwWNesdGaWsJy3nHrOa/z4lCGQ9FlCSmY7GNW2NJtQGdWeA0prKsR5DAeQQRrIETukj7kEUHC8TJZybaASDaQTmXFCk/xRDAqNKybpsgJqTdCCBhOivM7RaFXh1DhRZQ7RbbzPQrqXRImlFXJ/VWk4z6nfgKgGOUX3ug8faybWm6BqVXoOkCgwp2SRaXiteL4YyvWh+y2MlaloRusQK+BY9BtZkKA0lZA6RURuUDtjlOAvnn/7kdpEHi3CyzMvRNI3L+2BUlG/+JA9v8rGYv4ZjOzzA/u76I1geUj9YBbEvqvdNHH8nMz8LDbw8F7vuoqunT92vfp+dTj/YSFq+uAEAAA==
recorded_at: Fri, 20 Aug 2021 13:25:26 GMT
recorded_with: VCR 6.0.0

View file

@ -0,0 +1,72 @@
---
http_interactions:
- request:
method: get
uri: https://reallybadexample.zendesk.com/api/v2/users/me
body:
encoding: US-ASCII
string: ''
headers:
Accept-Encoding:
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
Accept:
- "*/*"
User-Agent:
- Zammad User Agent
Host:
- reallybadexample.zendesk.com
response:
status:
code: 404
message: Not Found
headers:
Date:
- Fri, 20 Aug 2021 13:25:20 GMT
Content-Type:
- application/json; charset=UTF-8
Transfer-Encoding:
- chunked
Connection:
- keep-alive
Strict-Transport-Security:
- max-age=0;
Cache-Control:
- no-cache
X-Zendesk-Origin-Server:
- classic-app-server-687bcbddf6-x7wfr
X-Request-Id:
- 681bf2721fb6176e-FRA
- 681bf2721fb6176e-FRA
X-Runtime:
- '0.010825'
X-Zendesk-Zorg:
- 'yes'
Cf-Cache-Status:
- DYNAMIC
Expect-Ct:
- max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
Set-Cookie:
- __cf_bm=25e43ee2df7527a44ececb61b288b058f3e93618-1629465920-1800-AV0sJMJfHlILXaL3XuAK9Isde5xLN3TIuOcagCSyUKzZUZjl3gq3zXQvk1ZIOlHwNmC7FbC6germXXB+pTmT6Q3w7Fv78hiT4Qxf4huJ5ZeQ;
path=/; expires=Fri, 20-Aug-21 13:55:20 GMT; domain=.zendesk.com; HttpOnly;
Secure; SameSite=None
- __cfruid=a2f5d943a0947fed81d7e574ebc7369eaf3da66d-1629465920; path=/; domain=.zendesk.com;
HttpOnly; Secure; SameSite=None
Report-To:
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=BwKWE1NbxNZpR7KP1tzIuOVmCbyQZK60K0SV%2Bu4tgV%2BRss%2BKbUBqjDYc%2B4xypzDLgdaMf9OeP8sHV%2FhllZ36MuApT%2BEzF%2B61XnuZmHgArSDmSQmvbF3RlWXtNclVCuArMq9fWvf2p7SMIpMDHYk%3D"}],"group":"cf-nel","max_age":604800}'
Nel:
- '{"success_fraction":0,"report_to":"cf-nel","max_age":604800}'
Server:
- cloudflare
Cf-Ray:
- 681bf2721fb6176e-FRA
body:
encoding: ASCII-8BIT
string: |
{
"error": {
"title": "No help desk at reallybadexample.zendesk.com",
"message": "There is no help desk configured at this address. This means that the address is available and that you can claim it at http://www.zendesk.com/signup"
}
}
recorded_at: Fri, 20 Aug 2021 13:25:20 GMT
recorded_with: VCR 6.0.0

View file

@ -0,0 +1,162 @@
---
http_interactions:
- request:
method: get
uri: "<IMPORT_ZENDESK_ENDPOINT>/users/me"
body:
encoding: US-ASCII
string: ''
headers:
Accept-Encoding:
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
Accept:
- "*/*"
User-Agent:
- Zammad User Agent
Host:
- "<IMPORT_ZENDESK_ENDPOINT_HOSTNAME>"
response:
status:
code: 200
message: OK
headers:
Date:
- Fri, 20 Aug 2021 13:25:32 GMT
Content-Type:
- application/json; charset=UTF-8
Transfer-Encoding:
- chunked
Connection:
- keep-alive
X-Zendesk-Api-Version:
- v2
X-Zendesk-Application-Version:
- v9449
X-Frame-Options:
- SAMEORIGIN
Access-Control-Expose-Headers:
- X-Zendesk-API-Warn
Vary:
- origin
X-Rate-Limit:
- '700'
X-Rate-Limit-Remaining:
- '700'
Strict-Transport-Security:
- max-age=31536000;
Etag:
- W/"3c0256d85244a27a8ce7b6f5873ccd20"
Cache-Control:
- max-age=0, private, must-revalidate
X-Zendesk-Origin-Server:
- classic-app-server-5d8ffc66d-4qfvw
X-Request-Id:
- 681bf2ba78d91456-FRA
- 681bf2ba78d91456-FRA
X-Runtime:
- '0.062649'
X-Zendesk-Zorg:
- 'yes'
X-Content-Type-Options:
- nosniff
Cf-Cache-Status:
- DYNAMIC
Expect-Ct:
- max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
Report-To:
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=zoYPc%2BRXmsDxXz60KgGj6HbcHwUVl2DMdXJDLG7Puadk819LSODyeTWQVmq%2BWNr6dPfLjl%2BbjgadmjuMkEMh3%2FagyesmlXY6%2FmIE7h7ufqhaf3WDEHy54jYUlnSVDOZsFcaoMYbL0w%3D%3D"}],"group":"cf-nel","max_age":604800}'
Nel:
- '{"success_fraction":0,"report_to":"cf-nel","max_age":604800}'
Set-Cookie:
- __cfruid=da46982ffcca5ea958f4e4ca167a32ad2a9f96b7-1629465932; path=/; domain=.<IMPORT_ZENDESK_ENDPOINT_HOSTNAME>;
HttpOnly; Secure; SameSite=None
Server:
- cloudflare
Cf-Ray:
- 681bf2ba78d91456-FRA
body:
encoding: ASCII-8BIT
string: '{"user":{"id":null,"url":null,"name":"Nicht registrierter Benutzer","email":"invalid@example.com","created_at":null,"updated_at":null,"time_zone":"Berlin","iana_time_zone":"Europe/Berlin","phone":null,"shared_phone_number":null,"photo":null,"locale_id":8,"locale":"de","organization_id":null,"role":"end-user","verified":false,"authenticity_token":"K4wyhBU1oaZc51Iy3A0wE4iBxJxbFdcdiGbGTfCiML1zJpFFy6QhSMHp+lzp2PvYoyUtVqunySi7wRpOtrywzg=="}}'
recorded_at: Fri, 20 Aug 2021 13:25:31 GMT
- request:
method: get
uri: "<IMPORT_ZENDESK_ENDPOINT>/users/me"
body:
encoding: US-ASCII
string: ''
headers:
Accept:
- application/json
Accept-Encoding:
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
User-Agent:
- ZendeskAPI Ruby 1.32.0
Authorization:
- Basic <IMPORT_ZENDESK_ENDPOINT_BASIC_AUTH>
response:
status:
code: 200
message: OK
headers:
Date:
- Fri, 20 Aug 2021 13:25:33 GMT
Content-Type:
- application/json; charset=UTF-8
Transfer-Encoding:
- chunked
Connection:
- keep-alive
X-Zendesk-Api-Version:
- v2
X-Zendesk-Application-Version:
- v9449
X-Frame-Options:
- SAMEORIGIN
Access-Control-Expose-Headers:
- X-Zendesk-API-Warn
Vary:
- origin
X-Rate-Limit:
- '700'
X-Rate-Limit-Remaining:
- '699'
Strict-Transport-Security:
- max-age=31536000;
Etag:
- W/"f14a46f2e02be3ac54793639fc4a2bab"
Cache-Control:
- max-age=0, private, must-revalidate
X-Zendesk-Origin-Server:
- classic-app-server-5d8ffc66d-tlbz4
X-Request-Id:
- 681bf2c5282d42f7-FRA
- 681bf2c5282d42f7-FRA
X-Runtime:
- '0.211401'
X-Zendesk-Zorg:
- 'yes'
Content-Encoding:
- gzip
X-Content-Type-Options:
- nosniff
Cf-Cache-Status:
- DYNAMIC
Expect-Ct:
- max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
Report-To:
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=lptF1lImDKX46TfzAwSGsGGPe8vCgQJGykBIRA%2B%2B%2F50MYmNlyuNV9bqDghfiMLyqZFABSRwpO57DlW8WMoXvCCLngFo7MyPCmxwsWF9DGqdu0uyoB1hRY9CgaDRzPz1yfiwKO8kfkg%3D%3D"}],"group":"cf-nel","max_age":604800}'
Nel:
- '{"success_fraction":0,"report_to":"cf-nel","max_age":604800}'
Set-Cookie:
- __cfruid=194b2ee3473a1a1f8f7c192193f8c8d8240c03b8-1629465933; path=/; domain=.<IMPORT_ZENDESK_ENDPOINT_HOSTNAME>;
HttpOnly; Secure; SameSite=None
Server:
- cloudflare
Cf-Ray:
- 681bf2c5282d42f7-FRA
body:
encoding: ASCII-8BIT
string: !binary |-
H4sIAAAAAAAAA21T7WrbMBR9laHfSfxRu0kMhW39WDvYYDSlJWMIxb5x1MiSK125TUrfZm+yF9uVk7QdDPIjlo7OPefo6Jl5B5YVz0xWrEiSPB4fZeOjZMC8VaxgK8TWFVG01V5vVqDa0RZ0BW49Kk0TiVZGXRoFChe9HR7dO6PZgGnRAHF8NosP143EFS1BI2TgXZjFyIW1jz1zYKPd0oJAqLhAgqRxkg/j8TCZztK0yBL6zQnj2+o9Jk2G8WSYxrPkqEjGRToJGJQN8K3R/XSwSgY1UmjB3++ce2taiF4B7Wp3Io6TJEvSjM64lbCkp9/h2jeLkBVaDwNGa2hYob1SA6ZMKRTwPsPDF80GPby5Jhpja6HlVqA0egfKs3Ge58cEtkYFmaJqepUdWLmUQES7McLjCjTKUuKGo1mDJvCpz9cSl8mndn7V2ondCHfTfYmO8wf3/XEVx7fusrs7W2utHlT3sMavAJN6fG9mJoovmqu7bC5vz8q5TKeX02/mdHZxfnd+++PkJFzQE4LVQvUyd+ZQ1I4VP1nKfg2YUFLQFyOoKFF2pH0ndBcVK5ZCOYpnn5yoSfzrohIOuTK11Icr/v/1PRq+JHZjebDPQYuFCpEcuGWtBXobciMdFSCVai9KG4T935Asx01LsJ2R0js0De/X3+w1pgIraNjBCYW9BuQWHFpJHqnLewKj1Ya3VnbUQE6VbcgcDdvLOhwIBf7HtvOuDa/mzUEFS+EV8toa3/Za0izPs2l4eBZaY5GXrjsICu+LUylURcOe2d5GRe2tzGPoQ0opKAkLKnrtUIaSskuvqz+/2cvLy1+xR8KQ5AMAAA==
recorded_at: Fri, 20 Aug 2021 13:25:33 GMT
recorded_with: VCR 6.0.0

View file

@ -0,0 +1,162 @@
---
http_interactions:
- request:
method: get
uri: "<IMPORT_ZENDESK_ENDPOINT>/users/me"
body:
encoding: US-ASCII
string: ''
headers:
Accept-Encoding:
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
Accept:
- "*/*"
User-Agent:
- Zammad User Agent
Host:
- "<IMPORT_ZENDESK_ENDPOINT_HOSTNAME>"
response:
status:
code: 200
message: OK
headers:
Date:
- Fri, 20 Aug 2021 13:25:28 GMT
Content-Type:
- application/json; charset=UTF-8
Transfer-Encoding:
- chunked
Connection:
- keep-alive
X-Zendesk-Api-Version:
- v2
X-Zendesk-Application-Version:
- v9449
X-Frame-Options:
- SAMEORIGIN
Access-Control-Expose-Headers:
- X-Zendesk-API-Warn
Vary:
- origin
X-Rate-Limit:
- '700'
X-Rate-Limit-Remaining:
- '700'
Strict-Transport-Security:
- max-age=31536000;
Etag:
- W/"8375b55c4a431d8dfb8712262f6e3751"
Cache-Control:
- max-age=0, private, must-revalidate
X-Zendesk-Origin-Server:
- classic-app-server-5d8ffc66d-zdfqv
X-Request-Id:
- 681bf2a41cd942e1-FRA
- 681bf2a41cd942e1-FRA
X-Runtime:
- '0.063942'
X-Zendesk-Zorg:
- 'yes'
X-Content-Type-Options:
- nosniff
Cf-Cache-Status:
- DYNAMIC
Expect-Ct:
- max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
Report-To:
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=0adRYvUqj6DLw53lysn1c4fdAfplJ9hZLGI9u43zLUexARu6T0reARX2x1XO9KniTTM54OzlS3ViC3jlmu3iwTUzxq2%2BrAos0l6bY1sLYEcPvwgdUUW%2Fu8luaL2vx2k5MVgogIw89Q%3D%3D"}],"group":"cf-nel","max_age":604800}'
Nel:
- '{"success_fraction":0,"report_to":"cf-nel","max_age":604800}'
Set-Cookie:
- __cfruid=d91ca7754792696e2e55df017a943bfcba44da63-1629465928; path=/; domain=.<IMPORT_ZENDESK_ENDPOINT_HOSTNAME>;
HttpOnly; Secure; SameSite=None
Server:
- cloudflare
Cf-Ray:
- 681bf2a41cd942e1-FRA
body:
encoding: ASCII-8BIT
string: '{"user":{"id":null,"url":null,"name":"Nicht registrierter Benutzer","email":"invalid@example.com","created_at":null,"updated_at":null,"time_zone":"Berlin","iana_time_zone":"Europe/Berlin","phone":null,"shared_phone_number":null,"photo":null,"locale_id":8,"locale":"de","organization_id":null,"role":"end-user","verified":false,"authenticity_token":"iN4i2T1LrOEa1Sstda+gU2F9ARv5ICRoTRVuKOiX01BCr29ys5aHk+ANDErHOy9TluEfw9fySXlsnTXG6MetGg=="}}'
recorded_at: Fri, 20 Aug 2021 13:25:28 GMT
- request:
method: get
uri: "<IMPORT_ZENDESK_ENDPOINT>/users/me"
body:
encoding: US-ASCII
string: ''
headers:
Accept:
- application/json
Accept-Encoding:
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
User-Agent:
- ZendeskAPI Ruby 1.32.0
Authorization:
- Basic Ym9iLnNtaXRoQHpudW55LmNvbS90b2tlbjoxbnY0bDFkVDBLM04=
response:
status:
code: 200
message: OK
headers:
Date:
- Fri, 20 Aug 2021 13:25:30 GMT
Content-Type:
- application/json; charset=UTF-8
Transfer-Encoding:
- chunked
Connection:
- keep-alive
X-Zendesk-Api-Version:
- v2
X-Zendesk-Application-Version:
- v9449
X-Frame-Options:
- SAMEORIGIN
Access-Control-Expose-Headers:
- X-Zendesk-API-Warn
Vary:
- origin
X-Rate-Limit:
- '700'
X-Rate-Limit-Remaining:
- '700'
Strict-Transport-Security:
- max-age=31536000;
Etag:
- W/"3a3354af8bec0d0ee73e1dfe8f2afe57"
Cache-Control:
- max-age=0, private, must-revalidate
X-Zendesk-Origin-Server:
- classic-app-server-5d8ffc66d-gcvf7
X-Request-Id:
- 681bf2aebcae4ec8-FRA
- 681bf2aebcae4ec8-FRA
X-Runtime:
- '0.070674'
X-Zendesk-Zorg:
- 'yes'
Content-Encoding:
- gzip
X-Content-Type-Options:
- nosniff
Cf-Cache-Status:
- DYNAMIC
Expect-Ct:
- max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
Report-To:
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=3EKqvaJktbKP3J3zBer88hwW1KsiD5eyi6EFc7sUE8Ymynx%2FtRpMMTjeO2kTzweHgePS3b5NPJB12t%2BCcWp9f2yTQtlp2VRmWJknJeUEiog%2B4NcuBmjyah4bgObY7yQGJaFxWYbxEw%3D%3D"}],"group":"cf-nel","max_age":604800}'
Nel:
- '{"success_fraction":0,"report_to":"cf-nel","max_age":604800}'
Set-Cookie:
- __cfruid=cde6c6306e84619802437e5b4c76a238af75f3fe-1629465930; path=/; domain=.<IMPORT_ZENDESK_ENDPOINT_HOSTNAME>;
HttpOnly; Secure; SameSite=None
Server:
- cloudflare
Cf-Ray:
- 681bf2aebcae4ec8-FRA
body:
encoding: ASCII-8BIT
string: !binary |-
H4sIAAAAAAAAA12QUWvCQBCE/4rcq2mDpVQRhKpYGsSUKqboSziTjVm87MXLRjTif+8lQSl9u52Zj9m9qygLMGJ4FRiLIZVKOaI06v4kmYEYCh+jlDsG9liwQTAMpjMBKrmyrCMgk2gRgXSSCuN3OMssV/Ac6cy6kQHJEIeSHwV5/E9hzCCsNNVlEzAKyYIoSYZ/nVlpdA7uI5CnDdFuXaTS2JZGC6nMdvVZrWU11vdB6UgqCOtzB45oJ9sag23UZi8JK8moqUm0vNGqXgwofmp+yxEnMJgg2EQiVQGOkCWnQIwR8iVkfQCyAA+662A3Xv+8fCTb1cGf+6/eFOfH8bG3WC9mF7psvMpbVm+9ioLg01vwWX1/9fPYTQ7bLpz6Ew91Nl8N/G3X9frLab5xe/vRSNxuv0GxQ424AQAA
recorded_at: Fri, 20 Aug 2021 13:25:30 GMT
recorded_with: VCR 6.0.0

View file

@ -0,0 +1,72 @@
---
http_interactions:
- request:
method: get
uri: https://reallybadexample.zendesk.com/api/v2/users/me
body:
encoding: US-ASCII
string: ''
headers:
Accept-Encoding:
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
Accept:
- "*/*"
User-Agent:
- Zammad User Agent
Host:
- reallybadexample.zendesk.com
response:
status:
code: 404
message: Not Found
headers:
Date:
- Fri, 20 Aug 2021 13:25:22 GMT
Content-Type:
- application/json; charset=UTF-8
Transfer-Encoding:
- chunked
Connection:
- keep-alive
Strict-Transport-Security:
- max-age=0;
Cache-Control:
- no-cache
X-Zendesk-Origin-Server:
- classic-app-server-687bcbddf6-thrh8
X-Request-Id:
- 681bf27f9911dfe3-FRA
- 681bf27f9911dfe3-FRA
X-Runtime:
- '0.013831'
X-Zendesk-Zorg:
- 'yes'
Cf-Cache-Status:
- DYNAMIC
Expect-Ct:
- max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
Set-Cookie:
- __cf_bm=a7f835bb234b38bfc60b856171221a38404366dc-1629465922-1800-AXfdmkG4tiWbLv6YOmgNJw0zp7sMKZurLIa0h/dPedp8qQd+5exVovRZO25rrHNZXnxm8LVadLpPxLYGO5WCXzrwoqVimHeyNRwLvV1AGcDN;
path=/; expires=Fri, 20-Aug-21 13:55:22 GMT; domain=.zendesk.com; HttpOnly;
Secure; SameSite=None
- __cfruid=adb8a84aaa2e97ae23ba7001b3ed6d3f495e8165-1629465922; path=/; domain=.zendesk.com;
HttpOnly; Secure; SameSite=None
Report-To:
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=LNVzHYTBH8fWiM2jiWF7B4mIqaHP3B2OeB8AhB6FhS7c0rN%2BA%2B9DAhJ%2FqDdKQ2t0Xk%2B%2FGwhkIsKvBGk1JKqU3ZamMtlqgp9qKbqAwTiCOcX1fenrU2jXHIeILZjl%2BDUhboztaA4agu9IiQauN88%3D"}],"group":"cf-nel","max_age":604800}'
Nel:
- '{"success_fraction":0,"report_to":"cf-nel","max_age":604800}'
Server:
- cloudflare
Cf-Ray:
- 681bf27f9911dfe3-FRA
body:
encoding: ASCII-8BIT
string: |
{
"error": {
"title": "No help desk at reallybadexample.zendesk.com",
"message": "There is no help desk configured at this address. This means that the address is available and that you can claim it at http://www.zendesk.com/signup"
}
}
recorded_at: Fri, 20 Aug 2021 13:25:22 GMT
recorded_with: VCR 6.0.0

File diff suppressed because one or more lines are too long

View file

@ -1,106 +0,0 @@
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
require 'browser_test_helper'
class ZendeskImportBrowserTest < TestCase
def test_import
if !ENV['IMPORT_BT_ZENDESK_ENDPOINT']
raise "ERROR: Need IMPORT_BT_ZENDESK_ENDPOINT - hint IMPORT_BT_ZENDESK_ENDPOINT='https://example.zendesk.com/' (including trailing slash!)"
end
if !ENV['IMPORT_BT_ZENDESK_ENDPOINT_USERNAME']
raise "ERROR: Need IMPORT_BT_ZENDESK_ENDPOINT_USERNAME - hint IMPORT_BT_ZENDESK_ENDPOINT_USERNAME='your@email.com'"
end
if !ENV['IMPORT_BT_ZENDESK_ENDPOINT_KEY']
raise "ERROR: Need IMPORT_BT_ZENDESK_ENDPOINT_KEY - hint IMPORT_BT_ZENDESK_ENDPOINT_KEY='XYZ3133723421111'"
end
@browser = browser_instance
location(url: browser_url)
click(css: 'a[href="#import"]')
click(css: 'a[href="#import/zendesk"]')
set(
css: '#zendesk-url',
value: 'https://reallybadexample.zendesk.com/'
)
sleep 5
watch_for(
css: '.zendesk-url-error',
value: 'Hostname not found!',
)
set(
css: '#zendesk-url',
value: ENV['IMPORT_BT_ZENDESK_ENDPOINT']
)
sleep 5
watch_for_disappear(
css: '.zendesk-url-error',
value: 'Hostname not found!',
)
click(css: '.js-zendesk-credentials')
set(
css: '#zendesk-email',
value: ENV['IMPORT_BT_ZENDESK_ENDPOINT_USERNAME']
)
set(
css: '#zendesk-api-token',
value: '1nv4l1dT0K3N'
)
sleep 5
watch_for(
css: '.zendesk-api-token-error',
value: 'Invalid credentials!',
)
set(
css: '#zendesk-api-token',
value: ENV['IMPORT_BT_ZENDESK_ENDPOINT_KEY']
)
sleep 5
watch_for_disappear(
css: '.zendesk-url-error',
value: 'Invalid credentials!',
)
click(css: '.js-migration-start')
watch_for(
css: '.js-groups .js-done',
value: '2',
timeout: 120,
)
watch_for(
css: '.js-organizations .js-done',
value: '2',
timeout: 120,
)
watch_for(
css: '.js-users .js-done',
value: '143',
timeout: 120,
)
watch_for(
css: 'body',
value: 'login',
timeout: 800,
)
end
end

View file

@ -1,570 +0,0 @@
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
require 'integration_test_helper'
class ZendeskImportTest < ActiveSupport::TestCase
self.test_order = :sorted
if !ENV['IMPORT_ZENDESK_ENDPOINT']
raise "ERROR: Need IMPORT_ZENDESK_ENDPOINT - hint IMPORT_ZENDESK_ENDPOINT='https://example.zendesk.com/api/v2'"
end
if !ENV['IMPORT_ZENDESK_ENDPOINT_KEY']
raise "ERROR: Need IMPORT_ZENDESK_ENDPOINT_KEY - hint IMPORT_ZENDESK_ENDPOINT_KEY='01234567899876543210'"
end
if !ENV['IMPORT_ZENDESK_ENDPOINT_USERNAME']
raise "ERROR: Need IMPORT_ZENDESK_ENDPOINT_USERNAME - hint IMPORT_ZENDESK_ENDPOINT_USERNAME='bob.ross@happylittletrees.com'"
end
Setting.set('import_zendesk_endpoint', ENV['IMPORT_ZENDESK_ENDPOINT'])
Setting.set('import_zendesk_endpoint_key', ENV['IMPORT_ZENDESK_ENDPOINT_KEY'])
Setting.set('import_zendesk_endpoint_username', ENV['IMPORT_ZENDESK_ENDPOINT_USERNAME'])
Setting.set('import_mode', true)
Setting.set('system_init_done', false)
job = ImportJob.create(name: 'Import::Zendesk')
job.start
# check statistic count
test 'check statistic' do
# retrive statistic
compare_statistic = {
Groups: {
skipped: 0,
created: 2,
updated: 0,
unchanged: 0,
failed: 0,
deactivated: 0,
sum: 2,
total: 2
},
Users: {
skipped: 0,
created: 142,
updated: 1,
unchanged: 0,
failed: 0,
deactivated: 0,
sum: 143,
total: 143
},
Organizations: {
skipped: 0,
created: 1,
updated: 0,
unchanged: 1,
failed: 0,
deactivated: 0,
sum: 2,
total: 2
},
Tickets: {
skipped: 1,
created: 142,
updated: 2,
unchanged: 0,
failed: 0,
deactivated: 0,
sum: 145,
total: 145
}
}
assert_equal(compare_statistic.with_indifferent_access, job.result, 'statistic')
end
# check count of imported items
test 'check counts' do
assert_equal(145, User.count, 'users')
assert_equal(3, Group.count, 'groups')
assert_equal(3, Role.count, 'roles')
assert_equal(2, Organization.count, 'organizations')
assert_equal(143, Ticket.count, 'tickets')
assert_equal(152, Ticket::Article.count, 'ticket articles')
assert_equal(3, Store.count, 'ticket article attachments')
# TODO: Macros, Views, Automations...
end
# check imported users and permission
test 'check users' do
role_admin = Role.find_by(name: 'Admin')
role_agent = Role.find_by(name: 'Agent')
role_customer = Role.find_by(name: 'Customer')
group_support = Group.find_by(name: 'Support')
group_additional_group = Group.find_by(name: 'Additional Group')
checks = [
{
id: 145,
data: {
firstname: 'Bob Smith',
lastname: 'Smith',
login: 'bob.smith@znuny.com',
email: 'bob.smith@znuny.com',
active: true,
phone: '00114124',
lieblingstier: 'Hundä',
},
roles: [role_admin, role_agent],
groups: [group_support],
},
{
id: 142,
data: {
firstname: 'Hansimerkur',
lastname: '',
login: 'hansimerkur@znuny.com',
email: 'hansimerkur@znuny.com',
active: true,
lieblingstier: nil,
},
roles: [role_admin, role_agent],
groups: [group_additional_group, group_support],
},
{
id: 6,
data: {
firstname: 'Bernd',
lastname: 'Hofbecker',
login: 'bernd.hofbecker@znuny.com',
email: 'bernd.hofbecker@znuny.com',
active: true,
},
roles: [role_customer],
groups: [],
},
{
id: 143,
data: {
firstname: 'Zendesk',
lastname: '',
login: 'noreply@zendesk.com',
email: 'noreply@zendesk.com',
active: true,
},
roles: [role_customer],
groups: [],
},
{
id: 5,
data: {
firstname: 'Hans',
lastname: 'Peter Wurst',
login: 'hansimerkur+zd-c1@znuny.com',
email: 'hansimerkur+zd-c1@znuny.com',
active: true,
},
roles: [role_customer],
groups: [],
},
]
checks.each do |check|
user = User.find(check[:id])
check[:data].each do |key, value|
user_value = user[key]
text = "user.#{key} for user_id #{check[:id]}"
if value.nil?
assert_nil(user_value, text)
else
assert_equal(value, user_value, text)
end
end
assert_equal(check[:roles], user.roles.sort.to_a, "#{user.login} roles")
assert_equal(check[:groups], user.groups_access('full').sort.to_a, "#{user.login} groups")
end
end
# check user fields
test 'check user fields' do
local_fields = User.column_names
copmare_fields = %w[
id
organization_id
login
firstname
lastname
email
image
image_source
web
password
phone
fax
mobile
department
street
zip
city
country
address
vip
verified
active
note
last_login
source
login_failed
out_of_office
out_of_office_start_at
out_of_office_end_at
out_of_office_replacement_id
preferences
updated_by_id
created_by_id
created_at
updated_at
lieblingstier
custom_dropdown
]
assert_equal(copmare_fields, local_fields, 'user fields')
end
# check groups/queues
test 'check groups' do
checks = [
{
id: 1,
data: {
name: 'Users',
active: true,
},
},
{
id: 2,
data: {
name: 'Additional Group',
active: true,
},
},
{
id: 3,
data: {
name: 'Support',
active: true,
},
},
]
checks.each do |check|
group = Group.find(check[:id])
check[:data].each do |key, value|
assert_equal(value, group[key], "group.#{key} for group_id #{check[:id]}")
end
end
end
# check imported organizations
test 'check organizations' do
checks = [
{
id: 1,
data: {
name: 'Zammad Foundation',
note: '',
api_key: nil,
custom_dropdown: nil,
},
},
{
id: 2,
data: {
name: 'Znuny',
note: nil,
api_key: 'my api öäüß',
custom_dropdown: 'b',
},
},
]
checks.each do |check|
organization = Organization.find(check[:id])
check[:data].each do |key, value|
organization_value = organization[key]
text = "organization.#{key} for organization_id #{check[:id]}"
if value.nil?
assert_nil(organization_value, text)
else
assert_equal(value, organization_value, text)
end
end
end
end
# check organization fields
test 'check organization fields' do
local_fields = Organization.column_names
copmare_fields = %w[
id
name
shared
domain
domain_assignment
active
note
updated_by_id
created_by_id
created_at
updated_at
api_key
custom_dropdown
]
assert_equal(copmare_fields, local_fields, 'organization fields')
end
# check imported tickets
test 'check tickets' do
checks = [
{
id: 2,
data: {
number: '2',
title: 'test',
note: nil,
create_article_type_id: 1,
create_article_sender_id: 2,
article_count: 2,
state_id: 3,
group_id: 3,
priority_id: 3,
owner_id: User.find_by(login: 'bob.smith@znuny.com').id,
customer_id: User.find_by(login: 'bernd.hofbecker@znuny.com').id,
organization_id: 2,
test_checkbox: true,
custom_integer: 999,
custom_dropdown: 'key2',
custom_decimal: '1.6',
not_existing: nil,
},
},
{
id: 3,
data: {
number: '3',
title: 'Bob Smith, here is the test ticket you requested',
note: nil,
create_article_type_id: 10,
create_article_sender_id: 2,
article_count: 5,
state_id: 3,
group_id: 3,
priority_id: 1,
owner_id: User.find_by(login: 'bob.smith@znuny.com').id,
customer_id: User.find_by(login: 'noreply@zendesk.com').id,
organization_id: nil,
test_checkbox: false,
custom_integer: nil,
custom_dropdown: '',
custom_decimal: nil,
not_existing: nil,
},
},
{
id: 5,
data: {
number: '5',
title: 'Twitter',
note: nil,
create_article_type_id: 6,
create_article_sender_id: 2,
article_count: 1,
state_id: 1,
group_id: 3,
priority_id: 2,
owner_id: User.find_by(login: '-').id,
customer_id: 69,
organization_id: nil,
},
},
{
id: 143,
data: {
number: '143',
title: 'Basti ist cool',
note: nil,
create_article_type_id: 8,
create_article_sender_id: 2,
article_count: 1,
state_id: 1,
group_id: 1,
priority_id: 2,
owner_id: User.find_by(login: '-').id,
customer_id: 7,
organization_id: nil,
},
},
{
id: 145,
data: {
number: '145',
title: 'closed ticket - should be archived and imported',
note: nil,
create_article_type_id: 11,
create_article_sender_id: 1,
article_count: 1,
state_id: Ticket::State.find_by(name: 'closed').id,
group_id: Group.find_by(name: 'Additional Group').id,
priority_id: Ticket::Priority.find_by(name: '2 normal').id,
owner_id: User.find_by(login: 'hansimerkur@znuny.com').id,
customer_id: User.find_by(login: 'bob.smith@znuny.com').id,
organization_id: Organization.find_by(name: 'Znuny').id,
},
},
# {
# id: ,
# data: {
# title: ,
# note: ,
# create_article_type_id: ,
# create_article_sender_id: ,
# article_count: ,
# state_id: ,
# group_id: ,
# priority_id: ,
# owner_id: ,
# customer_id: ,
# organization_id: ,
# },
# },
]
checks.each do |check|
ticket = Ticket.find(check[:id])
check[:data].each do |key, value|
ticket_value = ticket[key]
text = "ticket.#{key} for ticket_id #{check[:id]}"
if value.nil?
assert_nil(ticket_value, text)
else
assert_equal(value, ticket_value, text)
end
end
end
end
test 'check article attachments' do
checks = [
{
message_id: 39_984_258_725,
data: {
count: 1,
1 => {
preferences: {
'Content-Type' => 'image/jpeg',
'resizable' => true,
'content_preview' => true
},
filename: '1a3496b9-53d9-494d-bbb0-e1d2e22074f8.jpeg',
},
},
},
{
message_id: 32_817_827_921,
data: {
count: 1,
1 => {
preferences: {
'Content-Type' => 'image/jpeg',
'resizable' => true,
'content_preview' => true
},
filename: 'paris.jpg',
},
},
},
{
message_id: 538_901_840_720,
data: {
count: 1,
1 => {
preferences: {
'Content-Type' => 'text/rtf'
},
filename: 'test.rtf',
},
},
},
]
checks.each do |check|
article = Ticket::Article.find_by(message_id: check[:message_id])
assert_equal(check[:data][:count], article.attachments.count, 'attachemnt count')
(1..check[:data][:count]).each do |attachment_counter|
attachment = article.attachments[ attachment_counter - 1 ]
compare_attachment = check[:data][ attachment_counter ]
assert_equal(compare_attachment[:filename], attachment.filename, 'attachment file name')
assert_equal(compare_attachment[:preferences], attachment[:preferences], 'attachment preferences')
end
end
end
# check ticket fields
test 'check ticket fields' do
local_fields = Ticket.column_names
copmare_fields = %w[
id
group_id
priority_id
state_id
organization_id
number
title
owner_id
customer_id
note
first_response_at
first_response_escalation_at
first_response_in_min
first_response_diff_in_min
close_at
close_escalation_at
close_in_min
close_diff_in_min
update_escalation_at
update_in_min
update_diff_in_min
last_contact_at
last_contact_agent_at
last_contact_customer_at
last_owner_update_at
create_article_type_id
create_article_sender_id
article_count
escalation_at
pending_time
type
time_unit
preferences
updated_by_id
created_by_id
created_at
updated_at
custom_decimal
test_checkbox
custom_date
custom_integer
custom_regex
custom_dropdown
]
assert_equal(copmare_fields, local_fields, 'ticket fields')
end
end