snow_sync 3.1.5 → 3.1.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 94f2f27e9878dc97c7f3cc662cf3519fbccb3cd771666feb5a9976585607ae4f
4
- data.tar.gz: 8803cd91afadab4e1e0a572f46547fb569518c50a15121003496eb4f7cdca47b
3
+ metadata.gz: 006d22f37ee45ef3de904baba95ba0ee0e6a80dc25259741bbab58e9e34db4ee
4
+ data.tar.gz: 0e31d3394fc906562060141146dc15032c8701d7da5ec76495b9cc7d17e68bd6
5
5
  SHA512:
6
- metadata.gz: 00dfb1a35ef10a6331c7df8f84df2ab401a7d6de794317be1d6a04c2808830e063b1830e12081fb2aa93dcf81f34164dedc930a224c37b684cf2e07824a23a0e
7
- data.tar.gz: 7eeeec614853accf1ba6c72f10e24f5210ae811bf01cc773c70eb5f9f71e7ebb1505b244bb24c7a4def4bb5134fc4195103686190617d7693f9d72a7bb3b422b
6
+ metadata.gz: f45e339f65b62bc897d697b1bb46f442cbb6a48f5ab6728701d7d1415efa91223725db708237b7637e8c34c8ad756b18d309a10a6a2a78ffeb3cc4c452637fe6
7
+ data.tar.gz: 4e3701f3d65594d6d284b99e86f8694d9565e87546570440ba89842163c1a1493aecdbbbc10e9ee755369f5e6a2ce66c351947b584b3d8bca5b8d9c13c640a20
data/README.md CHANGED
@@ -62,12 +62,12 @@ cd /lib/snow_sync
62
62
  ```
63
63
 
64
64
  * Setup the configurations in the configs.yml
65
- * Now supports multi-table map configurations
65
+ * Supports multi-table map configurations
66
66
  * YAML configuration path is the current working directory
67
67
  * Append /api/now/table/ to the base_url
68
68
 
69
69
  ```bash
70
- guard -i
70
+ bundle exec guard -i
71
71
  ```
72
72
 
73
73
  **Note:** if the sync directory is deleted after a successful sync, reset the credential configs in the configs.yml so they can be re-encrypted on the next sync
@@ -79,7 +79,7 @@ guard -i
79
79
  cd <path-to-the-snow-sync-dir>/gems/snow_sync-<version>
80
80
  ```
81
81
 
82
- * Integration tests use a test record in the instance, unit tests do not
82
+ * Integration tests use a test record in the test instance
83
83
  * Setup the test configurations in the test_configs.yml
84
84
  * YAML configuration path is the current working directory
85
85
  * Append /api/now/table/ to the base_url
@@ -88,6 +88,12 @@ cd <path-to-the-snow-sync-dir>/gems/snow_sync-<version>
88
88
  bundle exec rspec spec/sync_util_spec.rb
