Skip to content

Commit 095727c

Browse files
committed
closes #101
1 parent 22989c6 commit 095727c

File tree

3 files changed

+87
-10
lines changed

3 files changed

+87
-10
lines changed

ruby/hyper-operation/lib/hyper-operation/exception.rb

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
1+
module Mutations
2+
class ErrorArray
3+
def self.new_from_error_hash(errors)
4+
new(errors.collect do |key, values|
5+
ErrorAtom.new(key, values[:symbol], values)
6+
end)
7+
end
8+
end
9+
end
10+
111
module Hyperstack
212
class AccessViolation < StandardError
3-
413
attr_accessor :details
514

615
def initialize(message = nil, details = nil)
@@ -15,7 +24,16 @@ def __hyperstack_on_error(operation, params, fmted_message)
1524

1625
class Operation
1726
class ValidationException < Mutations::ValidationException
27+
def as_json(*)
28+
errors.as_json
29+
end
30+
31+
def initialize(errors)
32+
unless errors.is_a? Mutations::ErrorHash
33+
errors = Mutations::ErrorArray.new_from_error_hash(errors)
34+
end
35+
super(errors)
36+
end
1837
end
1938
end
20-
2139
end

ruby/hyper-operation/lib/hyper-operation/server_op.rb

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@ def run(*args)
2020
deserialize_response response.json[:response]
2121
end
2222
.fail do |response|
23-
Exception.new response.json[:error]
23+
begin
24+
const_get(response.json[:error_class]).new(response.json[:error])
25+
rescue
26+
Exception.new response.json[:error]
27+
end
2428
end
2529
end
2630
elsif on_opal_server?
@@ -84,6 +88,16 @@ def run_from_client(security_param, controller, operation, params)
8488
handle_exception(e, operation, params)
8589
end
8690

91+
def status(e)
92+
if e.is_a? AccessViolation
93+
403
94+
elsif e.is_a? Operation::ValidationException
95+
400
96+
else
97+
500
98+
end
99+
end
100+
87101
def handle_exception(e, operation, params)
88102
if e.respond_to? :__hyperstack_on_error
89103
params = params.to_h
@@ -93,7 +107,8 @@ def handle_exception(e, operation, params)
93107
message << "\n#{e.details}" if e.respond_to? :details
94108
e.__hyperstack_on_error(operation, params, message.join("\n"))
95109
end
96-
{ json: { error: e }, status: 500 }
110+
111+
{ json: { error_class: e.class.to_s, error: e}, status: status(e) }
97112
end
98113

99114

ruby/hyper-operation/spec/hyper-operation/server_op_spec.rb

Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,14 @@
22

33
describe "isomorphic operations", js: true do
44

5+
let(:response_spy) { spy('response_spy') }
6+
57
before(:each) do
8+
9+
allow(Hyperstack::ServerOp).to receive(:run_from_client).and_wrap_original do |m, *args|
10+
m.call(*args).tap { |r| response_spy.status = r[:status] }
11+
end
12+
613
on_client do
714
class Test
815
include Hyperstack::Component
@@ -65,28 +72,65 @@ def fact(x)
6572

6673
it "will pass server failures back" do
6774
ServerFacts.param :acting_user, nils: true
75+
6876
expect_promise do
69-
ServerFacts.run(n: -1).fail { |exception| Promise.new.resolve(exception) }
70-
end.to eq('N is too small')
77+
ServerFacts.run(n: -1).fail { |exception| Promise.new.resolve(exception.inspect) }
78+
end.to eq('#<Hyperstack::Operation::ValidationException: n is too small>')
79+
expect(response_spy).to have_received(:status=).with(400)
7180
expect_promise do
72-
ServerFacts.run(n: 10000000000).fail { |exception| Promise.new.resolve(exception) }
73-
end.to eq('stack level too deep')
81+
ServerFacts.run(n: 10000000000).fail { |exception| Promise.new.resolve(exception.inspect) }
82+
end.to eq('#<Exception: stack level too deep>')
83+
expect(response_spy).to have_received(:status=).with(500)
84+
end
85+
86+
it "pass abort status back" do
87+
# just to check we will actually interrogate the structure of the exception in this spec
88+
ServerFacts.param :acting_user, nils: true
89+
class ServerFacts < Hyperstack::ServerOp
90+
step { abort! }
91+
end
92+
expect_promise do
93+
ServerFacts.run(n: 5).fail do |exception|
94+
Promise.new.resolve(exception.inspect)
95+
end
96+
end.to eq('#<Hyperstack::Operation::Exit: Hyperstack::Operation::Exit>')
97+
expect(response_spy).to have_received(:status=).with(500)
98+
end
99+
100+
it "pass failure data back" do
101+
# just to check we will actually interrogate the structure of the exception in this spec
102+
ServerFacts.param :acting_user, nils: true
103+
class ServerFacts < Hyperstack::ServerOp
104+
step { raise 'failure' }
105+
failed { [{'some' => 'data'}] }
106+
end
107+
expect_promise do
108+
ServerFacts.run(n: 5).fail do |exception|
109+
Promise.new.resolve(exception)
110+
end
111+
end.to eq([{'some' => 'data'}])
112+
expect(response_spy).to have_received(:status=).with(500)
74113
end
75114

76115
it "pass validation failures back" do
116+
# just to check we will actually interrogate the structure of the exception in this spec
77117
ServerFacts.param :acting_user, nils: true
78118
class ServerFacts < Hyperstack::ServerOp
79119
validate { false }
80120
end
81121
expect_promise do
82-
ServerFacts.run(n: 5).fail { |exception| Promise.new.resolve(exception) }
83-
end.to include('param validation 1 failed')
122+
ServerFacts.run(n: 5).fail do |exception|
123+
Promise.new.resolve(exception.errors.message_list)
124+
end
125+
end.to eq(['param validation 1 failed'])
126+
expect(response_spy).to have_received(:status=).with(400)
84127
end
85128

86129
it "will reject uplinks that don't accept acting_user" do
87130
expect_promise do
88131
ServerFacts.run(n: 5).fail { |exception| Promise.new.resolve(exception) }
89132
end.to include('Hyperstack::AccessViolation')
133+
expect(response_spy).to have_received(:status=).with(403)
90134
end
91135
end
92136

0 commit comments

Comments
 (0)