pincerna 1.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +7 -0
  3. data/.rubocop.yml +77 -0
  4. data/.travis-gemfile +17 -0
  5. data/.travis.yml +7 -0
  6. data/.yardopts +1 -0
  7. data/CHANGELOG.md +3 -0
  8. data/Gemfile +23 -0
  9. data/LICENSE.md +21 -0
  10. data/README.md +211 -0
  11. data/Rakefile +45 -0
  12. data/bin/pincernad +56 -0
  13. data/docs/Pincerna.html +130 -0
  14. data/docs/Pincerna/Base.html +3051 -0
  15. data/docs/Pincerna/Bookmark.html +523 -0
  16. data/docs/Pincerna/Cache.html +767 -0
  17. data/docs/Pincerna/ChromeBookmark.html +308 -0
  18. data/docs/Pincerna/CurrencyConversion.html +589 -0
  19. data/docs/Pincerna/FirefoxBookmark.html +328 -0
  20. data/docs/Pincerna/Ip.html +1017 -0
  21. data/docs/Pincerna/Map.html +399 -0
  22. data/docs/Pincerna/SafariBookmark.html +308 -0
  23. data/docs/Pincerna/Server.html +673 -0
  24. data/docs/Pincerna/Translation.html +517 -0
  25. data/docs/Pincerna/UnitConversion.html +1042 -0
  26. data/docs/Pincerna/Version.html +189 -0
  27. data/docs/Pincerna/Vpn.html +561 -0
  28. data/docs/Pincerna/Weather.html +837 -0
  29. data/docs/_index.html +298 -0
  30. data/docs/class_list.html +54 -0
  31. data/docs/css/common.css +1 -0
  32. data/docs/css/full_list.css +57 -0
  33. data/docs/css/style.css +338 -0
  34. data/docs/file.README.html +327 -0
  35. data/docs/file_list.html +56 -0
  36. data/docs/frames.html +28 -0
  37. data/docs/index.html +327 -0
  38. data/docs/js/app.js +214 -0
  39. data/docs/js/full_list.js +178 -0
  40. data/docs/js/jquery.js +4 -0
  41. data/docs/method_list.html +389 -0
  42. data/docs/top-level-namespace.html +112 -0
  43. data/icon.png +0 -0
  44. data/images/chrome.png +0 -0
  45. data/images/currency.png +0 -0
  46. data/images/firefox.png +0 -0
  47. data/images/map.png +0 -0
  48. data/images/network.png +0 -0
  49. data/images/safari.png +0 -0
  50. data/images/translate.png +0 -0
  51. data/images/unit.png +0 -0
  52. data/images/vpn.png +0 -0
  53. data/images/weather.png +0 -0
  54. data/info.plist +961 -0
  55. data/it.cowtech.pincernad.plist +19 -0
  56. data/lib/pincerna.rb +30 -0
  57. data/lib/pincerna/base.rb +258 -0
  58. data/lib/pincerna/bookmark.rb +80 -0
  59. data/lib/pincerna/cache.rb +61 -0
  60. data/lib/pincerna/chrome_bookmark.rb +40 -0
  61. data/lib/pincerna/currency_conversion.rb +134 -0
  62. data/lib/pincerna/firefox_bookmark.rb +92 -0
  63. data/lib/pincerna/ip.rb +135 -0
  64. data/lib/pincerna/map.rb +30 -0
  65. data/lib/pincerna/safari_bookmark.rb +40 -0
  66. data/lib/pincerna/server.rb +85 -0
  67. data/lib/pincerna/translation.rb +67 -0
  68. data/lib/pincerna/unit_conversion.rb +120 -0
  69. data/lib/pincerna/version.rb +24 -0
  70. data/lib/pincerna/vpn.rb +74 -0
  71. data/lib/pincerna/weather.rb +188 -0
  72. data/pincerna.alfredworkflow +0 -0
  73. data/pincerna.gemspec +36 -0
  74. data/pincerna.sh +9 -0
  75. data/spec/cassettes/Pincerna_CurrencyConversion/_perform_filtering/should_return_valid_values.yml +38 -0
  76. data/spec/cassettes/Pincerna_Ip/_get_local_addresses/should_return_a_list_of_addresses.yml +47 -0
  77. data/spec/cassettes/Pincerna_Ip/_get_public_address/should_return_public_IP_address.yml +44 -0
  78. data/spec/cassettes/Pincerna_Translation/_perform_filtering/should_default_from_English_to_the_given_language_when_only_one_is_present.yml +124 -0
  79. data/spec/cassettes/Pincerna_Translation/_perform_filtering/should_query_Google_Translate_for_sentences_returning_no_alternatives.yml +51 -0
  80. data/spec/cassettes/Pincerna_Translation/_perform_filtering/should_query_Google_Translate_for_single_words.yml +71 -0
  81. data/spec/cassettes/Pincerna_Weather/_get_forecast/should_append_name.yml +177 -0
  82. data/spec/cassettes/Pincerna_Weather/_get_forecast/should_get_correct_forecasts.yml +339 -0
  83. data/spec/cassettes/Pincerna_Weather/_lookup_places/should_return_an_existing_WOEID_without_making_any_request.yml +56 -0
  84. data/spec/cassettes/Pincerna_Weather/_lookup_places/should_search_for_places.yml +189 -0
  85. data/spec/cassettes/Pincerna_Weather/_perform_filtering/should_get_forecast.yml +56 -0
  86. data/spec/coverage_helper.rb +44 -0
  87. data/spec/pincerna/base_spec.rb +166 -0
  88. data/spec/pincerna/bookmark_spec.rb +65 -0
  89. data/spec/pincerna/cache_spec.rb +88 -0
  90. data/spec/pincerna/chrome_bookmark_spec.rb +114 -0
  91. data/spec/pincerna/currency_conversion_spec.rb +46 -0
  92. data/spec/pincerna/firefox_bookmark_spec.rb +46 -0
  93. data/spec/pincerna/ip_spec.rb +194 -0
  94. data/spec/pincerna/map_spec.rb +24 -0
  95. data/spec/pincerna/safari_bookmark_spec.rb +237 -0
  96. data/spec/pincerna/server_spec.rb +108 -0
  97. data/spec/pincerna/translation_spec.rb +55 -0
  98. data/spec/pincerna/unit_conversion_spec.rb +98 -0
  99. data/spec/pincerna/vpn_spec.rb +68 -0
  100. data/spec/pincerna/weather_spec.rb +131 -0
  101. data/spec/spec_helper.rb +48 -0
  102. metadata +283 -0
