ruby-pwsh 0.10.2 → 0.11.0.rc.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,293 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Pwsh::Util do
6
+ let(:snake_case_string) { 'this_is_a_string' }
7
+ let(:pascal_case_string) { 'ThisIsAString' }
8
+ let(:kebab_case_string) { 'this-is-a-string' }
9
+ let(:camel_case_string) { 'thisIsAString' }
10
+ let(:snake_case_hash_in_an_array) do
11
+ [
12
+ 'just a string',
13
+ {
14
+ some_key: 'a value'
15
+ },
16
+ 1,
17
+ {
18
+ another_key: {
19
+ nested_key: 1,
20
+ nested_array: [
21
+ 1,
22
+ 'another string',
23
+ { super_nested_key: 'value' }
24
+ ]
25
+ }
26
+ }
27
+ ]
28
+ end
29
+ let(:snake_case_hash) do
30
+ {
31
+ a: 1,
32
+ apple_butter: %w[a b c],
33
+ some_key_value: {
34
+ nested_key: 1,
35
+ another_nested_key: 2
36
+ }
37
+ }
38
+ end
39
+ let(:pascal_case_hash_in_an_array) do
40
+ [
41
+ 'just a string',
42
+ {
43
+ SomeKey: 'a value'
44
+ },
45
+ 1,
46
+ {
47
+ AnotherKey: {
48
+ NestedKey: 1,
49
+ NestedArray: [
50
+ 1,
51
+ 'another string',
52
+ { SuperNestedKey: 'value' }
53
+ ]
54
+ }
55
+ }
56
+ ]
57
+ end
58
+ let(:pascal_case_hash) do
59
+ {
60
+ A: 1,
61
+ AppleButter: %w[a b c],
62
+ SomeKeyValue: {
63
+ NestedKey: 1,
64
+ AnotherNestedKey: 2
65
+ }
66
+ }
67
+ end
68
+ let(:kebab_case_hash) do
69
+ {
70
+ a: 1,
71
+ 'apple-butter': %w[a b c],
72
+ 'some-key-value': {
73
+ 'nested-key': 1,
74
+ 'another-nested-key': 2
75
+ }
76
+ }
77
+ end
78
+ let(:camel_case_hash) do
79
+ {
80
+ a: 1,
81
+ appleButter: %w[a b c],
82
+ someKeyValue: {
83
+ nestedKey: 1,
84
+ anotherNestedKey: 2
85
+ }
86
+ }
87
+ end
88
+
89
+ describe '.invalid_directories?' do
90
+ let(:valid_path_a) { 'C:/some/folder' }
91
+ let(:valid_path_b) { 'C:/another/folder' }
92
+ let(:valid_paths) { 'C:/some/folder;C:/another/folder' }
93
+ let(:invalid_path) { 'C:/invalid/path' }
94
+ let(:mixed_paths) { 'C:/some/folder;C:/invalid/path;C:/another/folder' }
95
+ let(:empty_string) { '' }
96
+ let(:empty_members) { 'C:/some/folder;;C:/another/folder' }
97
+
98
+ it 'returns false if passed nil' do
99
+ expect(described_class.invalid_directories?(nil)).to be false
100
+ end
101
+
102
+ it 'returns false if passed an empty string' do
103
+ expect(described_class.invalid_directories?('')).to be false
104
+ end
105
+
106
+ it 'returns false if one valid path is provided' do
107
+ expect(described_class).to receive(:on_windows?).and_return(true)
108
+ expect(File).to receive(:directory?).with(valid_path_a).and_return(true)
109
+ expect(described_class.invalid_directories?(valid_path_a)).to be false
110
+ end
111
+
112
+ it 'returns false if a collection of valid paths is provided' do
113
+ expect(described_class).to receive(:on_windows?).and_return(true)
114
+ expect(File).to receive(:directory?).with(valid_path_a).and_return(true)
115
+ expect(File).to receive(:directory?).with(valid_path_b).and_return(true)
116
+ expect(described_class.invalid_directories?(valid_paths)).to be false
117
+ end
118
+
119
+ it 'returns true if there is only one path and it is invalid' do
120
+ expect(described_class).to receive(:on_windows?).and_return(true)
121
+ expect(File).to receive(:directory?).with(invalid_path).and_return(false)
122
+ expect(described_class.invalid_directories?(invalid_path)).to be true
123
+ end
124
+
125
+ it 'returns true if the collection has on valid and one invalid member' do
126
+ expect(described_class).to receive(:on_windows?).and_return(true)
127
+ expect(File).to receive(:directory?).with(valid_path_a).and_return(true)
128
+ expect(File).to receive(:directory?).with(valid_path_b).and_return(true)
129
+ expect(File).to receive(:directory?).with(invalid_path).and_return(false)
130
+ expect(described_class.invalid_directories?(mixed_paths)).to be true
131
+ end
132
+
133
+ it 'returns false if collection has empty members but other entries are valid' do
134
+ expect(described_class).to receive(:on_windows?).and_return(true)
135
+ expect(File).to receive(:directory?).with(valid_path_a).and_return(true)
136
+ expect(File).to receive(:directory?).with(valid_path_b).and_return(true)
137
+ allow(File).to receive(:directory?).with('')
138
+ expect(described_class.invalid_directories?(empty_members)).to be false
139
+ end
140
+ end
141
+
142
+ describe '.snake_case' do
143
+ it 'converts a string to snake_case' do
144
+ expect(described_class.snake_case(camel_case_string)).to eq snake_case_string
145
+ expect(described_class.snake_case(kebab_case_string)).to eq snake_case_string
146
+ expect(described_class.snake_case(pascal_case_string)).to eq snake_case_string
147
+ end
148
+ end
149
+
150
+ describe '.snake_case_hash_keys' do
151
+ it 'snake_cases the keys in a passed hash' do
152
+ expect(described_class.snake_case_hash_keys(camel_case_hash)).to eq snake_case_hash
153
+ expect(described_class.snake_case_hash_keys(kebab_case_hash)).to eq snake_case_hash
154
+ expect(described_class.snake_case_hash_keys(pascal_case_hash)).to eq snake_case_hash
155
+ expect(described_class.snake_case_hash_keys(pascal_case_hash_in_an_array)).to eq snake_case_hash_in_an_array
156
+ end
157
+ end
158
+
159
+ describe '.pascal_case' do
160
+ it 'converts a string to PascalCase' do
161
+ expect(described_class.pascal_case(camel_case_string)).to eq pascal_case_string
162
+ expect(described_class.pascal_case(kebab_case_string)).to eq pascal_case_string
163
+ expect(described_class.pascal_case(snake_case_string)).to eq pascal_case_string
164
+ end
165
+ end
166
+
167
+ describe '.pascal_case_hash_keys' do
168
+ it 'PascalCases the keys in a passed hash' do
169
+ expect(described_class.pascal_case_hash_keys(camel_case_hash)).to eq pascal_case_hash
170
+ expect(described_class.pascal_case_hash_keys(kebab_case_hash)).to eq pascal_case_hash
171
+ expect(described_class.pascal_case_hash_keys(snake_case_hash)).to eq pascal_case_hash
172
+ expect(described_class.pascal_case_hash_keys(snake_case_hash_in_an_array)).to eq pascal_case_hash_in_an_array
173
+ end
174
+ end
175
+
176
+ describe '.symbolize_hash_keys' do
177
+ let(:array_with_string_keys_in_hashes) do
178
+ [
179
+ 'just a string',
180
+ {
181
+ 'some_key' => 'a value'
182
+ },
183
+ 1,
184
+ {
185
+ 'another_key' => {
186
+ 'nested_key' => 1,
187
+ 'nested_array' => [
188
+ 1,
189
+ 'another string',
190
+ { 'super_nested_key' => 'value' }
191
+ ]
192
+ }
193
+ }
194
+ ]
195
+ end
196
+ let(:array_with_symbol_keys_in_hashes) do
197
+ [
198
+ 'just a string',
199
+ {
200
+ some_key: 'a value'
201
+ },
202
+ 1,
203
+ {
204
+ another_key: {
205
+ nested_key: 1,
206
+ nested_array: [
207
+ 1,
208
+ 'another string',
209
+ { super_nested_key: 'value' }
210
+ ]
211
+ }
212
+ }
213
+ ]
214
+ end
215
+
216
+ it 'converts all string hash keys into symbols' do
217
+ expect(described_class.symbolize_hash_keys(array_with_string_keys_in_hashes)).to eq array_with_symbol_keys_in_hashes
218
+ end
219
+ end
220
+
221
+ describe '.escape_quotes' do
222
+ it 'handles single quotes' do
223
+ expect(described_class.escape_quotes("The 'Cats' go 'meow'!")).to match(/The ''Cats'' go ''meow''!/)
224
+ end
225
+
226
+ it 'handles double single quotes' do
227
+ expect(described_class.escape_quotes("The ''Cats'' go 'meow'!")).to match(/The ''''Cats'''' go ''meow''!/)
228
+ end
229
+
230
+ it 'handles double quotes' do
231
+ expect(described_class.escape_quotes("The 'Cats' go \"meow\"!")).to match(/The ''Cats'' go "meow"!/)
232
+ end
233
+
234
+ it 'handles dollar signs' do
235
+ expect(described_class.escape_quotes('This should show $foo variable')).to match(/This should show \$foo variable/)
236
+ end
237
+ end
238
+
239
+ describe '.format_powershell_value' do
240
+ let(:ruby_array) { ['string', 1, :symbol, true] }
241
+ let(:powershell_array) { "@('string', 1, symbol, $true)" }
242
+ let(:ruby_hash) do
243
+ {
244
+ string: 'string',
245
+ number: 1,
246
+ symbol: :some_symbol,
247
+ boolean: true,
248
+ nested_hash: {
249
+ another_string: 'foo',
250
+ another_number: 2,
251
+ array: [1, 2, 3]
252
+ }
253
+ }
254
+ end
255
+ let(:powershell_hash) { "@{string = 'string'; number = 1; symbol = some_symbol; boolean = $true; nested_hash = @{another_string = 'foo'; another_number = 2; array = @(1, 2, 3)}}" }
256
+
257
+ it 'returns a symbol as a non-interpolated string' do
258
+ expect(described_class.format_powershell_value(:apple)).to eq('apple')
259
+ end
260
+
261
+ it 'returns a number as a non interpolated string' do
262
+ expect(described_class.format_powershell_value(101)).to eq('101')
263
+ expect(described_class.format_powershell_value(1.1)).to eq('1.1')
264
+ end
265
+
266
+ it 'returns boolean values as the appropriate PowerShell automatic variable' do
267
+ expect(described_class.format_powershell_value(true)).to eq('$true')
268
+ expect(described_class.format_powershell_value(:false)).to eq('$false') # rubocop:disable Lint/BooleanSymbol
269
+ end
270
+
271
+ it 'returns a string as an escaped string' do
272
+ expect(described_class.format_powershell_value('some string')).to eq("'some string'")
273
+ end
274
+
275
+ it 'returns an array as a string representing a PowerShell array' do
276
+ expect(described_class.format_powershell_value(ruby_array)).to eq(powershell_array)
277
+ end
278
+
279
+ it 'returns a hash as a string representing a PowerShell hash' do
280
+ expect(described_class.format_powershell_value(ruby_hash)).to eq(powershell_hash)
281
+ end
282
+
283
+ it 'raises an error if an unknown type is passed' do
284
+ expect { described_class.format_powershell_value(described_class) }.to raise_error(/unsupported type Module/)
285
+ end
286
+ end
287
+
288
+ describe '.custom_powershell_property' do
289
+ it 'returns a powershell hash with the name and expression keys' do
290
+ expect(described_class.custom_powershell_property('apple', '$_.SomeValue / 5')).to eq("@{Name = 'apple'; Expression = {$_.SomeValue / 5}}")
291
+ end
292
+ end
293
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Pwsh do
6
+ it 'has a version number' do
7
+ expect(described_class::VERSION).not_to be_nil
8
+ expect(described_class::VERSION).to be_a(String)
9
+ end
10
+ end
@@ -0,0 +1,121 @@
1
+ # frozen_string_literal: false
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Pwsh::WindowsPowerShell do
6
+ describe '.version' do
7
+ context 'on non-Windows platforms', unless: Pwsh::Util.on_windows? do
8
+ it 'is not defined' do
9
+ expect(defined?(described_class.version)).to be_nil
10
+ end
11
+ end
12
+
13
+ context 'On Windows', if: Pwsh::Util.on_windows? do
14
+ context 'when Windows PowerShell version is greater than three' do
15
+ it 'detects a Windows PowerShell version' do
16
+ allow_any_instance_of(Win32::Registry).to receive(:[]).with('PowerShellVersion').and_return('5.0.10514.6')
17
+ expect(described_class.version).to eq('5.0.10514.6')
18
+ end
19
+
20
+ it 'calls the Windows PowerShell three registry path' do
21
+ reg_key = instance_double(bob)
22
+ allow(reg_key).to receive(:[]).with('PowerShellVersion').and_return('5.0.10514.6')
23
+ allow_any_instance_of(Win32::Registry).to receive(:open).with('SOFTWARE\Microsoft\PowerShell\3\PowerShellEngine', Win32::Registry::KEY_READ | 0x100).and_yield(reg_key)
24
+
25
+ described_class.version
26
+ end
27
+
28
+ it 'does not call Windows PowerShell one registry path' do
29
+ reg_key = instance_double(bob)
30
+ allow(reg_key).to receive(:[]).with('PowerShellVersion').and_return('5.0.10514.6')
31
+ allow_any_instance_of(Win32::Registry).to receive(:open).with('SOFTWARE\Microsoft\PowerShell\3\PowerShellEngine', Win32::Registry::KEY_READ | 0x100).and_yield(reg_key)
32
+ expect_any_instance_of(Win32::Registry).not_to receive(:open).with('SOFTWARE\Microsoft\PowerShell\1\PowerShellEngine', Win32::Registry::KEY_READ | 0x100)
33
+
34
+ described_class.version
35
+ end
36
+ end
37
+
38
+ context 'when Windows PowerShell version is less than three' do
39
+ it 'detects a Windows PowerShell version' do
40
+ allow_any_instance_of(Win32::Registry).to receive(:[]).with('PowerShellVersion').and_return('2.0')
41
+
42
+ expect(described_class.version).to eq('2.0')
43
+ end
44
+
45
+ it 'calls the Windows PowerShell one registry path' do
46
+ reg_key = instance_double(bob)
47
+ allow(reg_key).to receive(:[]).with('PowerShellVersion').and_return('2.0')
48
+ allow_any_instance_of(Win32::Registry).to receive(:open).with('SOFTWARE\Microsoft\PowerShell\1\PowerShellEngine',
49
+ Win32::Registry::KEY_READ | 0x100).and_yield(reg_key)
50
+ allow_any_instance_of(Win32::Registry).to receive(:open).with('SOFTWARE\Microsoft\PowerShell\3\PowerShellEngine',
51
+ Win32::Registry::KEY_READ | 0x100).and_raise(Win32::Registry::Error.new(2), 'nope')
52
+
53
+ expect(described_class.version).to eq('2.0')
54
+ end
55
+ end
56
+
57
+ context 'when Windows PowerShell is not installed' do
58
+ it 'returns nil and not throw' do
59
+ allow_any_instance_of(Win32::Registry).to receive(:open).with('SOFTWARE\Microsoft\PowerShell\1\PowerShellEngine',
60
+ Win32::Registry::KEY_READ | 0x100).and_raise(Win32::Registry::Error.new(2), 'nope')
61
+ allow_any_instance_of(Win32::Registry).to receive(:open).with('SOFTWARE\Microsoft\PowerShell\3\PowerShellEngine',
62
+ Win32::Registry::KEY_READ | 0x100).and_raise(Win32::Registry::Error.new(2), 'nope')
63
+
64
+ expect(described_class.version).to be_nil
65
+ end
66
+ end
67
+ end
68
+ end
69
+
70
+ describe '.compatible_version?' do
71
+ context 'on non-Windows platforms', unless: Pwsh::Util.on_windows? do
72
+ it 'returns false' do
73
+ expect(described_class.compatible_version?).to be(false)
74
+ end
75
+ end
76
+
77
+ context 'On Windows', if: Pwsh::Util.on_windows? do
78
+ context 'when the Windows PowerShell major version is nil' do
79
+ it 'returns false' do
80
+ expect(described_class).to receive(:version).and_return(nil)
81
+ expect(described_class.compatible_version?).to be(false)
82
+ end
83
+ end
84
+
85
+ context 'when the Windows PowerShell major version is less than two' do
86
+ it 'returns false' do
87
+ expect(described_class).to receive(:version).and_return('1.0')
88
+ expect(described_class.compatible_version?).to be(false)
89
+ end
90
+ end
91
+
92
+ context 'when the Windows PowerShell major version is two' do
93
+ it 'returns true if .NET 3.5 is installed' do
94
+ expect(described_class).to receive(:version).and_return('2.0')
95
+ allow_any_instance_of(Win32::Registry).to receive(:open).with('SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.5', Win32::Registry::KEY_READ | 0x100).and_yield
96
+ expect(described_class.compatible_version?).to be(true)
97
+ end
98
+
99
+ it 'returns false if .NET 3.5 is not installed' do
100
+ expect(described_class).to receive(:version).and_return('2.0')
101
+ allow_any_instance_of(Win32::Registry).to receive(:open).with('SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.5', Win32::Registry::KEY_READ | 0x100).and_raise(Win32::Registry::Error, 1)
102
+ expect(described_class.compatible_version?).to be(false)
103
+ end
104
+ end
105
+
106
+ context 'when the Windows PowerShell major version is three' do
107
+ it 'returns true' do
108
+ expect(described_class).to receive(:version).and_return('3.0')
109
+ expect(described_class.compatible_version?).to be(true)
110
+ end
111
+ end
112
+
113
+ context 'when the Windows PowerShell major version is greater than three' do
114
+ it 'returns true' do
115
+ expect(described_class).to receive(:version).and_return('4.0')
116
+ expect(described_class.compatible_version?).to be(true)
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end