castle-rb 6.0.1 → 7.0.0

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.
Files changed (98) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +8 -8
  3. data/lib/castle.rb +7 -11
  4. data/lib/castle/api.rb +7 -12
  5. data/lib/castle/api/approve_device.rb +1 -6
  6. data/lib/castle/api/authenticate.rb +10 -7
  7. data/lib/castle/api/end_impersonation.rb +3 -8
  8. data/lib/castle/api/filter.rb +37 -0
  9. data/lib/castle/api/get_device.rb +1 -6
  10. data/lib/castle/api/get_devices_for_user.rb +1 -6
  11. data/lib/castle/api/log.rb +37 -0
  12. data/lib/castle/api/report_device.rb +1 -6
  13. data/lib/castle/api/risk.rb +37 -0
  14. data/lib/castle/api/start_impersonation.rb +3 -8
  15. data/lib/castle/api/track.rb +1 -6
  16. data/lib/castle/client.rb +36 -16
  17. data/lib/castle/commands/approve_device.rb +1 -5
  18. data/lib/castle/commands/end_impersonation.rb +1 -1
  19. data/lib/castle/commands/filter.rb +23 -0
  20. data/lib/castle/commands/get_device.rb +1 -5
  21. data/lib/castle/commands/get_devices_for_user.rb +1 -5
  22. data/lib/castle/commands/{identify.rb → log.rb} +4 -3
  23. data/lib/castle/commands/report_device.rb +1 -5
  24. data/lib/castle/commands/risk.rb +23 -0
  25. data/lib/castle/commands/start_impersonation.rb +1 -1
  26. data/lib/castle/configuration.rb +18 -8
  27. data/lib/castle/core/get_connection.rb +3 -1
  28. data/lib/castle/core/process_response.rb +5 -2
  29. data/lib/castle/core/process_webhook.rb +10 -5
  30. data/lib/castle/core/send_request.rb +8 -16
  31. data/lib/castle/errors.rb +37 -13
  32. data/lib/castle/failover/prepare_response.rb +2 -7
  33. data/lib/castle/failover/strategy.rb +3 -0
  34. data/lib/castle/headers/extract.rb +4 -4
  35. data/lib/castle/headers/filter.rb +9 -6
  36. data/lib/castle/ips/extract.rb +4 -2
  37. data/lib/castle/logger.rb +3 -3
  38. data/lib/castle/payload/prepare.rb +3 -4
  39. data/lib/castle/secure_mode.rb +3 -2
  40. data/lib/castle/support/hanami.rb +2 -6
  41. data/lib/castle/support/rails.rb +1 -3
  42. data/lib/castle/utils/clean_invalid_chars.rb +1 -3
  43. data/lib/castle/verdict.rb +2 -0
  44. data/lib/castle/version.rb +1 -1
  45. data/lib/castle/webhooks/verify.rb +9 -7
  46. data/spec/integration/rails/rails_spec.rb +9 -7
  47. data/spec/integration/rails/support/home_controller.rb +26 -24
  48. data/spec/lib/castle/api/approve_device_spec.rb +3 -3
  49. data/spec/lib/castle/api/authenticate_spec.rb +20 -24
  50. data/spec/lib/castle/api/end_impersonation_spec.rb +11 -5
  51. data/spec/lib/castle/api/filter_spec.rb +5 -0
  52. data/spec/lib/castle/api/get_device_spec.rb +3 -3
  53. data/spec/lib/castle/api/get_devices_for_user_spec.rb +3 -3
  54. data/spec/lib/castle/api/log_spec.rb +5 -0
  55. data/spec/lib/castle/api/report_device_spec.rb +3 -3
  56. data/spec/lib/castle/api/risk_spec.rb +5 -0
  57. data/spec/lib/castle/api/start_impersonation_spec.rb +11 -5
  58. data/spec/lib/castle/api/track_spec.rb +11 -7
  59. data/spec/lib/castle/api_spec.rb +4 -20
  60. data/spec/lib/castle/client_id/extract_spec.rb +4 -13
  61. data/spec/lib/castle/client_spec.rb +81 -84
  62. data/spec/lib/castle/commands/authenticate_spec.rb +8 -15
  63. data/spec/lib/castle/commands/end_impersonation_spec.rb +6 -9
  64. data/spec/lib/castle/commands/{identify_spec.rb → filter_spec.rb} +41 -19
  65. data/spec/lib/castle/commands/log_spec.rb +100 -0
  66. data/spec/lib/castle/commands/risk_spec.rb +100 -0
  67. data/spec/lib/castle/commands/start_impersonation_spec.rb +6 -9
  68. data/spec/lib/castle/commands/track_spec.rb +9 -18
  69. data/spec/lib/castle/configuration_spec.rb +2 -6
  70. data/spec/lib/castle/context/get_default_spec.rb +8 -8
  71. data/spec/lib/castle/context/prepare_spec.rb +6 -7
  72. data/spec/lib/castle/core/get_connection_spec.rb +6 -22
  73. data/spec/lib/castle/core/process_response_spec.rb +1 -8
  74. data/spec/lib/castle/core/send_request_spec.rb +4 -29
  75. data/spec/lib/castle/headers/extract_spec.rb +1 -3
  76. data/spec/lib/castle/headers/filter_spec.rb +12 -11
  77. data/spec/lib/castle/ips/extract_spec.rb +4 -13
  78. data/spec/lib/castle/logger_spec.rb +2 -6
  79. data/spec/lib/castle/payload/prepare_spec.rb +5 -4
  80. data/spec/lib/castle/session_spec.rb +13 -36
  81. data/spec/lib/castle/singleton_configuration_spec.rb +2 -6
  82. data/spec/lib/castle/utils/clean_invalid_chars_spec.rb +2 -2
  83. data/spec/lib/castle/utils/merge_spec.rb +3 -1
  84. data/spec/lib/castle/validators/present_spec.rb +5 -6
  85. data/spec/lib/castle/webhooks/verify_spec.rb +8 -24
  86. data/spec/lib/castle_spec.rb +4 -10
  87. data/spec/spec_helper.rb +1 -3
  88. data/spec/support/shared_examples/action_request.rb +152 -0
  89. data/spec/support/shared_examples/configuration.rb +14 -42
  90. metadata +23 -18
  91. data/lib/castle/api/identify.rb +0 -26
  92. data/lib/castle/api/review.rb +0 -24
  93. data/lib/castle/commands/review.rb +0 -17
  94. data/lib/castle/events.rb +0 -49
  95. data/spec/lib/castle/api/identify_spec.rb +0 -68
  96. data/spec/lib/castle/api/review_spec.rb +0 -19
  97. data/spec/lib/castle/commands/review_spec.rb +0 -24
  98. data/spec/lib/castle/events_spec.rb +0 -5
@@ -30,9 +30,7 @@ describe Castle::Commands::EndImpersonation do
30
30
 
31
31
  context 'when active true' do
32
32
  let(:payload) { default_payload.merge(context: context.merge(active: true)) }
33
- let(:command_data) do
34
- default_payload.merge(context: context.merge(active: true))
35
- end
33
+ let(:command_data) { default_payload.merge(context: context.merge(active: true)) }
36
34
 
37
35
  it { expect(command.method).to be_eql(:delete) }
38
36
  it { expect(command.path).to be_eql('impersonate') }
@@ -41,9 +39,7 @@ describe Castle::Commands::EndImpersonation do
41
39
 
42
40
  context 'when active false' do
43
41
  let(:payload) { default_payload.merge(context: context.merge(active: false)) }
44
- let(:command_data) do
45
- default_payload.merge(context: context.merge(active: false))
46
- end
42
+ let(:command_data) { default_payload.merge(context: context.merge(active: false)) }
47
43
 
48
44
  it { expect(command.method).to be_eql(:delete) }
49
45
  it { expect(command.path).to be_eql('impersonate') }
@@ -67,9 +63,10 @@ describe Castle::Commands::EndImpersonation do
67
63
  let(:payload) { {} }
68
64
 
69
65
  it do
70
- expect do
71
- validate!
72
- end.to raise_error(Castle::InvalidParametersError, 'user_id is missing or empty')
66
+ expect { validate! }.to raise_error(
67
+ Castle::InvalidParametersError,
68
+ 'user_id is missing or empty'
69
+ )
73
70
  end
74
71
  end
75
72
 
@@ -1,11 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- describe Castle::Commands::Identify do
3
+ describe Castle::Commands::Filter do
4
4
  subject(:instance) { described_class }
5
5
 
6
6
  let(:context) { { test: { test1: '1' } } }
7
- let(:default_payload) { { user_id: '1234', sent_at: time_auto, context: context } }
8
-
7
+ let(:user) { { id: '1234', email: 'foobar@mail.com' } }
8
+ let(:default_payload) do
9
+ {
10
+ request_token: '7e51335b-f4bc-4bc7-875d-b713fb61eb23-bf021a3022a1a302',
11
+ event: '$registration',
12
+ user: user,
13
+ sent_at: time_auto,
14
+ context: context
15
+ }
16
+ end
9
17
  let(:time_now) { Time.now }
10
18
  let(:time_auto) { time_now.utc.iso8601(3) }
11
19
 
@@ -16,36 +24,39 @@ describe Castle::Commands::Identify do
16
24
  describe '.build' do
17
25
  subject(:command) { instance.build(payload) }
18
26
 
27
+ context 'with properties' do
28
+ let(:payload) { default_payload.merge(properties: { test: '1' }) }
29
+ let(:command_data) { default_payload.merge(properties: { test: '1' }, context: context) }
30
+
31
+ it { expect(command.method).to be_eql(:post) }
32
+ it { expect(command.path).to be_eql('filter') }
33
+ it { expect(command.data).to be_eql(command_data) }
34
+ end
35
+
19
36
  context 'with user_traits' do
20
37
  let(:payload) { default_payload.merge(user_traits: { test: '1' }) }
21
- let(:command_data) do
22
- default_payload.merge(user_traits: { test: '1' }, context: context)
23
- end
38
+ let(:command_data) { default_payload.merge(user_traits: { test: '1' }, context: context) }
24
39
 
25
40
  it { expect(command.method).to be_eql(:post) }
26
- it { expect(command.path).to be_eql('identify') }
41
+ it { expect(command.path).to be_eql('filter') }
27
42
  it { expect(command.data).to be_eql(command_data) }
28
43
  end
29
44
 
30
45
  context 'when active true' do
31
46
  let(:payload) { default_payload.merge(context: context.merge(active: true)) }
32
- let(:command_data) do
33
- default_payload.merge(context: context.merge(active: true))
34
- end
47
+ let(:command_data) { default_payload.merge(context: context.merge(active: true)) }
35
48
 
36
49
  it { expect(command.method).to be_eql(:post) }
37
- it { expect(command.path).to be_eql('identify') }
50
+ it { expect(command.path).to be_eql('filter') }
38
51
  it { expect(command.data).to be_eql(command_data) }
39
52
  end
40
53
 
41
54
  context 'when active false' do
42
55
  let(:payload) { default_payload.merge(context: context.merge(active: false)) }
43
- let(:command_data) do
44
- default_payload.merge(context: context.merge(active: false))
45
- end
56
+ let(:command_data) { default_payload.merge(context: context.merge(active: false)) }
46
57
 
47
58
  it { expect(command.method).to be_eql(:post) }
48
- it { expect(command.path).to be_eql('identify') }
59
+ it { expect(command.path).to be_eql('filter') }
49
60
  it { expect(command.data).to be_eql(command_data) }
50
61
  end
51
62
 
@@ -54,7 +65,7 @@ describe Castle::Commands::Identify do
54
65
  let(:command_data) { default_payload.merge(context: context) }
55
66
 
56
67
  it { expect(command.method).to be_eql(:post) }
57
- it { expect(command.path).to be_eql('identify') }
68
+ it { expect(command.path).to be_eql('filter') }
58
69
  it { expect(command.data).to be_eql(command_data) }
59
70
  end
60
71
  end
@@ -62,14 +73,25 @@ describe Castle::Commands::Identify do
62
73
  describe '#validate!' do
63
74
  subject(:validate!) { instance.build(payload) }
64
75
 
65
- context 'with user_id not present' do
76
+ context 'with event not present' do
66
77
  let(:payload) { {} }
67
78
 
79
+ it do
80
+ expect { validate! }.to raise_error(
81
+ Castle::InvalidParametersError,
82
+ 'event is missing or empty'
83
+ )
84
+ end
85
+ end
86
+
87
+ context 'with user not present' do
88
+ let(:payload) { { event: '$login' } }
89
+
68
90
  it { expect { validate! }.not_to raise_error }
