ruby-pwsh 0.10.1 → 0.10.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,286 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Pwsh::Util do
6
+ context '.invalid_directories?' do
7
+ let(:valid_path_a) { 'C:/some/folder' }
8
+ let(:valid_path_b) { 'C:/another/folder' }
9
+ let(:valid_paths) { 'C:/some/folder;C:/another/folder' }
10
+ let(:invalid_path) { 'C:/invalid/path' }
11
+ let(:mixed_paths) { 'C:/some/folder;C:/invalid/path;C:/another/folder' }
12
+ let(:empty_string) { '' }
13
+ let(:empty_members) { 'C:/some/folder;;C:/another/folder' }
14
+
15
+ it 'returns false if passed nil' do
16
+ expect(described_class.invalid_directories?(nil)).to be false
17
+ end
18
+
19
+ it 'returns false if passed an empty string' do
20
+ expect(described_class.invalid_directories?('')).to be false
21
+ end
22
+
23
+ it 'returns false if one valid path is provided' do
24
+ expect(described_class).to receive(:on_windows?).and_return(true)
25
+ expect(File).to receive(:directory?).with(valid_path_a).and_return(true)
26
+ expect(described_class.invalid_directories?(valid_path_a)).to be false
27
+ end
28
+
29
+ it 'returns false if a collection of valid paths is provided' do
30
+ expect(described_class).to receive(:on_windows?).and_return(true)
31
+ expect(File).to receive(:directory?).with(valid_path_a).and_return(true)
32
+ expect(File).to receive(:directory?).with(valid_path_b).and_return(true)
33
+ expect(described_class.invalid_directories?(valid_paths)).to be false
34
+ end
35
+
36
+ it 'returns true if there is only one path and it is invalid' do
37
+ expect(described_class).to receive(:on_windows?).and_return(true)
38
+ expect(File).to receive(:directory?).with(invalid_path).and_return(false)
39
+ expect(described_class.invalid_directories?(invalid_path)).to be true
40
+ end
41
+
42
+ it 'returns true if the collection has on valid and one invalid member' do
43
+ expect(described_class).to receive(:on_windows?).and_return(true)
44
+ expect(File).to receive(:directory?).with(valid_path_a).and_return(true)
45
+ expect(File).to receive(:directory?).with(valid_path_b).and_return(true)
46
+ expect(File).to receive(:directory?).with(invalid_path).and_return(false)
47
+ expect(described_class.invalid_directories?(mixed_paths)).to be true
48
+ end
49
+
50
+ it 'returns false if collection has empty members but other entries are valid' do
51
+ expect(described_class).to receive(:on_windows?).and_return(true)
52
+ expect(File).to receive(:directory?).with(valid_path_a).and_return(true)
53
+ expect(File).to receive(:directory?).with(valid_path_b).and_return(true)
54
+ allow(File).to receive(:directory?).with('')
55
+ expect(described_class.invalid_directories?(empty_members)).to be false
56
+ end
57
+ end
58
+
59
+ let(:camel_case_hash) do
60
+ {
61
+ a: 1,
62
+ appleButter: %w[a b c],
63
+ someKeyValue: {
64
+ nestedKey: 1,
65
+ anotherNestedKey: 2
66
+ }
67
+ }
68
+ end
69
+ let(:kebab_case_hash) do
70
+ {
71
+ a: 1,
72
+ 'apple-butter': %w[a b c],
73
+ 'some-key-value': {
74
+ 'nested-key': 1,
75
+ 'another-nested-key': 2
76
+ }
77
+ }
78
+ end
79
+ let(:pascal_case_hash) do
80
+ {
81
+ A: 1,
82
+ AppleButter: %w[a b c],
83
+ SomeKeyValue: {
84
+ NestedKey: 1,
85
+ AnotherNestedKey: 2
86
+ }
87
+ }
88
+ end
89
+ let(:pascal_case_hash_in_an_array) do
90
+ [
91
+ 'just a string',
92
+ {
93
+ SomeKey: 'a value'
94
+ },
95
+ 1,
96
+ {
97
+ AnotherKey: {
98
+ NestedKey: 1,
99
+ NestedArray: [
100
+ 1,
101
+ 'another string',
102
+ { SuperNestedKey: 'value' }
103
+ ]
104
+ }
105
+ }
106
+ ]
107
+ end
108
+ let(:snake_case_hash) do
109
+ {
110
+ a: 1,
111
+ apple_butter: %w[a b c],
112
+ some_key_value: {
113
+ nested_key: 1,
114
+ another_nested_key: 2
115
+ }
116
+ }
117
+ end
118
+ let(:snake_case_hash_in_an_array) do
119
+ [
120
+ 'just a string',
121
+ {
122
+ some_key: 'a value'
123
+ },
124
+ 1,
125
+ {
126
+ another_key: {
127
+ nested_key: 1,
128
+ nested_array: [
129
+ 1,
130
+ 'another string',
131
+ { super_nested_key: 'value' }
132
+ ]
133
+ }
134
+ }
135
+ ]
136
+ end
137
+ let(:camel_case_string) { 'thisIsAString' }
138
+ let(:kebab_case_string) { 'this-is-a-string' }
139
+ let(:pascal_case_string) { 'ThisIsAString' }
140
+ let(:snake_case_string) { 'this_is_a_string' }
141
+
142
+ context '.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
+ context '.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
+ context '.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
+ context '.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
+ context '.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
+ context '.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
+ context '.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
+ it 'returns a symbol as a non-interpolated string' do
257
+ expect(described_class.format_powershell_value(:apple)).to eq('apple')
258
+ end
259
+ it 'returns a number as a non interpolated string' do
260
+ expect(described_class.format_powershell_value(101)).to eq('101')
261
+ expect(described_class.format_powershell_value(1.1)).to eq('1.1')
262
+ end
263
+ it 'returns boolean values as the appropriate PowerShell automatic variable' do
264
+ expect(described_class.format_powershell_value(true)).to eq('$true')
265
+ expect(described_class.format_powershell_value(:false)).to eq('$false') # rubocop:disable Lint/BooleanSymbol
266
+ end
267
+ it 'returns a string as an escaped string' do
268
+ expect(described_class.format_powershell_value('some string')).to eq("'some string'")
269
+ end
270
+ it 'returns an array as a string representing a PowerShell array' do
271
+ expect(described_class.format_powershell_value(ruby_array)).to eq(powershell_array)
272
+ end
273
+ it 'returns a hash as a string representing a PowerShell hash' do
274
+ expect(described_class.format_powershell_value(ruby_hash)).to eq(powershell_hash)
275
+ end
276
+ it 'raises an error if an unknown type is passed' do
277
+ expect { described_class.format_powershell_value(described_class) }.to raise_error(/unsupported type Module/)
278
+ end
279
+ end
280
+
281
+ context '.custom_powershell_property' do
282
+ it 'returns a powershell hash with the name and expression keys' do
283
+ expect(described_class.custom_powershell_property('apple', '$_.SomeValue / 5')).to eq("@{Name = 'apple'; Expression = {$_.SomeValue / 5}}")
284
+ end
285
+ end
286
+ 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_kind_of(String)
9
+ end
10
+ end
@@ -0,0 +1,116 @@
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 eq(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 eq(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 eq(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 eq(false)
82
+ end
83
+ end
84
+ context 'when the Windows PowerShell major version is less than two' do
85
+ it 'returns false' do
86
+ expect(described_class).to receive(:version).and_return('1.0')
87
+ expect(described_class.compatible_version?).to eq(false)
88
+ end
89
+ end
90
+ context 'when the Windows PowerShell major version is two' do
91
+ it 'returns true if .NET 3.5 is installed' do
92
+ expect(described_class).to receive(:version).and_return('2.0')
93
+ 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
94
+ expect(described_class.compatible_version?).to eq(true)
95
+ end
96
+ it 'returns false if .NET 3.5 is not installed' do
97
+ expect(described_class).to receive(:version).and_return('2.0')
98
+ 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)
99
+ expect(described_class.compatible_version?).to eq(false)
100
+ end
101
+ end
102
+ context 'when the Windows PowerShell major version is three' do
103
+ it 'returns true' do
104
+ expect(described_class).to receive(:version).and_return('3.0')
105
+ expect(described_class.compatible_version?).to eq(true)
106
+ end
107
+ end
108
+ context 'when the Windows PowerShell major version is greater than three' do
109
+ it 'returns true' do
110
+ expect(described_class).to receive(:version).and_return('4.0')
111
+ expect(described_class.compatible_version?).to eq(true)
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end