@@ -0,0 +1,46 @@
1
+ # encoding: utf-8
2
+ #
3
+ # This file is part of the pincerna gem. Copyright (C) 2013 and above Shogun <shogun@cowtech.it>.
4
+ # Licensed under the MIT license, which can be found at https://choosealicense.com/licenses/mit.
5
+ #
6
+
7
+ require "spec_helper"
8
+
9
+ describe Pincerna::CurrencyConversion do
10
+ subject { Pincerna::CurrencyConversion.new("QUERY", "yml") }
11
+
12
+ describe "matching" do
13
+ it "should match valid queries" do
14
+ allow_any_instance_of(Pincerna::CurrencyConversion).to receive(:perform_filtering) { |*args| args }
15
+ allow_any_instance_of(Pincerna::CurrencyConversion).to receive(:process_results) { |*args| args }
16
+
17
+ expect(Pincerna::CurrencyConversion.new("123 EUR to GBP", "yml").filter).to eq_as_yaml([[123.0, "EUR", "GBP", false]])
18
+ expect(Pincerna::CurrencyConversion.new("-123.45 eur usd", "yml").filter).to eq_as_yaml([[-123.45, "EUR", "USD", false]])
19
+ expect(Pincerna::CurrencyConversion.new("123 EUR to GBP with rate", "yml").filter).to eq_as_yaml([[123.0, "EUR", "GBP", true]])
20
+ end
21
+
22
+ it "should not match invalid queries" do
23
+ expect_any_instance_of(Pincerna::CurrencyConversion).not_to receive(:perform_filtering)
24
+ expect_any_instance_of(Pincerna::CurrencyConversion).not_to receive(:process_results)
25
+
26
+ expect(Pincerna::CurrencyConversion.new("12A3 EUR to GBP", "yml").filter).to eq_as_yaml([])
27
+ end
28
+ end
29
+
30
+ describe "#perform_filtering", :vcr, :synchronous do
31
+ it "should return valid values" do
32
+ expect(subject.perform_filtering(123.45, "EUR", "USD", "RATE")).to eq({value: 123.45, from: "EUR", to: "USD", result: 163.756, rate: 1.327, with_rate: "RATE"})
33
+ end
34
+ end
35
+
36
+ describe "#process_results" do
37
+ before(:each) do
38
+ @value = {value: 123.45, from: "EUR", to: "USD", result: 163.892, rate: 1.328, with_rate: nil}
39
+ end
40
+
41
+ it "should correctly prepare results" do
42
+ expect(subject.process_results(@value)).to eq([{title: "123.45 EUR = 163.892 USD", arg: "123.45", subtitle: "Action this item to copy the converted amount on the clipboard.", icon: Pincerna::CurrencyConversion::ICON}])
43
+ expect(subject.process_results(@value.merge(with_rate: true))).to eq([{title: "123.45 EUR = 163.892 USD (1 EUR = 1.328 USD)", arg: "123.45", subtitle: "Action this item to copy the converted amount on the clipboard.", icon: Pincerna::CurrencyConversion::ICON}])
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,46 @@
1
+ # encoding: utf-8
2
+ #
3
+ # This file is part of the pincerna gem. Copyright (C) 2013 and above Shogun <shogun@cowtech.it>.
4
+ # Licensed under the MIT license, which can be found at https://choosealicense.com/licenses/mit.
5
+ #
6
+
7
+ require "spec_helper"
8
+
9
+ describe Pincerna::FirefoxBookmark do
10
+ subject { Pincerna::FirefoxBookmark.new("QUERY", "yml") }
11
+
12
+ describe "#firefox_bookmarks" do
13
+ before(:each) do
14
+ @sqlite = <<EOSQLITE
15
+ #{Pincerna::FirefoxBookmark::QUERIES.first}
16
+ NAME 1|URL 1|4
17
+ NAME 2|URL 2|4
18
+ NAME|3|URL 3|3
19
+ NAME 4|URL 4|2
20
+ #{Pincerna::FirefoxBookmark::QUERIES.last}
21
+ BookmarksBar|1|0
22
+ BookmarksMenu|2|0
23
+ FOLDER 1|3|1
24
+ FOLDER|2|4|3
25
+ EOSQLITE
26
+ end
27
+
28
+ it "should call sqlite4 to get latest bookmarks" do
29
+ expect(Dir).to receive(:glob).with(File.expand_path("~/Library/Application Support/Firefox/Profiles") + "/*.default").and_return(["FIRST", "SECOND"])
30
+ expect(subject).to receive(:execute_command).with("/usr/bin/sqlite3", "-echo", "FIRST/places.sqlite", Pincerna::FirefoxBookmark::QUERIES.join("; "))
31
+ subject.read_bookmarks
32
+ end
33
+
34
+ it "should return the correct list of bookmarks" do
35
+ expect(subject.instance_variable_set(:@bookmarks, []))
36
+ allow(subject).to receive(:execute_command).and_return(@sqlite)
37
+ subject.read_bookmarks
38
+ expect(subject.instance_variable_get(:@bookmarks)).to eq([
39
+ {name: "NAME 1", url: "URL 1", path: " \u2192 BookmarksBar \u2192 FOLDER 1 \u2192 FOLDER|2"},
40
+ {name: "NAME 2", url: "URL 2", path: " \u2192 BookmarksBar \u2192 FOLDER 1 \u2192 FOLDER|2"},
41
+ {name: "NAME|3", url: "URL 3", path: " \u2192 BookmarksBar \u2192 FOLDER 1"},
42
+ {name: "NAME 4", url: "URL 4", path: " \u2192 BookmarksMenu"}
43
+ ])
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,194 @@
1
+ # encoding: utf-8
2
+ #
3
+ # This file is part of the pincerna gem. Copyright (C) 2013 and above Shogun <shogun@cowtech.it>.
4
+ # Licensed under the MIT license, which can be found at https://choosealicense.com/licenses/mit.
5
+ #
6
+
7
+ require "spec_helper"
8
+
9
+ describe Pincerna::Ip do
10
+ subject { Pincerna::Ip.new("", "yml") }
11
+
12
+ before(:each) do
13
+ @ifconfig = <<EOIP
14
+ lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384
15
+ options=3<RXCSUM,TXCSUM>
16
+ inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1
17
+ inet 127.0.0.1 netmask 0xff000000
18
+ inet6 ::1 prefixlen 128
19
+ gif0: flags=8010<POINTOPOINT,MULTICAST> mtu 1280
20
+ stf0: flags=0<> mtu 1280
21
+ en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
22
+ options=2b<RXCSUM,TXCSUM,VLAN_HWTAGGING,TSO4>
23
+ ether 11:22:33:44:55:66
24
+ media: autoselect (none)
25
+ status: inactive
26
+ en1: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
27
+ ether 11:22:33:44:55:66
28
+ inet6 fe80::6aa8:6dff:fe2e:5afc%en1 prefixlen 64 scopeid 0x5
29
+ inet 192.168.1.21 netmask 0xffffff00 broadcast 192.168.1.255
30
+ media: autoselect
31
+ status: active
32
+ fw0: flags=8822<BROADCAST,SMART,SIMPLEX,MULTICAST> mtu 4078
33
+ lladdr 11:22:33:44:55:66:77:88
34
+ media: autoselect <full-duplex>
35
+ status: inactive
36
+ p2p0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 2304
37
+ ether 11:22:33:44:55:66
38
+ media: autoselect
39
+ status: inactive
40
+ utun0: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1380
41
+ inet6 fe80::b5bc:eb1b:ee64:cd82%utun0 prefixlen 64 scopeid 0x8
42
+ inet6 fd3e:ebdd:9d87:a608:b5bc:eb1b:ee64:cd82 prefixlen 64
43
+ EOIP
44
+
45
+ @networksetup = <<EONAMES
46
+
47
+ Hardware Port: Bluetooth DUN
48
+ Device: Bluetooth-Modem
49
+ Ethernet Address: N/A
50
+
51
+ Hardware Port: Ethernet
52
+ Device: en0
53
+ Ethernet Address: 11:22:33:44:55:66
54
+
55
+ Hardware Port: FireWire
56
+ Device: fw0
57
+ Ethernet Address: 11:22:33:44:55:66:77:88
58
+
59
+ Hardware Port: Wi-Fi
60
+ Device: en1
61
+ Ethernet Address: 11:22:33:44:55:66
62
+
63
+ Hardware Port: Bluetooth PAN
64
+ Device: en2
65
+ Ethernet Address: N/A
66
+
67
+ VLAN Configurations
68
+ ===================
69
+ EONAMES
70
+
71
+ allow_any_instance_of(Pincerna::Ip).to receive(:execute_command) { |*args| args[0] == "/sbin/ifconfig" ? @ifconfig : @networksetup }
72
+ end
73
+
74
+ describe "matching" do
75
+ it "should allow both empty and present queries" do
76
+ allow_any_instance_of(Pincerna::Ip).to receive(:perform_filtering) { |args| [args] }
77
+ allow_any_instance_of(Pincerna::Ip).to receive(:process_results) { |args| args }
78
+
79
+ expect(Pincerna::Ip.new("QUERY", "yml").filter).to eq_as_yaml(["QUERY"])
80
+ expect(Pincerna::Ip.new("", "yml").filter).to eq_as_yaml([""])
81
+ end
82
+ end
83
+
84
+ describe "#perform_filtering" do
85
+ before(:each) do
86
+ allow(subject).to receive(:get_public_address).and_return({interface: nil, address: "8.8.8.8"})
87
+ end
88
+
89
+ describe "should return list of IPs" do
90
+ it "with no query" do
91
+ expect(subject.perform_filtering("")).to eq([
92
+ {interface: nil, address: "8.8.8.8"},
93
+ {interface: "Loopback (lo0)", address: "127.0.0.1"},
94
+ {interface: "Loopback (lo0)", address: "::1"},
95
+ {interface: "Loopback (lo0)", address: "fe80::1%lo0"},
96
+ {interface: "Wi-Fi (en1)", address: "192.168.1.21"},
97
+ {interface: "Wi-Fi (en1)", address: "fe80::6aa8:6dff:fe2e:5afc%en1"},
98
+ {interface: "utun0", address: "fd3e:ebdd:9d87:a608:b5bc:eb1b:ee64:cd82"},
99
+ {interface: "utun0", address: "fe80::b5bc:eb1b:ee64:cd82%utun0"}
100
+ ])
101
+ end
102
+
103
+ it "with query" do
104
+ expect(subject.perform_filtering("p")).to eq([
105
+ {interface: nil, address: "8.8.8.8"},
106
+ {interface: "Loopback (lo0)", address: "127.0.0.1"},
107
+ {interface: "Loopback (lo0)", address: "::1"},
108
+ {interface: "Loopback (lo0)", address: "fe80::1%lo0"}
109
+ ])
110
+
111
+ subject.instance_variable_set(:@interface_filter, nil)
112
+ expect(subject.perform_filtering("wi")).to eq([
113
+ {interface: "Wi-Fi (en1)", address: "192.168.1.21"},
114
+ {interface: "Wi-Fi (en1)", address: "fe80::6aa8:6dff:fe2e:5afc%en1"}
115
+ ])
116
+ end
117
+ end
118
+ end
119
+
120
+ describe "#process_results" do
121
+ before(:each) do
122
+ @value = [{interface: "INTERFACE", address: "IP 1"}, {interface: nil, address: "IP 2"}]
123
+ end
124
+
125
+ it "should correctly prepare results" do
126
+ expect(subject.process_results(@value)).to eq([
127
+ {title: "INTERFACE IP: IP 1", arg: "IP 1", subtitle: "Action this item to copy the IP on the clipboard.", icon: Pincerna::Ip::ICON},
128
+ {title: "Public IP: IP 2", arg: "IP 2", subtitle: "Action this item to copy the IP on the clipboard.", icon: Pincerna::Ip::ICON}
129
+ ])
130
+ end
131
+ end
132
+
133
+ describe "#get_local_addresses", :vcr do
134
+ before(:each) do
135
+ subject.instance_variable_set(:@interface_filter, /.*/i)
136
+ expect(subject).to receive(:get_interfaces_names).and_return({"en0" => "Ethernet", "fw0" => "FireWire", "en1" => "Wi-Fi", "en2" => "Bluetooth PAN", "lo0" => "Loopback"})
137
+ expect(subject).to receive(:execute_command).with("/sbin/ifconfig").and_return(@ifconfig)
138
+ end
139
+
140
+ it "should return a list of addresses" do
141
+ expect(subject.get_local_addresses).to eq([
142
+ {interface: "Loopback (lo0)", address: "fe80::1%lo0"},
143
+ {interface: "Loopback (lo0)", address: "127.0.0.1"},
144
+ {interface: "Loopback (lo0)", address: "::1"},
145
+ {interface: "Wi-Fi (en1)", address: "fe80::6aa8:6dff:fe2e:5afc%en1"},
146
+ {interface: "Wi-Fi (en1)", address: "192.168.1.21"},
147
+ {interface: "utun0", address: "fe80::b5bc:eb1b:ee64:cd82%utun0"},
148
+ {interface: "utun0", address: "fd3e:ebdd:9d87:a608:b5bc:eb1b:ee64:cd82"}
149
+ ])
150
+ end
151
+ end
152
+
153
+ describe "#get_public_address", :vcr, :synchronous do
154
+ it "should return public IP address" do
155
+ address = subject.get_public_address
156
+
157
+ expect(address.keys).to eq([:interface, :address])
158
+ expect(address[:interface]).to be_nil
159
+ expect(address[:address]).to eq("8.8.8.8")
160
+ end
161
+ end
162
+
163
+ describe "#compare_ip_classes" do
164
+ it "should compare IP classes" do
165
+ expect(subject.compare_ip_classes("127.0.0.1", "::1")).to eq(-1)
166
+ expect(subject.compare_ip_classes("::1", "::fe80:aabb")).to eq(0)
167
+ expect(subject.compare_ip_classes("::1", "127.0.0.1")).to eq(1)
168
+ end
169
+ end
170
+
171
+ describe "#compare_ip_addresses" do
172
+ it "should correctly compare IP addresses" do
173
+ expect(subject.compare_ip_addresses("127.0.0.1", "::1")).to eq(-1)
174
+ expect(subject.compare_ip_addresses("::1", "127.0.0.1")).to eq(1)
175
+ expect(subject.compare_ip_addresses("127.0.0.1", "192.168.0.1")).to eq(-1)
176
+ expect(subject.compare_ip_addresses("192.168.0.0", "192.168.0.1")).to eq(-1)
177
+ expect(subject.compare_ip_addresses("192.168.0.1", "192.168.0.1")).to eq(0)
178
+ expect(subject.compare_ip_addresses("127.0.0.1", "10.0.0.1")).to eq(1)
179
+ expect(subject.compare_ip_addresses("::1", "::fe80:aabb")).to eq(-1)
180
+ expect(subject.compare_ip_addresses("::fe80:aabe", "::fe80:aabd")).to eq(1)
181
+ expect(subject.compare_ip_addresses("::fe80:aaaa", "::fe80:aaaa")).to eq(0)
182
+ end
183
+ end
184
+
185
+ describe "#get_interfaces_names" do
186
+ before(:each) do
187
+ expect(subject).to receive(:execute_command).with("/usr/sbin/networksetup", "-listallhardwareports").and_return(@networksetup)
188
+ end
189
+
190
+ it "should return the current names of system interfaces" do
191
+ expect(subject.get_interfaces_names).to eq({"en0" => "Ethernet", "fw0" => "FireWire", "en1" => "Wi-Fi", "en2" => "Bluetooth PAN", "lo0" => "Loopback"})
192
+ end
193
+ end
194
+ end
@@ -0,0 +1,24 @@
1
+ # encoding: utf-8
2
+ #
3
+ # This file is part of the pincerna gem. Copyright (C) 2013 and above Shogun <shogun@cowtech.it>.
4
+ # Licensed under the MIT license, which can be found at https://choosealicense.com/licenses/mit.
5
+ #
6
+
7
+ require "spec_helper"
8
+
9
+ describe Pincerna::Map do
10
+ subject { Pincerna::Map.new("QUERY", "yml") }
11
+
12
+ describe "#perform_filtering" do
13
+ it "should simply return the query" do
14
+ expect(subject.perform_filtering("QUERY")).to eq({query: "QUERY"})
15
+ end
16
+ end
17
+
18
+ describe "#process_results" do
19
+ it "should correctly prepare results" do
20
+ expect(subject.process_results({query: "San Mateo, CA"})).to eq([{title: "View location on Google Maps", arg: "San+Mateo%2C+CA", subtitle: "Action this item to open Google Maps in the browser.", icon: Pincerna::Map::ICON}])
21
+ expect(subject.process_results({query: "-123.45,67.89"})).to eq([{title: "View coordinates on Google Maps", arg: "-123.45%2C67.89", subtitle: "Action this item to open Google Maps in the browser.", icon: Pincerna::Map::ICON}])
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,237 @@
1
+ # encoding: utf-8
2
+ #
3
+ # This file is part of the pincerna gem. Copyright (C) 2013 and above Shogun <shogun@cowtech.it>.
4
+ # Licensed under the MIT license, which can be found at https://choosealicense.com/licenses/mit.
5
+ #
6
+
7
+ require "spec_helper"
8
+
9
+ describe Pincerna::SafariBookmark do
10
+ subject { Pincerna::SafariBookmark.new("QUERY", "yml") }
11
+
12
+ describe "#read_bookmarks" do
13
+ before(:each) do
14
+ @plutil = <<EOPLUTIL
15
+ <?xml version="1.0" encoding="UTF-8"?>
16
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
17
+ <plist version="1.0">
18
+ <dict>
19
+ <key>Children</key>
20
+ <array>
21
+ <dict>
22
+ <key>Title</key>
23
+ <string>History</string>
24
+ <key>WebBookmarkIdentifier</key>
25
+ <string>History</string>
26
+ <key>WebBookmarkType</key>
27
+ <string>WebBookmarkTypeProxy</string>
28
+ <key>WebBookmarkUUID</key>
29
+ <string>CCC</string>
30
+ </dict>
31
+ <dict>
32
+ <key>Children</key>
33
+ <array>
34
+ <dict>
35
+ <key>Children</key>
36
+ <array>
37
+ <dict>
38
+ <key>Children</key>
39
+ <array>
40
+ <dict>
41
+ <key>Sync</key>
42
+ <dict>
43
+ <key>Key</key>
44
+ <string>"C=AAA"</string>
45
+ <key>ServerID</key>
46
+ <string>AAA</string>
47
+ </dict>
48
+ <key>URIDictionary</key>
49
+ <dict>
50
+ <key>title</key>
51
+ <string>NAME 1</string>
52
+ </dict>
53
+ <key>URLString</key>
54
+ <string>URL 1</string>
55
+ <key>WebBookmarkType</key>
56
+ <string>WebBookmarkTypeLeaf</string>
57
+ <key>WebBookmarkUUID</key>
58
+ <string>AAA</string>
59
+ </dict>
60
+
61
+ <dict>
62
+ <key>Sync</key>
63
+ <dict>
64
+ <key>Key</key>
65
+ <string>"C=AAA"</string>
66
+ <key>ServerID</key>
67
+ <string>AAA</string>
68
+ </dict>
69
+ <key>URIDictionary</key>
70
+ <dict>
71
+ <key>title</key>
72
+ <string>NAME 2</string>
73
+ </dict>
74
+ <key>URLString</key>
75
+ <string>URL 2</string>
76
+ <key>WebBookmarkType</key>
77
+ <string>WebBookmarkTypeLeaf</string>
78
+ <key>WebBookmarkUUID</key>
79
+ <string>AAA</string>
80
+ </dict>
81
+
82
+ </array>
83
+ <key>Sync</key>
84
+ <dict>
85
+ <key>Data</key>
86
+ <data>CCC</data>
87
+ <key>Key</key>
88
+ <string>AAA</string>
89
+ <key>ServerID</key>
90
+ <string>BBB</string>
91
+ </dict>
92
+ <key>Title</key>
93
+ <string>FOLDER 2</string>
94
+ <key>WebBookmarkType</key>
95
+ <string>WebBookmarkTypeList</string>
96
+ <key>WebBookmarkUUID</key>
97
+ <string>CCC</string>
98
+ </dict>
99
+
100
+ <dict>
101
+ <key>Sync</key>
102
+ <dict>
103
+ <key>Key</key>
104
+ <string>"C=AAA"</string>
105
+ <key>ServerID</key>
106
+ <string>AAA</string>
107
+ </dict>
108
+ <key>URIDictionary</key>
109
+ <dict>
110
+ <key>title</key>
111
+ <string>NAME 3</string>
112
+ </dict>
113
+ <key>URLString</key>
114
+ <string>URL 3</string>
115
+ <key>WebBookmarkType</key>
116
+ <string>WebBookmarkTypeLeaf</string>
117
+ <key>WebBookmarkUUID</key>
118
+ <string>AAA</string>
119
+ </dict>
120
+ </array>
121
+ <key>Sync</key>
122
+ <dict>
123
+ <key>Data</key>
124
+ <data>DDD</data>
125
+ <key>Key</key>
126
+ <string>CCC</string>
127
+ <key>ServerID</key>
128
+ <string>DDD</string>
129
+ </dict>
130
+ <key>Title</key>
131
+ <string>FOLDER 1</string>
132
+ <key>WebBookmarkType</key>
133
+ <string>WebBookmarkTypeList</string>
134
+ <key>WebBookmarkUUID</key>
135
+ <string>AAA</string>
136
+ </dict>
137
+ </array>
138
+ <key>Sync</key>
139
+ <dict>
140
+ <key>ServerID</key>
141
+ <string>CCC</string>
142
+ </dict>
143
+ <key>Title</key>
144
+ <string>BookmarksBar</string>
145
+ <key>WebBookmarkType</key>
146
+ <string>WebBookmarkTypeList</string>
147
+ <key>WebBookmarkUUID</key>
148
+ <string>DDD</string>
149
+ </dict>
150
+ <dict>
151
+ <key>Sync</key>
152
+ <dict>
153
+ <key>ServerID</key>
154
+ <string>CCC</string>
155
+ </dict>
156
+ <key>Title</key>
157
+ <string>BookmarksMenu</string>
158
+ <key>WebBookmarkType</key>
159
+ <string>WebBookmarkTypeList</string>
160
+ <key>WebBookmarkUUID</key>
161
+ <string>DDD</string>
162
+ <key>Children</key>
163
+ <array>
164
+ <dict>
165
+ <key>Sync</key>
166
+ <dict>
167
+ <key>Key</key>
168
+ <string>"C=AAA"</string>
169
+ <key>ServerID</key>
170
+ <string>AAA</string>
171
+ </dict>
172
+ <key>URIDictionary</key>
173
+ <dict>
174
+ <key>title</key>
175
+ <string>NAME 4</string>
176
+ </dict>
177
+ <key>URLString</key>
178
+ <string>URL 4</string>
179
+ <key>WebBookmarkType</key>
180
+ <string>WebBookmarkTypeLeaf</string>
181
+ <key>WebBookmarkUUID</key>
182
+ <string>AAA</string>
183
+ </dict>
184
+ </array>
185
+ </dict>
186
+ <dict>
187
+ <key>ShouldOmitFromUI</key>
188
+ <true/>
189
+ <key>Sync</key>
190
+ <dict>
191
+ <key>ServerID</key>
192
+ <string>CCC</string>
193
+ </dict>
194
+ <key>Title</key>
195
+ <string>com.apple.ReadingList</string>
196
+ <key>WebBookmarkType</key>
197
+ <string>WebBookmarkTypeList</string>
198
+ <key>WebBookmarkUUID</key>
199
+ <string>DDD</string>
200
+ </dict>
201
+ </array>
202
+ <key>Sync</key>
203
+ <dict>
204
+ <key>ServerData</key>
205
+ <data>BBB</data>
206
+ </dict>
207
+ <key>Title</key>
208
+ <string></string>
209
+ <key>WebBookmarkFileVersion</key>
210
+ <integer>1</integer>
211
+ <key>WebBookmarkType</key>
212
+ <string>WebBookmarkTypeList</string>
213
+ <key>WebBookmarkUUID</key>
214
+ <string>AAA</string>
215
+ </dict>
216
+ </plist>
217
+ EOPLUTIL
218
+ end
219
+
220
+ it "should call plutil to get latest bookmarks" do
221
+ expect(subject).to receive(:execute_command).with("/usr/bin/plutil", "-convert", "xml1", "-o", "-", File.expand_path("~/Library/Safari/Bookmarks.plist"))
222
+ subject.read_bookmarks
223
+ end
224
+
225
+ it "should return the correct list of bookmarks" do
226
+ expect(subject.instance_variable_set(:@bookmarks, []))
227
+ allow(subject).to receive(:execute_command).and_return(@plutil)
228
+ subject.read_bookmarks
229
+ expect(subject.instance_variable_get(:@bookmarks)).to eq([
230
+ {name: "NAME 1", url: "URL 1", path: " \u2192 BookmarksBar \u2192 FOLDER 1 \u2192 FOLDER 2"},
231
+ {name: "NAME 2", url: "URL 2", path: " \u2192 BookmarksBar \u2192 FOLDER 1 \u2192 FOLDER 2"},
232
+ {name: "NAME 3", url: "URL 3", path: " \u2192 BookmarksBar \u2192 FOLDER 1"},
233
+ {name: "NAME 4", url: "URL 4", path: " \u2192 BookmarksMenu"}
234
+ ])
235
+ end
236
+ end
237
+ end