69
91
  end
70
92
 
71
- context 'with user_id present' do
72
- let(:payload) { { user_id: '1234' } }
93
+ context 'with event and user present' do
94
+ let(:payload) { { event: '$login', user: user } }
73
95
 
74
96
  it { expect { validate! }.not_to raise_error }
75
97
  end
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Castle::Commands::Log do
4
+ subject(:instance) { described_class }
5
+
6
+ let(:context) { { test: { test1: '1' } } }
7
+ let(:user) { { id: '1234', email: 'foobar@mail.com' } }
8
+ let(:default_payload) do
9
+ {
10
+ request_token: '7e51335b-f4bc-4bc7-875d-b713fb61eb23-bf021a3022a1a302',
11
+ event: '$login',
12
+ status: '$failed',
13
+ user: user,
14
+ sent_at: time_auto,
15
+ context: context
16
+ }
17
+ end
18
+ let(:time_now) { Time.now }
19
+ let(:time_auto) { time_now.utc.iso8601(3) }
20
+
21
+ before { Timecop.freeze(time_now) }
22
+
23
+ after { Timecop.return }
24
+
25
+ describe '.build' do
26
+ subject(:command) { instance.build(payload) }
27
+
28
+ context 'with properties' do
29
+ let(:payload) { default_payload.merge(properties: { test: '1' }) }
30
+ let(:command_data) { default_payload.merge(properties: { test: '1' }, context: context) }
31
+
32
+ it { expect(command.method).to be_eql(:post) }
33
+ it { expect(command.path).to be_eql('log') }
34
+ it { expect(command.data).to be_eql(command_data) }
35
+ end
36
+
37
+ context 'with user_traits' do
38
+ let(:payload) { default_payload.merge(user_traits: { test: '1' }) }
39
+ let(:command_data) { default_payload.merge(user_traits: { test: '1' }, context: context) }
40
+
41
+ it { expect(command.method).to be_eql(:post) }
42
+ it { expect(command.path).to be_eql('log') }
43
+ it { expect(command.data).to be_eql(command_data) }
44
+ end
45
+
46
+ context 'when active true' do
47
+ let(:payload) { default_payload.merge(context: context.merge(active: true)) }
48
+ let(:command_data) { default_payload.merge(context: context.merge(active: true)) }
49
+
50
+ it { expect(command.method).to be_eql(:post) }
51
+ it { expect(command.path).to be_eql('log') }
52
+ it { expect(command.data).to be_eql(command_data) }
53
+ end
54
+
55
+ context 'when active false' do
56
+ let(:payload) { default_payload.merge(context: context.merge(active: false)) }
57
+ let(:command_data) { default_payload.merge(context: context.merge(active: false)) }
58
+
59
+ it { expect(command.method).to be_eql(:post) }
60
+ it { expect(command.path).to be_eql('log') }
61
+ it { expect(command.data).to be_eql(command_data) }
62
+ end
63
+
64
+ context 'when active string' do
65
+ let(:payload) { default_payload.merge(context: context.merge(active: 'string')) }
66
+ let(:command_data) { default_payload.merge(context: context) }
67
+
68
+ it { expect(command.method).to be_eql(:post) }
69
+ it { expect(command.path).to be_eql('log') }
70
+ it { expect(command.data).to be_eql(command_data) }
71
+ end
72
+ end
73
+
74
+ describe '#validate!' do
75
+ subject(:validate!) { instance.build(payload) }
76
+
77
+ context 'with event not present' do
78
+ let(:payload) { {} }
79
+
80
+ it do
81
+ expect { validate! }.to raise_error(
82
+ Castle::InvalidParametersError,
83
+ 'event is missing or empty'
84
+ )
85
+ end
86
+ end
87
+
88
+ context 'with user not present' do
89
+ let(:payload) { { event: '$login' } }
90
+
91
+ it { expect { validate! }.not_to raise_error }
92
+ end
93
+
94
+ context 'with event and user present' do
95
+ let(:payload) { { event: '$login', user: user } }
96
+
97
+ it { expect { validate! }.not_to raise_error }
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Castle::Commands::Risk do
4
+ subject(:instance) { described_class }
5
+
6
+ let(:context) { { test: { test1: '1' } } }
7
+ let(:user) { { id: '1234', email: 'foobar@mail.com' } }
8
+ let(:default_payload) do
9
+ {
10
+ request_token: '7e51335b-f4bc-4bc7-875d-b713fb61eb23-bf021a3022a1a302',
11
+ event: '$login',
12
+ status: '$succeeded',
13
+ user: user,
14
+ sent_at: time_auto,
15
+ context: context
16
+ }
17
+ end
18
+ let(:time_now) { Time.now }
19
+ let(:time_auto) { time_now.utc.iso8601(3) }
20
+
21
+ before { Timecop.freeze(time_now) }
22
+
23
+ after { Timecop.return }
24
+
25
+ describe '.build' do
26
+ subject(:command) { instance.build(payload) }
27
+
28
+ context 'with properties' do
29
+ let(:payload) { default_payload.merge(properties: { test: '1' }) }
30
+ let(:command_data) { default_payload.merge(properties: { test: '1' }, context: context) }
31
+
32
+ it { expect(command.method).to be_eql(:post) }
33
+ it { expect(command.path).to be_eql('risk') }
34
+ it { expect(command.data).to be_eql(command_data) }
35
+ end
36
+
37
+ context 'with user_traits' do
38
+ let(:payload) { default_payload.merge(user_traits: { test: '1' }) }
39
+ let(:command_data) { default_payload.merge(user_traits: { test: '1' }, context: context) }
40
+
41
+ it { expect(command.method).to be_eql(:post) }
42
+ it { expect(command.path).to be_eql('risk') }
43
+ it { expect(command.data).to be_eql(command_data) }
44
+ end
45
+
46
+ context 'when active true' do
47
+ let(:payload) { default_payload.merge(context: context.merge(active: true)) }
48
+ let(:command_data) { default_payload.merge(context: context.merge(active: true)) }
49
+
50
+ it { expect(command.method).to be_eql(:post) }
51
+ it { expect(command.path).to be_eql('risk') }
52
+ it { expect(command.data).to be_eql(command_data) }
53
+ end
54
+
55
+ context 'when active false' do
56
+ let(:payload) { default_payload.merge(context: context.merge(active: false)) }
57
+ let(:command_data) { default_payload.merge(context: context.merge(active: false)) }
58
+
59
+ it { expect(command.method).to be_eql(:post) }
60
+ it { expect(command.path).to be_eql('risk') }
61
+ it { expect(command.data).to be_eql(command_data) }
62
+ end
63
+
64
+ context 'when active string' do
65
+ let(:payload) { default_payload.merge(context: context.merge(active: 'string')) }
66
+ let(:command_data) { default_payload.merge(context: context) }
67
+
68
+ it { expect(command.method).to be_eql(:post) }
69
+ it { expect(command.path).to be_eql('risk') }
70
+ it { expect(command.data).to be_eql(command_data) }
71
+ end
72
+ end
73
+
74
+ describe '#validate!' do
75
+ subject(:validate!) { instance.build(payload) }
76
+
77
+ context 'with event not present' do
78
+ let(:payload) { {} }
79
+
80
+ it do
81
+ expect { validate! }.to raise_error(
82
+ Castle::InvalidParametersError,
83
+ 'event is missing or empty'
84
+ )
85
+ end
86
+ end
87
+
88
+ context 'with user not present' do
89
+ let(:payload) { { event: '$login' } }
90
+
91
+ it { expect { validate! }.not_to raise_error }
92
+ end
93
+
94
+ context 'with event and user present' do
95
+ let(:payload) { { event: '$login', user: user } }
96
+
97
+ it { expect { validate! }.not_to raise_error }
98
+ end
99
+ end
100
+ end
@@ -30,9 +30,7 @@ describe Castle::Commands::StartImpersonation do
30
30
 