89
89
  ```
90
90
 
91
+ * Unit tests are pure, so they're not externally dependent
92
+
93
+ ```ruby
94
+ bundle exec rspec spec/sync_util_mock_spec.rb
95
+ ```
96
+
91
97
  **Note:** if the sync directory is deleted after a successful sync, reset the credential configs in the test_configs.yml so they can be re-encrypted on the next sync
92
98
 
93
99
  ## License
@@ -16,18 +16,19 @@ yield_options = {
16
16
  logger.info "Guard::Yield - Done!"
17
17
  end,
18
18
 
19
- run_on_modifications: proc do |log, _, files|
20
- log.info "!!: #{files * ','}"
19
+ run_on_modifications: proc do |logger, _, files|
21
20
  @util.push_modifications(files)
22
- @util.notify(files, log)
21
+ logger.info "!!: #{files}"
22
+ uname = `uname`.chomp.downcase
23
+ @util.notify(files, uname, logger)
23
24
  end,
24
25
 
25
- run_on_additions: proc do |log, _, files|
26
- log.info "++: #{files * ','}"
26
+ run_on_additions: proc do |logger, _, files|
27
+ logger.info "++: #{files}"
27
28
  end,
28
29
 
29
- run_on_removals: proc do |log, _, files|
30
- log.warn "xx: #{files * ','}"
30
+ run_on_removals: proc do |logger, _, files|
31
+ logger.warn "xx: #{files}"
31
32
  end,
32
33
 
33
34
  }
@@ -6,6 +6,7 @@ base_url:
6
6
  creds:
7
7
  user:
8
8
  pass:
9
+ encrypted:
9
10
 
10
11
  table_map:
11
12
  script_include:
@@ -75,8 +75,7 @@ module SnowSync
75
75
  # Encrypts config credentials based on previous sync
76
76
 
77
77
  def encrypt_credentials
78
- previous_sync = File.directory?("sync")
79
- if !previous_sync
78
+ unless @configs["creds"]["encrypted"]
80
79
  configs_path = @configs["conf_path"] + @cf
81
80
  configs = YAML::load_file(configs_path)
82
81
  # local configuration changes
@@ -84,10 +83,12 @@ module SnowSync
84
83
  passb64 = Base64.strict_encode64(@configs["creds"]["pass"])
85
84
  configs["creds"]["user"] = userb64
86
85
  configs["creds"]["pass"] = passb64
86
+ configs["creds"]["encrypted"] = true
87
87
  File.open(configs_path, 'w') { |f| YAML::dump(configs, f) }
88
88
  # object state configuration changes
89
89
  @configs["creds"]["user"] = userb64
90
90
  @configs["creds"]["pass"] = passb64
91
+ @configs["creds"]["encrypted"] = true
91
92
  end
92
93
  end
93
94
 
@@ -155,9 +156,8 @@ module SnowSync
155
156
  # Merges JS file changes with the encapsulated table response value
156
157
  # @param [String] type Config table label
157
158
  # @param [String] file JS file by name
158
- # @param [Hash] table_hash Configured servicenow table hash
159
159
 
160
- def merge_update(type, file, table_hash)
160
+ def merge_update(type, file)
161
161
  FileUtils.cd("sync" + "/" + type)
162
162
  script_body = File.open(file).read
163
163
  @configs["table_map"][type]["mod"] = script_body
@@ -182,7 +182,7 @@ module SnowSync
182
182
  type = path[1]
183
183
  file = path[2]
184
184
  table_hash = table_lookup(type, file)
185
- merge_update(type, file, table_hash)
185
+ merge_update(type, file)
186
186
  begin
187
187
  user = Base64.strict_decode64(@configs["creds"]["user"])
188
188
  pass = Base64.strict_decode64(@configs["creds"]["pass"])
@@ -201,22 +201,22 @@ module SnowSync
201
201
 
202
202
  # Dispatches osx & linux platform notification when file updates are pushed
203
203
  # @param [Array] update File updated
204
- # @param [Object] log Log object
204
+ # @param [String] uname Operating system name
205
+ # @param [Object] logger Logger object
205
206
 
206
- def notify(update, log)
207
- if `uname` =~ /Darwin/
207
+ def notify(update, uname, logger)
208
+ if uname =~ /darwin/
208
209
  TerminalNotifier::Guard.success(
209
- "File: #{update * ','}",
210
+ "File: #{update}",
210
211
  :title => "ServiceNow Script Update"
211
212
  )
212
- log.info "->: osx notification dispatched"
213
- elsif `uname` =~ /Linux/
213
+ logger.info "->: osx notification dispatched"
214
+ elsif uname =~ /linux/
214
215
  Libnotify.show(
215
216
  :summary => "ServiceNow Script Update",
216
- :body => "File: #{update * ','}",
217
- :timeout => 1.5
217
+ :body => "File: #{update}"
218
218
  )
219
- log.info "->: linux notification dispatched"
219
+ logger.info "->: linux notification dispatched"
220
220
  end
221
221
  end
222
222
 
@@ -1,3 +1,3 @@
1
1
  module SnowSync
2
- VERSION = "3.1.5"
2
+ VERSION = "3.1.6"
3
3
  end
data/spec/spec_helper.rb CHANGED
@@ -5,8 +5,8 @@ RSpec.configure do |config|
5
5
  require "json"
6
6
  require_relative "../lib/snow_sync/sync_util.rb"
7
7
 
8
- @util = SnowSync::SyncUtil.new(opts = "test")
9
- @util.encrypt_credentials
8
+ config.color
9
+ config.formatter = :documentation
10
10
 
11
11
  config.expect_with :rspec do |expectations|
12
12
  expectations.include_chain_clauses_in_custom_matcher_descriptions = true
@@ -0,0 +1,549 @@
1
+ require "spec_helper"
2
+
3
+ describe "#initialize" do
4
+
5
+ before do
6
+ allow(YAML).to receive(:load_file)
7
+ allow(Logger).to receive(:new)
8
+ end
9
+
10
+ it "should construct an instance" do
11
+ SnowSync::SyncUtil.new(opts = "test")
12
+ expect(YAML).to have_received(:load_file).with("test_configs.yml")
13
+ expect(Logger).to have_received(:new).with(STDERR)
14
+ end
15
+
16
+ end
17
+
18
+ describe "#create_directory" do
19
+
20
+ let :util do
21
+ SnowSync::SyncUtil.new(opts = "test")
22
+ end
23
+
24
+ let :logger do
25
+ instance_double(Logger)
26
+ end
27
+
28
+ let :dir_name do
29
+ "sync"
30
+ end
31
+
32
+ before do
33
+ allow(File).to receive(:directory?).and_return(false)
34
+ allow(FileUtils).to receive(:mkdir_p)
35
+ allow(Logger).to receive(:new).and_return(logger)
36
+ allow(logger).to receive(:info)
37
+ end
38
+
39
+ it "should create a directory" do
40
+ util.create_directory(dir_name)
41
+ expect(File).to have_received(:directory?).with(dir_name)
42
+ expect(FileUtils).to have_received(:mkdir_p).with(dir_name)
43
+ expect(logger).to have_received(:info).with("++: #{dir_name}")
44
+ end
45
+
46
+ end
47
+
48
+ describe "#create_subdirectory" do
49
+
50
+ let :util do
51
+ SnowSync::SyncUtil.new(opts = "test")
52
+ end
53
+
54
+ let :path do
55
+ proc { FileUtils.cd("sync") }
56
+ end
57
+
58
+ let :sub_dir_name do
59
+ "sub-dir-of-sync"
60
+ end
61
+
62
+ before do
63
+ allow_any_instance_of(SnowSync::SyncUtil).to receive(:create_directory)
64
+ .and_return("++: #{sub_dir_name}")
65
+ end
66
+
67
+ it "should create a subdirectory" do
68
+ expect(util.create_subdirectory(sub_dir_name, &path)).to eq("++: #{sub_dir_name}")
69
+ end
70
+
71
+ end
72
+
73
+ describe "#create_file" do
74
+
75
+ let :util do
76
+ SnowSync::SyncUtil.new(opts = "test")
77
+ end
78
+
79
+ let :logger do
80
+ instance_double(Logger)
81
+ end
82
+
83
+ let :file_name do
84
+ "test_file"
85
+ end
86
+
87
+ let :json do
88
+ { "test-json": "testing" }
89
+ end
90
+
91
+ let :path do
92
+ proc { }
93
+ end
94
+
95
+ before do
96
+ allow(File).to receive(:open).and_call_original
97
+ allow(Logger).to receive(:new).and_return(logger)
98
+ allow(logger).to receive(:info)
99
+ end
100
+
101
+ after do
102
+ test_file = `ls`.split("\n").pop
103
+ FileUtils.rm_rf(test_file)
104
+ end
105
+
106
+ it "should create a js file" do
107
+ util.create_file(file_name, json, &path)
108
+ expect(File).to have_received(:open).with(file_name + ".js", "w")
109
+ expect(logger).to have_received(:info).with("->: #{file_name}" + ".js")
110
+ expect(`ls`.split("\n").pop).to eq("test_file.js")
111
+ expect(File.open("#{file_name}.js").read).to eq("{:\"test-json\"=>\"testing\"}")
112
+ end
113
+
114
+ end
115
+
116
+ describe "#check_required_configs" do
117
+
118
+ let :util do
119
+ SnowSync::SyncUtil.new(opts = "test")
120
+ end
121
+
122
+ it "should raise an exception when there is no config path" do
123
+ util.configs["conf_path"] = nil
124
+ expect{util.check_required_configs}.to raise_error(
125
+ /Check the configuration path, base url, credentials or table to sync/)
126
+ end
127
+
128
+ it "should raise an exception when there is no base url" do
129
+ util.configs["base_url"] = nil
130
+ expect{util.check_required_configs}.to raise_error(
131
+ /Check the configuration path, base url, credentials or table to sync/)
132
+ end
133
+
134
+ it "should raise an exception when there is no username" do
135
+ util.configs["creds"]["user"] = nil
136
+ expect{util.check_required_configs}.to raise_error(
137
+ /Check the configuration path, base url, credentials or table to sync/)
138
+ end
139
+
140
+ it "should raise an exception when there is no password" do
141
+ util.configs["creds"]["pass"] = nil
142
+ expect{util.check_required_configs}.to raise_error(
143
+ /Check the configuration path, base url, credentials or table to sync/)
144
+ end
145
+
146
+ it "should raise an exception when there are no tables mapped" do
147
+ tables = util.configs["table_map"].keys
148
+ tables.each do |table|
149
+ util.configs["table_map"][table]["table"] = nil
150
+ expect{util.check_required_configs}.to raise_error(
151
+ /Check the configuration path, base url, credentials or table to sync/)
152
+ end
153
+ end
154
+
155
+ end
156
+
157
+ describe "#encrypt_credentials" do
158
+
159
+ let :util do
160
+ SnowSync::SyncUtil.new(opts = "test")
161
+ end
162
+
163
+ before do
164
+ FileUtils.touch("spec/test_configs.yml")
165
+ local_configs = {
166
+ "conf_path" => "spec/",
167
+ "base_url" => nil,
168
+ "creds" => {
169
+ "user" => "test-name",
170
+ "pass" => "test-password",
171
+ "encrypted" => false
172
+ }
173
+ }
174
+ allow(YAML).to receive(:load_file).and_return(local_configs)
175
+ allow(Base64).to receive(:strict_encode64).and_call_original
176
+ allow(File).to receive(:open).and_call_original
177
+ end
178
+
179
+ after do
180
+ FileUtils.rm_rf("spec/test_configs.yml")
181
+ end
182
+
183
+ it "should encrypt credentials" do
184
+ util.configs["conf_path"] = "spec/"
185
+ util.configs["creds"]["user"] = "test-name"
186
+ util.configs["creds"]["pass"] = "test-password"
187
+ util.encrypt_credentials
188
+ expect(YAML).to have_received(:load_file).with("spec/test_configs.yml")
189
+ allow(Base64).to receive(:strict_encode64).twice
190
+ expect(File).to have_received(:open).with("spec/test_configs.yml", "w")
191
+ # configs object state updates
192
+ expect(util.configs["creds"]["user"]).to eq("dGVzdC1uYW1l")
193
+ expect(util.configs["creds"]["pass"]).to eq("dGVzdC1wYXNzd29yZA==")
194
+ expect(util.configs["creds"]["encrypted"]).to eq(true)
195
+ # test configs file updates
196
+ encrypted_content = YAML::load_file("spec/test_configs.yml")
197
+ expect(encrypted_content["creds"]["user"]).to eq("dGVzdC1uYW1l")
198
+ expect(encrypted_content["creds"]["pass"]).to eq("dGVzdC1wYXNzd29yZA==")
199
+ expect(encrypted_content["creds"]["encrypted"]).to eq(true)
200
+ end
201
+ end
202
+
203
+ describe "#run_setup_and_sync" do
204
+
205
+ let :util do
206
+ SnowSync::SyncUtil.new(opts = "test")
207
+ end
208
+
209
+ let :logger do
210
+ instance_double(Logger)
211
+ end
212
+
213
+ before do
214
+ allow(Base64).to receive(:strict_decode64).and_call_original
215
+ allow(Base64).to receive(:strict_encode64).and_call_original
216
+ allow(RestClient).to receive(:get).and_return("{\"result\":[{ \"status\": \"200\" }]}")
217
+ allow(FileUtils).to receive(:cd)
218
+ end
219
+
220
+ it "should run setup & sync - sync directory present path" do
221
+ # allow not included in 'before' setup to set return bool
222
+ allow(File).to receive(:directory?).and_return(true)
223
+ expect_any_instance_of(SnowSync::SyncUtil).to receive(:create_subdirectory)
224
+ expect_any_instance_of(SnowSync::SyncUtil).to receive(:create_file)
225
+ util.configs = { "conf_path" => nil,
226
+ "base_url" => "https://test.com/api/now/table/",
227
+ "creds" => {
228
+ "user" => "dGVzdC1uYW1l",
229
+ "pass" => "dGVzdC1wYXNzd29yZA=="
230
+ },
231
+ "table_map" => {
232
+ "script_include" => {
233
+ "name" => "TestClass",
234
+ "table" => "sys_script_include",
235
+ "sys_id" => "xxxxxx-sysid-xxxxxx",
236
+ "field" => "test-field"
237
+ }
238
+ }
239
+ }
240
+ util.run_setup_and_sync
241
+ expect(File).to have_received(:directory?).with("sync")
242
+ expect(Base64).to have_received(:strict_decode64).with("dGVzdC1uYW1l")
243
+ expect(Base64).to have_received(:strict_decode64).with("dGVzdC1wYXNzd29yZA==")
244
+ expect(Base64).to have_received(:strict_encode64).with("test-name:test-password")
245
+ expect(RestClient).to have_received(:get).with(
246
+ "https://test.com/api/now/table/sys_script_include?sysparm_query=sys_id%3D" +
247
+ "xxxxxx-sysid-xxxxxx%5Ename%3DTestClass",
248
+ {:authorization => "Basic " + "dGVzdC1uYW1lOnRlc3QtcGFzc3dvcmQ=",
249
+ :accept => "application/json"})
250
+ expect(FileUtils).to have_received(:cd).with("../..")
251
+ end
252
+
253
+ it "should run setup & sync - sync directory not present path" do
254
+ # allow not included in 'before' setup to set return bool
255
+ allow(File).to receive(:directory?).and_return(false)
256
+ expect_any_instance_of(SnowSync::SyncUtil).to receive(:create_directory)
257
+ expect_any_instance_of(SnowSync::SyncUtil).to receive(:create_subdirectory)
258
+ expect_any_instance_of(SnowSync::SyncUtil).to receive(:create_file)
259
+ util.configs = { "conf_path" => nil,
260
+ "base_url" => "https://test.com/api/now/table/",
261
+ "creds" => {
262
+ "user" => "dGVzdC1uYW1l",
263
+ "pass" => "dGVzdC1wYXNzd29yZA=="
264
+ },
265
+ "table_map" => {
266
+ "script_include" => {
267
+ "name" => "TestClass",
268
+ "table" => "sys_script_include",
269
+ "sys_id" => "xxxxxx-sysid-xxxxxx",
270
+ "field" => "test-field"
271
+ }
272
+ }
273
+ }
274
+ util.run_setup_and_sync
275
+ expect(File).to have_received(:directory?).with("sync")
276
+ expect(Base64).to have_received(:strict_decode64).with("dGVzdC1uYW1l")
277
+ expect(Base64).to have_received(:strict_decode64).with("dGVzdC1wYXNzd29yZA==")
278
+ expect(Base64).to have_received(:strict_encode64).with("test-name:test-password")
279
+ expect(RestClient).to have_received(:get).with(
280
+ "https://test.com/api/now/table/sys_script_include?sysparm_query=sys_id%3D" +
281
+ "xxxxxx-sysid-xxxxxx%5Ename%3DTestClass",
282
+ {:authorization => "Basic " + "dGVzdC1uYW1lOnRlc3QtcGFzc3dvcmQ=",
283
+ :accept => "application/json"})
284
+ expect(FileUtils).to have_received(:cd).with("../..")
285
+ end
286
+
287
+ it "should handle an exception" do
288
+ # allow not included in 'before' setup to set return bool
289
+ allow(File).to receive(:directory?).and_return(true)
290
+ expect_any_instance_of(SnowSync::SyncUtil).to receive(:create_subdirectory)
291
+ allow(RestClient).to receive(:get).and_raise(RestClient::ExceptionWithResponse)
292
+ allow(Logger).to receive(:new).and_return(logger)
293
+ allow(logger).to receive(:error)
294
+ util.configs = { "conf_path" => nil,
295
+ "base_url" => "https://test.com/api/now/table/",
296
+ "creds" => {
297
+ "user" => "dGVzdC1uYW1l",
298
+ "pass" => "dGVzdC1wYXNzd29yZA=="
299
+ },
300
+ "table_map" => {
301
+ "script_include" => {
302
+ "name" => "TestClass",
303
+ "table" => "sys_script_include",
304
+ "sys_id" => "xxxxxx-sysid-xxxxxx",
305
+ "field" => "test-field"
306
+ }
307
+ }
308
+ }
309
+ util.run_setup_and_sync
310
+ expect(logger).to have_received(:error)
311
+ .with("ERROR: RestClient::ExceptionWithResponse").once
312
+ end
313
+
314
+ end
315
+
316
+ describe "#classify" do
317
+
318
+ let :util do
319
+ SnowSync::SyncUtil.new(opts = "test")
320
+ end
321
+
322
+ it "should convert snake_case string to CamelCase" do
323
+ expect(util.classify("test_class.js")).to eq("TestClass")
324
+ end
325
+
326
+ end
327
+
328
+ describe "#table_lookup" do
329
+
330
+ let :util do
331
+ SnowSync::SyncUtil.new(opts = "test")
332
+ end
333
+
334
+ it "should return configured SN table" do
335
+ util.configs = { "conf_path" => nil,
336
+ "base_url" => "https://test.com/api/now/table/",
337
+ "creds" => {
338
+ "user" => "dGVzdC1uYW1l",
339
+ "pass" => "dGVzdC1wYXNzd29yZA=="
340
+ },
341
+ "table_map" => {
342
+ "script_include" => {
343
+ "name" => "TestClass",
344
+ "table" => "sys_script_include",
345
+ "sys_id" => "xxxxxx-sysid-xxxxxx",
346
+ "field" => "test-field"
347
+ }
348
+ }
349
+ }
350
+ table_map = util.table_lookup("script_include", "test_class.js")
351
+ expect(table_map == { "name" => "TestClass",
352
+ "table" => "sys_script_include",
353
+ "sys_id" => "xxxxxx-sysid-xxxxxx",
354
+ "field" => "test-field"
355
+ }).to be(true)
356
+ end
357
+
358
+ end
359
+
360
+ describe "#merge_update" do
361
+
362
+ let! :util do
363
+ SnowSync::SyncUtil.new(opts = "test")
364
+ end
365
+
366
+ before do
367
+ allow(FileUtils).to receive(:cd)
368
+ allow(File).to receive(:open).and_return(IO)
369
+ allow(IO).to receive(:read).and_return("var x = 10;")
370
+ end
371
+
372
+ it "should merge a script change" do
373
+ util.configs = { "table_map" => {
374
+ "script_include" => {
375
+ "name" => "TestClass",
376
+ "table" => "sys_script_include",
377
+ "sys_id" => "xxxxxx-sysid-xxxxxx",
378
+ "field" => "test-field"
379
+ }
380
+ }
381
+ }
382
+ util.merge_update("script_include", "test_class.js")
383
+ expect(File).to have_received(:open).with("test_class.js")
384
+ expect(IO).to have_received(:read)
385
+ expect(FileUtils).to have_received(:cd).twice
386
+ expect(util.configs == { "table_map" => {
387
+ "script_include" => {
388
+ "name" => "TestClass",
389
+ "table" => "sys_script_include",
390
+ "sys_id" => "xxxxxx-sysid-xxxxxx",
391
+ "field" => "test-field",
392
+ "mod" => "var x = 10;"
393
+ }
394
+ }}).to be(true)
395
+ end
396
+
397
+ end
398
+
399
+ describe "#start_sync" do
400
+
401
+ let :util do
402
+ SnowSync::SyncUtil.new(opts = "test")
403
+ end
404
+
405
+ before do
406
+ allow_any_instance_of(SnowSync::SyncUtil).to receive(:check_required_configs)
407
+ allow_any_instance_of(SnowSync::SyncUtil).to receive(:encrypt_credentials)
408
+ allow_any_instance_of(SnowSync::SyncUtil).to receive(:run_setup_and_sync)
409
+ .and_return("sync-and-setup-complete!")
410
+ end
411
+
412
+ it "should create a subdirectory" do
413
+ expect(util.start_sync).to eq("sync-and-setup-complete!")
414
+ end
415
+
416
+ end
417
+
418
+ describe "#push_modifications" do
419
+
420
+ let :util do
421
+ SnowSync::SyncUtil.new(opts = "test")
422
+ end
423
+
424
+ let :logger do
425
+ instance_double(Logger)
426
+ end
427
+
428
+ before do
429
+ allow_any_instance_of(SnowSync::SyncUtil).to receive(:table_lookup)
430
+ .and_return({
431
+ "name" => "TestClass",
432
+ "table" => "sys_script_include",
433
+ "sys_id" => "xxxxxx-sysid-xxxxxx",
434
+ "field" => "test-field",
435
+ "mod" => "var x = 10;"
436
+ })
437
+ allow_any_instance_of(SnowSync::SyncUtil).to receive(:merge_update)
438
+ allow(Base64).to receive(:strict_decode64).and_call_original
439
+ allow(Base64).to receive(:strict_encode64).and_call_original
440
+ allow(RestClient).to receive(:patch).and_return("{\"result\":[{ \"status\": \"201\" }]}")
441
+ end
442
+
443
+ it "should push modifications to the instance" do
444
+ util.configs = { "conf_path" => nil,
445
+ "base_url" => "https://test.com/api/now/table/",
446
+ "creds" => {
447
+ "user" => "dGVzdC1uYW1l",
448
+ "pass" => "dGVzdC1wYXNzd29yZA=="
449
+ },
450
+ "table_map" => {
451
+ "script_include" => {
452
+ "name" => "TestClass",
453
+ "table" => "sys_script_include",
454
+ "sys_id" => "xxxxxx-sysid-xxxxxx",
455
+ "field" => "test-field",
456
+ "mod" => "var x = 10;"
457
+ }
458
+ }
459
+ }
460
+ util.push_modifications(["sync/script_include/test_class.js"])
461
+ expect(Base64).to have_received(:strict_decode64).with("dGVzdC1uYW1l")
462
+ expect(Base64).to have_received(:strict_decode64).with("dGVzdC1wYXNzd29yZA==")
463
+ expect(Base64).to have_received(:strict_encode64).with("test-name:test-password")
464
+ expect(RestClient).to have_received(:patch).with(
465
+ "https://test.com/api/now/table/sys_script_include/xxxxxx-sysid-xxxxxx",
466
+ "{\"test-field\":\"var x = 10;\"}",
467
+ {:authorization => "Basic " + "dGVzdC1uYW1lOnRlc3QtcGFzc3dvcmQ=",
468
+ :content_type => "application/json", :accept => "application/json"})
469
+ end
470
+
471
+ it "should handle an exception" do
472
+ allow(RestClient).to receive(:patch).and_raise(RestClient::ExceptionWithResponse)
473
+ allow(Logger).to receive(:new).and_return(logger)
474
+ allow(logger).to receive(:error)
475
+ util.configs = { "conf_path" => nil,
476
+ "base_url" => "https://test.com/api/now/table/",
477
+ "creds" => {
478
+ "user" => "dGVzdC1uYW1l",
479
+ "pass" => "dGVzdC1wYXNzd29yZA=="
480
+ },
481
+ "table_map" => {
482
+ "script_include" => {
483
+ "name" => "TestClass",
484
+ "table" => "sys_script_include",
485
+ "sys_id" => "xxxxxx-sysid-xxxxxx",
486
+ "field" => "test-field",
487
+ "mod" => "var x = 10;"
488
+ }
489
+ }
490
+ }
491
+ util.push_modifications(["sync/script_include/test_class.js"])
492
+ expect(logger).to have_received(:error)
493
+ .with("ERROR: RestClient::ExceptionWithResponse").once
494
+ end
495
+
496
+ end
497
+
498
+ describe "#notify" do
499
+
500
+ let :util do
501
+ SnowSync::SyncUtil.new(opts = "test")
502
+ end
503
+
504
+ let :logger do
505
+ instance_double(Logger)
506
+ end
507
+
508
+ let :update do
509
+ "test_class"
510
+ end
511
+
512
+ let :macosx? do
513
+ `uname`.chomp.downcase == "darwin"
514
+ end
515
+
516
+ let :linux? do
517
+ `uname`.chomp.downcase == "linux"
518
+ end
519
+
520
+ before do
521
+ allow(TerminalNotifier::Guard).to receive(:success) if macosx?
522
+ allow(Libnotify).to receive(:show) if linux?
523
+ allow(Logger).to receive(:new).and_return(logger)
524
+ allow(logger).to receive(:info)
525
+ end
526
+
527
+ condition = `uname`.chomp.downcase == "darwin"
528
+ context "when true", if: condition do
529
+ it "should send notification - macosx path" do
530
+ uname = "darwin"
531
+ util.notify(update, uname, util.logger)
532
+ expect(TerminalNotifier::Guard).to have_received(:success)
533
+ .with("File: #{update}", :title => "ServiceNow Script Update")
534
+ expect(logger).to have_received(:info).with("->: osx notification dispatched")
535
+ end
536
+ end
537
+
538
+ condition = `uname`.chomp.downcase == "linux"
539
+ context "when true", if: condition do
540
+ it "should send notification - linux path" do
541
+ uname = "linux"
542
+ util.notify(update, uname, util.logger)
543
+ expect(Libnotify).to have_received(:show)
544
+ .with(:summary => "ServiceNow Script Update", :body => "File: #{update}")
545
+ expect(logger).to have_received(:info).with("->: linux notification dispatched")
546
+ end
547
+ end
548
+
549
+ end
@@ -2,7 +2,7 @@ require "spec_helper"
2
2
 
3
3
  describe "utility object" do
4
4
 
5
- let! :util do
5
+ let :util do
6
6
  SnowSync::SyncUtil.new(opts = "test")
7
7
  end
8
8
 
@@ -20,22 +20,22 @@ describe "utility object" do
20
20
 
21
21
  end
22
22
 
23
- describe "create_directory" do
23
+ describe "#create_directory" do
24
24
 
25
- let! :util do
25
+ let :util do
26
26
  SnowSync::SyncUtil.new(opts = "test")
27
27
  end
28
28
 
29
- let! :created_time do
30
- util.create_directory("sync")
31
- return File.ctime("sync")
32
- end
33
-
34
29
  it "should create a directory" do
30
+ util.create_directory("sync")
35
31
  dir = `ls`.split("\n")
36
32
  expect(dir.include?("sync")).to eq true
37
33
  end
38
34
 
35
+ let :created_time do
36
+ File.ctime("sync")
37
+ end
38
+
39
39
  it "should not create directory" do
40
40
  util.create_directory("sync")
41
41
  check_created_time = File.ctime("sync")
@@ -44,15 +44,22 @@ describe "create_directory" do
44
44
 
45
45
  end
46
46
 
47
- describe "create_file" do
47
+ describe "#create_file" do
48
48
 
49
- let! :util do
49
+ let :util do
50
50
  SnowSync::SyncUtil.new(opts = "test")
51
51
  end
52
52
 
53
- it "should create a file" do
54
- FileUtils.mkdir_p("sync")
53
+ before do
55
54
  FileUtils.mkdir_p("sync/test_sub_dir")
55
+ end
56
+
57
+ after do
58
+ FileUtils.cd("../..")
59
+ FileUtils.rm_rf("sync")
60
+ end
61
+
62
+ it "should create a file" do
56
63
  json = { "property" => "value" }
57
64
  name = "TestClass".snakecase
58
65
  path = proc do
@@ -60,13 +67,11 @@ describe "create_file" do
60
67
  end
61
68
  util.create_file(name, json, &path)
62
69
  expect(File.exists?("test_class.js")).to eq true
63
- FileUtils.cd("../..")
64
- FileUtils.rm_rf("sync")
65
70
  end
66
71
 
67
72
  end
68
73
 
69
- describe "check_required_configs" do
74
+ describe "#check_required_configs" do
70
75
 
71
76
  let :util do
72
77
  SnowSync::SyncUtil.new(opts = "test")
@@ -74,35 +79,40 @@ describe "check_required_configs" do
74
79
 
75
80
  it "should raise an exception when there is no config path" do
76
81
  util.configs["conf_path"] = nil
77
- expect{util.check_required_configs}.to raise_error(/Check the configuration path, base url, credentials or table to sync/)
82
+ expect{util.check_required_configs}.to raise_error(
83
+ /Check the configuration path, base url, credentials or table to sync/)
78
84
  end
79
85
 
80
86
  it "should raise an exception when there is no base url" do
81
87
  util.configs["base_url"] = nil
82
- expect{util.check_required_configs}.to raise_error(/Check the configuration path, base url, credentials or table to sync/)
88
+ expect{util.check_required_configs}.to raise_error(
89
+ /Check the configuration path, base url, credentials or table to sync/)
83
90
  end
84
91
 
85
92
  it "should raise an exception when there is no username" do
86
93
  util.configs["creds"]["user"] = nil
87
- expect{util.check_required_configs}.to raise_error(/Check the configuration path, base url, credentials or table to sync/)
94
+ expect{util.check_required_configs}.to raise_error(
95
+ /Check the configuration path, base url, credentials or table to sync/)
88
96
  end
89
97
 
90
98
  it "should raise an exception when there is no password" do
91
99
  util.configs["creds"]["pass"] = nil
92
- expect{util.check_required_configs}.to raise_error(/Check the configuration path, base url, credentials or table to sync/)
100
+ expect{util.check_required_configs}.to raise_error(
101
+ /Check the configuration path, base url, credentials or table to sync/)
93
102
  end
94
103
 
95
104
  it "should raise an exception when there are no tables mapped" do
96
105
  tables = util.configs["table_map"].keys
97
106
  tables.each do |table|
98
107
  util.configs["table_map"][table]["table"] = nil
99
- expect{util.check_required_configs}.to raise_error(/Check the configuration path, base url, credentials or table to sync/)
108
+ expect{util.check_required_configs}.to raise_error(
109
+ /Check the configuration path, base url, credentials or table to sync/)
100
110
  end
101
111
  end
102
112
 
103
113
  end
104
114
 
105
- describe "classify" do
115
+ describe "#classify" do
106
116
 
107
117
  let :util do
108
118
  SnowSync::SyncUtil.new(opts = "test")
@@ -117,7 +127,7 @@ describe "classify" do
117
127
 
118
128
  end
119
129
 
120
- describe "table_lookup" do
130
+ describe "#table_lookup" do
121
131
 
122
132
  let :util do
123
133
  SnowSync::SyncUtil.new(opts = "test")
@@ -131,15 +141,21 @@ describe "table_lookup" do
131
141
 
132
142
  end
133
143
 
134
- describe "merge_update" do
144
+ describe "#merge_update" do
135
145
 
136
- let! :util do
146
+ let :util do
137
147
  SnowSync::SyncUtil.new(opts = "test")
138
148
  end
139
149
 
150
+ before do
151
+ FileUtils.mkdir_p("sync/script_include")
152
+ end
153
+
154
+ after do
155
+ FileUtils.rm_rf("sync")
156
+ end
157
+
140
158
  it "should merge script with the configs object" do
141
- FileUtils.mkdir_p("sync")
142
- FileUtils.mkdir_p("sync/script_include")
143
159
  json_resp = "var test = 'test'; \n" +
144
160
  "var testing = function(arg) { \n\tgs.print(arg) \n}; \n" +
145
161
  "testing('test');"
@@ -153,25 +169,30 @@ describe "merge_update" do
153
169
  path = file.split("/")
154
170
  type = path[1]
155
171
  file = path[2]
156
- table_map = util.table_lookup(type, file)
157
- util.merge_update(type, file, table_map)
172
+ util.merge_update(type, file)
158
173
  expect(util.configs["table_map"]["script_include"]["mod"] != nil).to eq true
159
- FileUtils.rm_rf("sync")
160
174
  end
161
175
 
162
176
  end
163
177
 
164
- describe "setup_sync_directories" do
178
+ describe "#run_setup_and_sync" do
165
179
 
166
- let! :util do
180
+ let :util do
167
181
  SnowSync::SyncUtil.new(opts = "test")
168
182
  end
169
183
 
170
- it "should setup and synchronize field from the SN instance" do
184
+ before do
185
+ util.encrypt_credentials
186
+ end
187
+
188
+ after do
189
+ FileUtils.rm_rf("sync")
190
+ end
191
+
192
+ it "should setup file locally and sync code from the instance" do
171
193
  util.run_setup_and_sync
172
194
  file = File.open("sync/script_include/test_class.js")
173
195
  expect(file.is_a?(Object)).to eq true
174
- FileUtils.rm_rf("sync")
175
196
  end
176
197
 
177
198
  end
@@ -182,23 +203,32 @@ describe "push_modifications - single table configuration" do
182
203
  SnowSync::SyncUtil.new(opts = "test")
183
204
  end
184
205
 
206
+ before do
207
+ util.encrypt_credentials
208
+ end
209
+
210
+ after do
211
+ FileUtils.rm_rf("sync")
212
+ end
213
+
185
214
  it "should push modifications to a configured instance" do
186
215
  util.run_setup_and_sync
187
216
  file = File.open("sync/script_include/test_class.js", "r+")
188
217
  lines = file.readlines
189
218
  file.close
190
- lines[0] = "// test comment -\n"
219
+ lines[0] = "// test comment - single push \n"
191
220
  newfile = File.new("sync/script_include/test_class.js", "w")
192
221
  lines.each do |line|
193
222
  newfile.write(line)
194
223
  end
195
224
  newfile.close
196
225
  util.push_modifications(["sync/script_include/test_class.js"])
226
+ # resync confirms mods were pushed to the instance
197
227
  util.run_setup_and_sync
198
228
  file = File.open("sync/script_include/test_class.js", "r+")
199
229
  lines = file.readlines
200
230
  file.close
201
- expect(lines[0]).to eq "// test comment -\n"
231
+ expect(lines[0]).to eq "// test comment - single push \n"
202
232
  end
203
233
 
204
234
  end
@@ -209,7 +239,15 @@ describe "push_modifications - mutli-table configuration" do
209
239
  SnowSync::SyncUtil.new(opts = "test")
210
240
  end
211
241
 
212
- it "should sync, update, queue, push, re-sync mods for a configured instance" do
242
+ before do
243
+ util.encrypt_credentials
244
+ end
245
+
246
+ after do
247
+ FileUtils.rm_rf("sync")
248
+ end
249
+
250
+ it "should push modifications to a configured instance" do
213
251
  def do_edit(file, edit)
214
252
  file = File.open(file, "r+")
215
253
  lines = file.readlines
@@ -229,14 +267,18 @@ describe "push_modifications - mutli-table configuration" do
229
267
  end
230
268
  util.run_setup_and_sync
231
269
  # sys_script_include
232
- do_edit("sync/script_include/test_class.js", "// test comment -\n")
270
+ do_edit(
271
+ "sync/script_include/test_class.js", "// test comment - multi push 1\n")
233
272
  # sys_ui_action
234
- do_edit("sync/ui_action/test_action.js", "// test comment -\n")
273
+ do_edit(
274
+ "sync/ui_action/test_action.js", "// test comment - multi push 2\n")
235
275
  # queued mods, push in sequence
236
- util.push_modifications(["sync/script_include/test_class.js", "sync/ui_action/test_action.js"])
276
+ util.push_modifications(
277
+ ["sync/script_include/test_class.js", "sync/ui_action/test_action.js"])
278
+ # resync confirms mods were pushed to the instance
237
279
  util.run_setup_and_sync
238
- run_check("sync/script_include/test_class.js", "// test comment -\n")
239
- run_check("sync/ui_action/test_action.js", "// test comment -\n")
280
+ run_check("sync/script_include/test_class.js", "// test comment - multi push 1\n")
281
+ run_check("sync/ui_action/test_action.js", "// test comment - multi push 2\n")
240
282
  end
241
283
 
242
284
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: snow_sync
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.5
4
+ version: 3.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Wallace
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-01-08 00:00:00.000000000 Z
11
+ date: 2022-01-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -197,6 +197,7 @@ files:
197
197
  - lib/snow_sync/version.rb
198
198
  - spec/docker_install_spec.rb
199
199
  - spec/spec_helper.rb
200
+ - spec/sync_util_mock_spec.rb
200
201
  - spec/sync_util_spec.rb
201
202
  homepage: https://rubygems.org/gems/snow_sync
202
203
  licenses: