foreman_teamdynamix 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/locale/Makefile ADDED
@@ -0,0 +1,60 @@
1
+ #
2
+ # Makefile for PO merging and MO generation. More info in the README.
3
+ #
4
+ # make all-mo (default) - generate MO files
5
+ # make check - check translations using translate-tool
6
+ # make tx-update - download and merge translations from Transifex
7
+ # make clean - clean everything
8
+ #
9
+ DOMAIN = foreman_teamdynamix
10
+ VERSION = $(shell ruby -e 'require "rubygems";spec = Gem::Specification::load(Dir.glob("../*.gemspec")[0]);puts spec.version')
11
+ POTFILE = $(DOMAIN).pot
12
+ MOFILE = $(DOMAIN).mo
13
+ POFILES = $(shell find . -name '$(DOMAIN).po')
14
+ MOFILES = $(patsubst %.po,%.mo,$(POFILES))
15
+ POXFILES = $(patsubst %.po,%.pox,$(POFILES))
16
+ EDITFILES = $(patsubst %.po,%.edit.po,$(POFILES))
17
+
18
+ %.mo: %.po
19
+ mkdir -p $(shell dirname $@)/LC_MESSAGES
20
+ msgfmt -o $(shell dirname $@)/LC_MESSAGES/$(MOFILE) $<
21
+
22
+ # Generate MO files from PO files
23
+ all-mo: $(MOFILES)
24
+
25
+ # Check for malformed strings
26
+ %.pox: %.po
27
+ msgfmt -c $<
28
+ pofilter --nofuzzy -t variables -t blank -t urls -t emails -t long -t newlines \
29
+ -t endwhitespace -t endpunc -t puncspacing -t options -t printf -t validchars --gnome $< > $@
30
+ cat $@
31
+ ! grep -q msgid $@
32
+
33
+ %.edit.po:
34
+ touch $@
35
+
36
+ check: $(POXFILES)
37
+
38
+ # Unify duplicate translations
39
+ uniq-po:
40
+ for f in $(shell find ./ -name "*.po") ; do \
41
+ msguniq $$f -o $$f ; \
42
+ done
43
+
44
+ tx-pull: $(EDITFILES)
45
+ tx pull -f
46
+ for f in $(EDITFILES) ; do \
47
+ sed -i 's/^\("Project-Id-Version: \).*$$/\1$(DOMAIN) $(VERSION)\\n"/' $$f; \
48
+ done
49
+
50
+ tx-update: tx-pull
51
+ @echo
52
+ @echo Run rake plugin:gettext[$(DOMAIN)] from the Foreman installation, then make -C locale mo-files to finish
53
+ @echo
54
+
55
+ mo-files: $(MOFILES)
56
+ git add $(POFILES) $(POTFILE) ../locale/*/LC_MESSAGES
57
+ git commit -m "i18n - pulling from tx"
58
+ @echo
59
+ @echo Changes commited!
60
+ @echo
@@ -0,0 +1,18 @@
1
+ # foreman_teamdynamix
2
+ #
3
+ # This file is distributed under the same license as foreman_teamdynamix.
4
+ #
5
+ #, fuzzy
6
+ msgid ""
7
+ msgstr ""
8
+ "Project-Id-Version: version 0.0.1\n"
9
+ "Report-Msgid-Bugs-To: \n"
10
+ "POT-Creation-Date: 2014-08-20 08:46+0100\n"
11
+ "PO-Revision-Date: 2014-08-20 08:54+0100\n"
12
+ "Last-Translator: Foreman Team <foreman-dev@googlegroups.com>\n"
13
+ "Language-Team: Foreman Team <foreman-dev@googlegroups.com>\n"
14
+ "Language: \n"
15
+ "MIME-Version: 1.0\n"
16
+ "Content-Type: text/plain; charset=UTF-8\n"
17
+ "Content-Transfer-Encoding: 8bit\n"
18
+ "Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -0,0 +1,18 @@
1
+ # foreman_teamdynamix
2
+ #
3
+ # This file is distributed under the same license as foreman_teamdynamix.
4
+ #
5
+ #, fuzzy
6
+ msgid ""
7
+ msgstr ""
8
+ "Project-Id-Version: version 0.0.1\n"
9
+ "Report-Msgid-Bugs-To: \n"
10
+ "POT-Creation-Date: 2014-08-20 08:46+0100\n"
11
+ "PO-Revision-Date: 2014-08-20 08:46+0100\n"
12
+ "Last-Translator: Foreman Team <foreman-dev@googlegroups.com>\n"
13
+ "Language-Team: Foreman Team <foreman-dev@googlegroups.com>\n"
14
+ "Language: \n"
15
+ "MIME-Version: 1.0\n"
16
+ "Content-Type: text/plain; charset=UTF-8\n"
17
+ "Content-Transfer-Encoding: 8bit\n"
18
+ "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
data/locale/gemspec.rb ADDED
@@ -0,0 +1,2 @@
1
+ # Matches foreman_teamdynamix.gemspec
2
+ _('A Foreman Plugin to create a configurable TeamDynamix Asset when a host is created in Foreman')
@@ -0,0 +1,17 @@
1
+ class FakeTeamdynamixApi
2
+ def create_asset(*)
3
+ get_asset
4
+ end
5
+
6
+ def search_asset(*)
7
+ Array.wrap(get_asset)
8
+ end
9
+
10
+ def retire_asset(*)
11
+ true
12
+ end
13
+
14
+ def get_asset(*)
15
+ JSON.parse(File.read(File.join(File.dirname(__FILE__), 'sample_asset.json')))
16
+ end
17
+ end
@@ -0,0 +1,31 @@
1
+ require 'test_plugin_helper'
2
+
3
+ class HostsControllerTest < ActionController::TestCase
4
+ let(:td_tab_title) { SETTINGS[:teamdynamix][:title] || 'Team Dynamix' }
5
+ let(:host) { FactoryBot.create(:host, :managed) }
6
+ let(:td_api) { FakeTeamdynamixApi.new }
7
+ before do
8
+ Host::Managed.any_instance.stubs(:td_api).returns(td_api)
9
+ end
10
+ # rubocop:disable Style/StringLiterals, HttpPositionalArguments
11
+ describe 'Given host exist as an asset in TeamDynamix' do
12
+ describe 'when TeamDynamix asset attributes are configured' do
13
+ describe 'GET hosts/show' do
14
+ test 'loads the TeamDynamix tab' do
15
+ get :show, { :id => host.name }, set_session_user
16
+ assert_includes response.headers['Content-Type'], 'text/html'
17
+ assert_includes response.body, "<ul id=\"myTab\""
18
+ assert_equal response.status, 200
19
+ assert_includes response.body, "<li><a href=\"#teamdynamix\" data-toggle=\"tab\">#{td_tab_title}</a></li>"
20
+ assert_includes response.body, "<div id=\"teamdynamix\" class=\"tab-pane\" data-ajax-url=\"/hosts/#{host.name}/teamdynamix\" data-on-complete=\"onContentLoad\">"
21
+ end
22
+ test 'TeamDynamix tab contains configured asset attributes' do
23
+ skip
24
+ get hosts_teamdynamix_path, { :id => host.name }, set_session_user
25
+ assert_template 'foreman_teamdynamix'
26
+ end
27
+ end
28
+ end
29
+ end
30
+ # rubocop:enable Style/StringLiterals, HttpPositionalArguments
31
+ end
@@ -0,0 +1,63 @@
1
+ require 'test_plugin_helper'
2
+
3
+ class HostsHelperExtensionsTest < ActiveSupport::TestCase
4
+ include ActionView::Helpers::UrlHelper
5
+ include ForemanTeamdynamix::HostsHelperExtensions
6
+ let(:host) { FactoryBot.create(:host, :managed) }
7
+ let(:td_api) { FakeTeamdynamixApi.new }
8
+ before do
9
+ Host::Managed.any_instance.stubs(:td_api).returns(td_api)
10
+ @host = host
11
+ end
12
+
13
+ describe '#teamdynamix_fields' do
14
+ let(:sample_asset) { td_api.get_asset }
15
+ let(:default_fields) { [sample_asset_uri] }
16
+ let(:direct_attribs_config) { { 'Asset ID' => 'ID', 'Owner' => 'OwningCustomerName', 'Parent Asset' => 'ParentID' } }
17
+ let(:direct_attribs_fields) { get_direct_asset_attribs_val(direct_attribs_config) }
18
+ let(:expected_fields) { default_fields + direct_attribs_fields }
19
+ before do
20
+ SETTINGS[:teamdynamix][:fields] = {}
21
+ SETTINGS[:teamdynamix][:fields].merge!(direct_attribs_config)
22
+ end
23
+
24
+ context 'configuration only has attributes' do
25
+ test 'returns fields as expected' do
26
+ assert_equal teamdynamix_fields, expected_fields
27
+ end
28
+ end
29
+
30
+ context 'configuration has nested attributes' do
31
+ let(:nested_attribs_config) do
32
+ { 'mu.ci.Description' => "Attributes.'mu.ci.Description'",
33
+ 'Ticket Routing Details' => "Attributes.'Ticket Routing Details'" }
34
+ end
35
+ let(:nested_attribs_fields) { get_nested_asset_attribs_val(nested_attribs_config) }
36
+ let(:expected_fields) { default_fields + nested_attribs_fields }
37
+ before do
38
+ SETTINGS[:teamdynamix][:fields] = {}
39
+ SETTINGS[:teamdynamix][:fields].merge!(nested_attribs_config)
40
+ end
41
+ test 'returns fields as expected' do
42
+ assert_equal teamdynamix_fields, expected_fields
43
+ end
44
+ end
45
+ end
46
+
47
+ describe '#teamdynamix_title' do
48
+ let(:title_orig) { SETTINGS[:teamdynamix][:title] }
49
+ before do
50
+ title_orig
51
+ SETTINGS[:teamdynamix][:title] = 'TeamDynamix Tab'
52
+ end
53
+ test 'returns correct title' do
54
+ assert_equal teamdynamix_title, SETTINGS[:teamdynamix][:title]
55
+ end
56
+
57
+ test 'settings title is not present: return default title' do
58
+ SETTINGS[:teamdynamix][:title] = nil
59
+ assert_equal teamdynamix_title, 'Team Dynamix'
60
+ SETTINGS[:teamdynamix][:title] = title_orig
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,37 @@
1
+ require 'test_helper'
2
+
3
+ class HostExtensionsTests < ActiveSupport::TestCase
4
+ let(:td_api) { FakeTeamdynamixApi.new }
5
+ before do
6
+ Host::Managed.any_instance.stubs(:td_api).returns(td_api)
7
+ end
8
+
9
+ describe '#create' do
10
+ let(:host) { FactoryBot.create(:host, :managed) }
11
+ it 'triggers after_create callback on Host::Managed model' do
12
+ assert_send([Host::Managed, :after_validation, :create_teamdynamix_asset])
13
+ end
14
+
15
+ it 'calls Teamdynamix API to create an asset' do
16
+ assert_send([td_api, :create_asset, host])
17
+ end
18
+
19
+ it 'sets host#teamdynamix_asset_id' do
20
+ assert_not_nil(host.teamdynamix_asset_id)
21
+ end
22
+ end
23
+
24
+ describe '#destroy' do
25
+ let(:host) { FactoryBot.create(:host, :managed) }
26
+ before do
27
+ host.destroy
28
+ end
29
+ it 'triggers before_destroy callback' do
30
+ assert_send([Host::Managed, :before_destroy, :retire_teamdynamix_asset])
31
+ end
32
+
33
+ it 'calls Teamdynamix API to retire an asset' do
34
+ assert_send([td_api, :retire_asset, host.teamdynamix_asset_id])
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,193 @@
1
+ {
2
+ "ID": 1111,
3
+ "AppID": 111,
4
+ "AppName": "Assets/CIs",
5
+ "ProductModelID": 1070,
6
+ "ProductModelName": "Application/Software",
7
+ "ManufacturerID": 1030,
8
+ "ManufacturerName": "MU",
9
+ "SupplierID": 1031,
10
+ "SupplierName": "Supplier",
11
+ "StatusID": 641,
12
+ "StatusName": "In Use",
13
+ "LocationID": 0,
14
+ "LocationName": "None",
15
+ "LocationRoomID": 0,
16
+ "LocationRoomName": "None",
17
+ "Tag": null,
18
+ "SerialNumber": "delete.foreman_teamdynamix.com",
19
+ "Name": "delete.foreman_teamdynamix.com",
20
+ "PurchaseCost": 0,
21
+ "AcquisitionDate": "0001-01-01T05:00:00Z",
22
+ "ExpectedReplacementDate": "0001-01-01T05:00:00Z",
23
+ "RequestingCustomerID": "00000000-0000-0000-0000-000000000000",
24
+ "RequestingCustomerName": "None",
25
+ "RequestingDepartmentID": 0,
26
+ "RequestingDepartmentName": "None",
27
+ "OwningCustomerID": "00000000-0000-0000-0000-000000000000",
28
+ "OwningCustomerName": "some name",
29
+ "OwningDepartmentID": 16253,
30
+ "OwningDepartmentName": "Advancement Services",
31
+ "ParentID": 10306,
32
+ "ParentSerialNumber": "Banner",
33
+ "ParentName": "",
34
+ "ParentTag": null,
35
+ "MaintenanceScheduleID": 0,
36
+ "MaintenanceScheduleName": "None",
37
+ "ConfigurationItemID": 16308,
38
+ "CreatedDate": "2014-11-20T21:22:52.057Z",
39
+ "CreatedUid": "00000000-0000-0000-0000-000000000000",
40
+ "CreatedFullName": "some name",
41
+ "ModifiedDate": "2017-09-15T15:25:09.79Z",
42
+ "ModifiedUid": "00000000-0000-0000-0000-000000000000",
43
+ "ModifiedFullName": "some name",
44
+ "ExternalID": "Banner Advancement",
45
+ "ExternalSourceID": 0,
46
+ "ExternalSourceName": "None",
47
+ "Attributes": [
48
+ {
49
+ "ID": 11636,
50
+ "Name": "Ticket Routing Details",
51
+ "Order": 0,
52
+ "Description": "",
53
+ "SectionID": 0,
54
+ "SectionName": null,
55
+ "FieldType": "textarea",
56
+ "DataType": "String",
57
+ "Choices": [],
58
+ "IsRequired": false,
59
+ "IsUpdatable": true,
60
+ "Value": "sample",
61
+ "ValueText": "",
62
+ "ChoicesText": "",
63
+ "AssociatedItemIDs": [
64
+ 0
65
+ ]
66
+ },
67
+ {
68
+ "ID": 11632,
69
+ "Name": "mu.ci.Description",
70
+ "Order": 50,
71
+ "Description": "",
72
+ "SectionID": 0,
73
+ "SectionName": null,
74
+ "FieldType": "textarea",
75
+ "DataType": "String",
76
+ "Choices": [],
77
+ "IsRequired": false,
78
+ "IsUpdatable": false,
79
+ "Value": "Foreman host delete.foreman_teamdynamix.com created by ForemanTeamdynamix plugin",
80
+ "ValueText": "",
81
+ "ChoicesText": "",
82
+ "AssociatedItemIDs": [
83
+ 0
84
+ ]
85
+ },
86
+ {
87
+ "ID": 11634,
88
+ "Name": "mu.ci.Lifecycle Status",
89
+ "Order": 50,
90
+ "Description": "This is the ITSM Lifecycle phase",
91
+ "SectionID": 0,
92
+ "SectionName": null,
93
+ "FieldType": "dropdown",
94
+ "DataType": "String",
95
+ "Choices": [
96
+ {
97
+ "ID": 26191,
98
+ "Name": "Development",
99
+ "IsActive": true,
100
+ "DateCreated": "2014-11-13T19:56:04.747Z",
101
+ "DateModified": "2014-11-13T19:56:04.747Z",
102
+ "Order": 0
103
+ },
104
+ {
105
+ "ID": 26192,
106
+ "Name": "Early-life Support",
107
+ "IsActive": true,
108
+ "DateCreated": "2014-11-13T19:56:04.747Z",
109
+ "DateModified": "2014-11-13T19:56:04.747Z",
110
+ "Order": 0
111
+ },
112
+ {
113
+ "ID": 26194,
114
+ "Name": "Pre-production",
115
+ "IsActive": true,
116
+ "DateCreated": "2014-11-13T19:56:04.75Z",
117
+ "DateModified": "2014-11-13T19:56:04.75Z",
118
+ "Order": 0
119
+ },
120
+ {
121
+ "ID": 26193,
122
+ "Name": "Production",
123
+ "IsActive": true,
124
+ "DateCreated": "2014-11-13T19:56:04.747Z",
125
+ "DateModified": "2014-11-13T19:56:04.747Z",
126
+ "Order": 0
127
+ },
128
+ {
129
+ "ID": 26190,
130
+ "Name": "Test",
131
+ "IsActive": true,
132
+ "DateCreated": "2014-11-13T19:56:04.747Z",
133
+ "DateModified": "2014-11-13T19:56:04.747Z",
134
+ "Order": 0
135
+ }
136
+ ],
137
+ "IsRequired": true,
138
+ "IsUpdatable": false,
139
+ "Value": "26190",
140
+ "ValueText": "Production",
141
+ "ChoicesText": "Production",
142
+ "AssociatedItemIDs": [
143
+ 0
144
+ ]
145
+ },
146
+ {
147
+ "ID": 11639,
148
+ "Name": "mu.application.location",
149
+ "Order": 204,
150
+ "Description": "Where is the application running?",
151
+ "SectionID": 0,
152
+ "SectionName": null,
153
+ "FieldType": "hradio",
154
+ "DataType": "String",
155
+ "Choices": [
156
+ {
157
+ "ID": 26223,
158
+ "Name": "Cloud",
159
+ "IsActive": true,
160
+ "DateCreated": "2014-11-13T19:56:04.787Z",
161
+ "DateModified": "2014-11-13T19:56:04.787Z",
162
+ "Order": 0
163
+ },
164
+ {
165
+ "ID": 26224,
166
+ "Name": "Endpoint Device",
167
+ "IsActive": true,
168
+ "DateCreated": "2014-11-13T19:56:04.787Z",
169
+ "DateModified": "2014-11-13T19:56:04.787Z",
170
+ "Order": 0
171
+ },
172
+ {
173
+ "ID": 26222,
174
+ "Name": "Premise",
175
+ "IsActive": true,
176
+ "DateCreated": "2014-11-13T19:56:04.787Z",
177
+ "DateModified": "2014-11-13T19:56:04.787Z",
178
+ "Order": 0
179
+ }
180
+ ],
181
+ "IsRequired": false,
182
+ "IsUpdatable": false,
183
+ "Value": "26222",
184
+ "ValueText": "Premise",
185
+ "ChoicesText": "Premise",
186
+ "AssociatedItemIDs": [
187
+ 0
188
+ ]
189
+ }
190
+ ],
191
+ "Attachments": [],
192
+ "Uri": "api/730/assets/1111"
193
+ }
@@ -0,0 +1,165 @@
1
+ require 'test_plugin_helper'
2
+ # rubocop:disable Metrics/ClassLength
3
+ class TeamdynamixApiTest < ActiveSupport::TestCase
4
+ # rubocop:enable Metrics/ClassLength
5
+ let(:subject) { TeamdynamixApi.instance }
6
+ let(:api_config) { SETTINGS[:teamdynamix][:api] }
7
+ let(:app_id) { api_config[:appId].to_s }
8
+ let(:api_url) { api_config[:url] }
9
+ let(:host) { FactoryBot.build(:host, :managed) }
10
+ let(:auth_payload) { { username: api_config[:username], password: api_config[:password] }.to_json }
11
+ let(:dummy_token) { 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1bmlxdWVfbmFtZSI6InR5YWdpbkBtaWFtaW9oLmVkdSIsImlzcyI6IlREIiwiYXVkIjoiaHR0cHM6Ly93d3cudGVhbWR5bmFtaXguY29tLyIsImV4cCI6MTUxNzA2OTU1OSwibmJmIjoxNTE2OTgzMTU5fQ.PkvKbYQCV-hY7_ni4-Zg3qJARBagSzz99fclBYyxxas' }
12
+ let(:sample_asset) { FakeTeamdynamixApi.new.get_asset }
13
+ let(:sample_asset_id) { sample_asset['ID'].to_s }
14
+ let(:host_name) { 'delete.foreman_teamdynamix.com' }
15
+ let(:get_asset_path) { api_url + '/' + app_id + '/assets/' + sample_asset_id }
16
+ let(:create_status_id) { 641 }
17
+ let(:custom_attributes) do
18
+ [{ 'name' => 'mu.ci.Lifecycle Status', 'id' => 11_634, 'value' => '26193' },
19
+ { 'name' => 'mu.ci.Description', 'id' => 11_632, 'value' => 'Foreman host created by ForemanTeamdynamix plugin' }]
20
+ end
21
+ let(:create_path) { api_url + '/' + app_id + '/assets' }
22
+ let(:create_payload) do
23
+ { AppID: app_id,
24
+ SerialNumber: host_name,
25
+ Name: host_name,
26
+ StatusID: create_status_id,
27
+ Attributes: custom_attributes }
28
+ end
29
+ before do
30
+ stub_request(:post, api_url + '/auth')
31
+ .with(body: auth_payload,
32
+ headers: { 'Content-Type' => 'application/json' })
33
+ .to_return(status: 200, body: dummy_token)
34
+ host.name = host_name
35
+ end
36
+
37
+ describe '#update_asset' do
38
+ let(:update_path) { get_asset_path }
39
+ let(:update_payload) { { ID: host.teamdynamix_asset_id }.merge!(create_payload) }
40
+ before do
41
+ host.teamdynamix_asset_id = sample_asset_id
42
+ SETTINGS[:teamdynamix][:api][:create] = { StatusID: create_status_id,
43
+ Attributes: custom_attributes }
44
+ end
45
+ context 'Valid Request' do
46
+ before do
47
+ stub_request(:post, update_path)
48
+ .with(headers: { 'Authorization' => 'Bearer ' + dummy_token,
49
+ 'Content-Type' => 'application/json' },
50
+ body: update_payload)
51
+ .to_return(status: 200, body: sample_asset.to_json)
52
+ end
53
+ it 'successfully creates an asset and return it' do
54
+ asset = subject.update_asset(host)
55
+ assert_equal(asset['SerialNumber'], host.name)
56
+ assert_equal(asset['AppID'].to_s, app_id.to_s)
57
+ assert_equal(asset['StatusID'], create_status_id)
58
+ end
59
+ end
60
+ end
61
+
62
+ describe '#retire_asset' do
63
+ let(:retire_status_id) { 642 }
64
+ before do
65
+ subject.stubs(:get_asset).returns(sample_asset)
66
+ SETTINGS[:teamdynamix][:api][:delete] = { StatusID: retire_status_id }
67
+ end
68
+ describe 'valid request' do
69
+ let(:retired_asset) { sample_asset.merge('StatusID' => retire_status_id) }
70
+ let(:retire_path) { api_url + '/' + app_id + '/assets/' + sample_asset_id }
71
+ before do
72
+ stub_request(:post, retire_path)
73
+ .with(headers: { 'Authorization' => 'Bearer ' + dummy_token,
74
+ 'Content-Type' => 'application/json' })
75
+ .to_return(status: 200, body: retired_asset.to_json)
76
+ end
77
+ it 'marks the asset retired in Team Dynamix' do
78
+ assert_nothing_raised do
79
+ asset = subject.retire_asset(sample_asset_id)
80
+ assert_equal(asset['StatusID'], retire_status_id)
81
+ end
82
+ end
83
+ end
84
+ end
85
+
86
+ describe '#create_asset' do
87
+ before do
88
+ SETTINGS[:teamdynamix][:api][:create] = { StatusID: create_status_id,
89
+ Attributes: custom_attributes }
90
+ end
91
+ context 'Valid Request' do
92
+ before do
93
+ stub_request(:post, create_path)
94
+ .with(headers: { 'Authorization' => 'Bearer ' + dummy_token,
95
+ 'Content-Type' => 'application/json' },
96
+ body: create_payload)
97
+ .to_return(status: 200, body: sample_asset.to_json)
98
+ end
99
+ it 'successfully creates an asset and return it' do
100
+ asset = subject.create_asset(host)
101
+ assert_not_nil(asset['ID'])
102
+ assert_equal(asset['SerialNumber'], host.name)
103
+ assert_equal(asset['AppID'].to_s, app_id.to_s)
104
+ assert_equal(asset['StatusID'], create_status_id)
105
+ end
106
+ end
107
+
108
+ context 'Invalid Request: missing SerialNumber' do
109
+ # rubocop:disable Style/StringLiterals
110
+ let(:error_body) { "Name or serial number must be provided for asset records" }
111
+ let(:error) { { status: "400", msg: "", body: error_body }.to_json }
112
+ # rubocop:enable Style/StringLiterals
113
+ before do
114
+ stub_request(:post, create_path)
115
+ .with(headers: { 'Authorization' => 'Bearer ' + dummy_token,
116
+ 'Content-Type' => 'application/json' },
117
+ body: create_payload)
118
+ .to_return(status: 400, body: error_body)
119
+ end
120
+ it 'raises error with status 400 for invalid payload' do
121
+ assert_raises_with_message(RuntimeError, error) do
122
+ subject.create_asset(host)
123
+ end
124
+ end
125
+ end
126
+ end
127
+
128
+ describe '#request_token' do
129
+ describe 'valida credentials' do
130
+ end
131
+ it 'returns a bearer token if credentials are correct' do
132
+ assert_not_nil(subject.send(:request_token))
133
+ end
134
+
135
+ describe 'invalid credentials' do
136
+ # rubocop:disable Style/StringLiterals
137
+ let(:error_body) { "Invalid username or password." }
138
+ let(:error) { { status: "403", msg: "", body: error_body }.to_json }
139
+ # rubocop:enable Style/StringLiterals
140
+ before do
141
+ stub_request(:post, api_url + '/auth')
142
+ .with(body: auth_payload)
143
+ .to_return(status: 403, body: error_body)
144
+ end
145
+ it 'raises error with status 403' do
146
+ assert_raises_with_message(RuntimeError, error) do
147
+ subject.send(:request_token)
148
+ end
149
+ end
150
+ end
151
+ end
152
+
153
+ describe '#get_asset' do
154
+ context 'Valid Request' do
155
+ before do
156
+ stub_request(:get, get_asset_path)
157
+ .with(headers: { 'Authorization' => 'Bearer ' + dummy_token })
158
+ .to_return(status: 200, body: sample_asset.to_json)
159
+ end
160
+ it 'returns asset json' do
161
+ assert_equal(subject.get_asset(sample_asset_id), sample_asset)
162
+ end
163
+ end
164
+ end
165
+ end
@@ -0,0 +1,38 @@
1
+ def override_settings
2
+ SETTINGS[:teamdynamix] = { api: { url: 'https://api.teamdynamix.com/TDWebApi/api',
3
+ appId: '111',
4
+ username: 'a_valid_username',
5
+ password: 'a_valid_pwd' } }
6
+ end
7
+ override_settings
8
+
9
+ def get_direct_asset_attribs_val(config)
10
+ direct_attrib_fields = []
11
+ config.each do |tag, attr_name|
12
+ direct_attrib_fields << [tag, sample_asset[attr_name]]
13
+ end
14
+ direct_attrib_fields
15
+ end
16
+
17
+ def get_nested_asset_attribs_val(config)
18
+ nested_attrib_fields = []
19
+ config.each do |tag, nested_attrib|
20
+ parent_attrib, child_attrib = nested_attrib.split(".'")
21
+ child_attrib.delete!("'")
22
+ attrib_val = sample_asset[parent_attrib].select { |attrib| attrib['Name'] == child_attrib }[0]['Value']
23
+ nested_attrib_fields << [tag, attrib_val]
24
+ end
25
+ nested_attrib_fields
26
+ end
27
+
28
+ def sample_asset_uri
29
+ api_url = SETTINGS[:teamdynamix][:api][:url]
30
+ asset_uri = api_url.split('api').first + sample_asset['Uri']
31
+ [_('URI'), link_to(sample_asset['Uri'], asset_uri, target: '_blank')]
32
+ end
33
+
34
+ require 'webmock/minitest'
35
+ WebMock.disable_net_connect!(allow_localhost: true)
36
+
37
+ require 'fake_teamdynamix_api'
38
+ require 'test_helper'
@@ -0,0 +1,11 @@
1
+ require 'test_plugin_helper'
2
+
3
+ class ForemanTeamdynamixTest < ActiveSupport::TestCase
4
+ setup do
5
+ User.current = User.find_by(login: 'admin')
6
+ end
7
+
8
+ test 'the truth' do
9
+ assert true
10
+ end
11
+ end