31
31
  context 'when active true' do
32
32
  let(:payload) { default_payload.merge(context: context.merge(active: true)) }
33
- let(:command_data) do
34
- default_payload.merge(context: context.merge(active: true))
35
- end
33
+ let(:command_data) { default_payload.merge(context: context.merge(active: true)) }
36
34
 
37
35
  it { expect(command.method).to be_eql(:post) }
38
36
  it { expect(command.path).to be_eql('impersonate') }
@@ -41,9 +39,7 @@ describe Castle::Commands::StartImpersonation do
41
39
 
42
40
  context 'when active false' do
43
41
  let(:payload) { default_payload.merge(context: context.merge(active: false)) }
44
- let(:command_data) do
45
- default_payload.merge(context: context.merge(active: false))
46
- end
42
+ let(:command_data) { default_payload.merge(context: context.merge(active: false)) }
47
43
 
48
44
  it { expect(command.method).to be_eql(:post) }
49
45
  it { expect(command.path).to be_eql('impersonate') }
@@ -67,9 +63,10 @@ describe Castle::Commands::StartImpersonation do
67
63
  let(:payload) { {} }
68
64
 
69
65
  it do
70
- expect do
71
- validate!
72
- end.to raise_error(Castle::InvalidParametersError, 'user_id is missing or empty')
66
+ expect { validate! }.to raise_error(
67
+ Castle::InvalidParametersError,
68
+ 'user_id is missing or empty'
69
+ )
73
70
  end
74
71
  end
75
72
 
@@ -18,9 +18,7 @@ describe Castle::Commands::Track do
18
18
 
19
19
  context 'with user_id' do
20
20
  let(:payload) { default_payload.merge(user_id: '1234') }
21
- let(:command_data) do
22
- default_payload.merge(user_id: '1234', context: context)
23
- end
21
+ let(:command_data) { default_payload.merge(user_id: '1234', context: context) }
24
22
 
25
23
  it { expect(command.method).to be_eql(:post) }
26
24
  it { expect(command.path).to be_eql('track') }
@@ -29,9 +27,7 @@ describe Castle::Commands::Track do
29
27
 
30
28
  context 'with properties' do
31
29
  let(:payload) { default_payload.merge(properties: { test: '1' }) }
32
- let(:command_data) do
33
- default_payload.merge(properties: { test: '1' }, context: context)
34
- end
30
+ let(:command_data) { default_payload.merge(properties: { test: '1' }, context: context) }
35
31
 
36
32
  it { expect(command.method).to be_eql(:post) }
37
33
  it { expect(command.path).to be_eql('track') }
@@ -40,9 +36,7 @@ describe Castle::Commands::Track do
40
36
 
41
37
  context 'with user_traits' do
42
38
  let(:payload) { default_payload.merge(user_traits: { test: '1' }) }
43
- let(:command_data) do
44
- default_payload.merge(user_traits: { test: '1' }, context: context)
45
- end
39
+ let(:command_data) { default_payload.merge(user_traits: { test: '1' }, context: context) }
46
40
 
47
41
  it { expect(command.method).to be_eql(:post) }
48
42
  it { expect(command.path).to be_eql('track') }
@@ -51,9 +45,7 @@ describe Castle::Commands::Track do
51
45
 
52
46
  context 'when active true' do
53
47
  let(:payload) { default_payload.merge(context: context.merge(active: true)) }
54
- let(:command_data) do
55
- default_payload.merge(context: context.merge(active: true))
56
- end
48
+ let(:command_data) { default_payload.merge(context: context.merge(active: true)) }
57
49
 
58
50
  it { expect(command.method).to be_eql(:post) }
59
51
  it { expect(command.path).to be_eql('track') }
@@ -62,9 +54,7 @@ describe Castle::Commands::Track do
62
54
 
63
55
  context 'when active false' do
64
56
  let(:payload) { default_payload.merge(context: context.merge(active: false)) }
65
- let(:command_data) do
66
- default_payload.merge(context: context.merge(active: false))
67
- end
57
+ let(:command_data) { default_payload.merge(context: context.merge(active: false)) }
68
58
 
69
59
  it { expect(command.method).to be_eql(:post) }
70
60
  it { expect(command.path).to be_eql('track') }
@@ -88,9 +78,10 @@ describe Castle::Commands::Track do
88
78
  let(:payload) { {} }
89
79
 
90
80
  it do
91
- expect do
92
- validate!
93
- end.to raise_error(Castle::InvalidParametersError, 'event is missing or empty')
81
+ expect { validate! }.to raise_error(
82
+ Castle::InvalidParametersError,
83
+ 'event is missing or empty'
84
+ )
94
85
  end
95
86
  end
96
87