aggro 0.0.1 → 0.0.2
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +8 -0
- data/.travis.yml +15 -0
- data/Gemfile +9 -0
- data/README.md +5 -1
- data/Rakefile +10 -0
- data/aggro.gemspec +8 -1
- data/lib/aggro.rb +191 -7
- data/lib/aggro/abstract_store.rb +12 -0
- data/lib/aggro/aggregate.rb +98 -0
- data/lib/aggro/aggregate_ref.rb +68 -6
- data/lib/aggro/attribute_dsl.rb +96 -0
- data/lib/aggro/binding_dsl.rb +45 -0
- data/lib/aggro/block_helper.rb +14 -0
- data/lib/aggro/channel.rb +37 -0
- data/lib/aggro/client.rb +12 -0
- data/lib/aggro/cluster_config.rb +57 -0
- data/lib/aggro/command.rb +16 -0
- data/lib/aggro/concurrent_actor.rb +26 -0
- data/lib/aggro/event_bus.rb +94 -0
- data/lib/aggro/event_dsl.rb +53 -0
- data/lib/aggro/event_proxy.rb +23 -0
- data/lib/aggro/event_serializer.rb +14 -0
- data/lib/aggro/file_store.rb +97 -0
- data/lib/aggro/file_store/reader.rb +21 -0
- data/lib/aggro/file_store/writer.rb +27 -0
- data/lib/aggro/handler/command.rb +60 -0
- data/lib/aggro/handler/create_aggregate.rb +42 -0
- data/lib/aggro/handler/get_events.rb +30 -0
- data/lib/aggro/handler/query.rb +60 -0
- data/lib/aggro/handler/start_saga.rb +56 -0
- data/lib/aggro/local_node.rb +28 -0
- data/lib/aggro/locator.rb +32 -0
- data/lib/aggro/message/ask.rb +16 -0
- data/lib/aggro/message/command.rb +36 -0
- data/lib/aggro/message/create_aggregate.rb +16 -0
- data/lib/aggro/message/endpoint.rb +16 -0
- data/lib/aggro/message/events.rb +24 -0
- data/lib/aggro/message/get_events.rb +16 -0
- data/lib/aggro/message/heartbeat.rb +16 -0
- data/lib/aggro/message/invalid_target.rb +20 -0
- data/lib/aggro/message/ok.rb +20 -0
- data/lib/aggro/message/publisher_endpoint_inquiry.rb +16 -0
- data/lib/aggro/message/query.rb +36 -0
- data/lib/aggro/message/result.rb +16 -0
- data/lib/aggro/message/start_saga.rb +28 -0
- data/lib/aggro/message/unhandled_operation.rb +20 -0
- data/lib/aggro/message/unknown_operation.rb +20 -0
- data/lib/aggro/message_parser.rb +10 -0
- data/lib/aggro/message_router.rb +26 -0
- data/lib/aggro/nanomsg_transport.rb +31 -0
- data/lib/aggro/nanomsg_transport/client.rb +35 -0
- data/lib/aggro/nanomsg_transport/connection.rb +98 -0
- data/lib/aggro/nanomsg_transport/publish.rb +17 -0
- data/lib/aggro/nanomsg_transport/publisher.rb +37 -0
- data/lib/aggro/nanomsg_transport/raw_reply.rb +18 -0
- data/lib/aggro/nanomsg_transport/raw_request.rb +18 -0
- data/lib/aggro/nanomsg_transport/reply.rb +17 -0
- data/lib/aggro/nanomsg_transport/request.rb +17 -0
- data/lib/aggro/nanomsg_transport/server.rb +84 -0
- data/lib/aggro/nanomsg_transport/socket_error.rb +20 -0
- data/lib/aggro/nanomsg_transport/subscribe.rb +27 -0
- data/lib/aggro/nanomsg_transport/subscriber.rb +82 -0
- data/lib/aggro/node.rb +29 -0
- data/lib/aggro/node_list.rb +39 -0
- data/lib/aggro/projection.rb +13 -0
- data/lib/aggro/query.rb +11 -0
- data/lib/aggro/saga.rb +94 -0
- data/lib/aggro/saga_runner.rb +87 -0
- data/lib/aggro/saga_runner/start_saga.rb +12 -0
- data/lib/aggro/saga_status.rb +29 -0
- data/lib/aggro/server.rb +88 -0
- data/lib/aggro/subscriber.rb +48 -0
- data/lib/aggro/subscription.rb +41 -0
- data/lib/aggro/transform/boolean.rb +16 -0
- data/lib/aggro/transform/email.rb +26 -0
- data/lib/aggro/transform/id.rb +34 -0
- data/lib/aggro/transform/integer.rb +22 -0
- data/lib/aggro/transform/money.rb +22 -0
- data/lib/aggro/transform/noop.rb +16 -0
- data/lib/aggro/transform/string.rb +16 -0
- data/lib/aggro/transform/time_interval.rb +24 -0
- data/lib/aggro/version.rb +1 -1
- data/spec/lib/aggro/abstract_store_spec.rb +15 -0
- data/spec/lib/aggro/aggregate_ref_spec.rb +63 -12
- data/spec/lib/aggro/aggregate_spec.rb +207 -0
- data/spec/lib/aggro/channel_spec.rb +87 -0
- data/spec/lib/aggro/client_spec.rb +26 -0
- data/spec/lib/aggro/cluster_config_spec.rb +33 -0
- data/spec/lib/aggro/command_spec.rb +52 -0
- data/spec/lib/aggro/concurrent_actor_spec.rb +44 -0
- data/spec/lib/aggro/event_bus_spec.rb +20 -0
- data/spec/lib/aggro/event_serializer_spec.rb +28 -0
- data/spec/lib/aggro/file_store/reader_spec.rb +32 -0
- data/spec/lib/aggro/file_store/writer_spec.rb +67 -0
- data/spec/lib/aggro/file_store_spec.rb +51 -0
- data/spec/lib/aggro/handler/command_spec.rb +78 -0
- data/spec/lib/aggro/handler/create_aggregate_spec.rb +64 -0
- data/spec/lib/aggro/handler/get_events_handler_spec.rb +45 -0
- data/spec/lib/aggro/handler/query_spec.rb +78 -0
- data/spec/lib/aggro/handler/start_saga_spec.rb +64 -0
- data/spec/lib/aggro/local_node_spec.rb +52 -0
- data/spec/lib/aggro/locator_spec.rb +61 -0
- data/spec/lib/aggro/message/ask_spec.rb +23 -0
- data/spec/lib/aggro/message/command_spec.rb +50 -0
- data/spec/lib/aggro/message/create_aggregate_spec.rb +28 -0
- data/spec/lib/aggro/message/endpoint_spec.rb +23 -0
- data/spec/lib/aggro/message/events_spec.rb +37 -0
- data/spec/lib/aggro/message/get_events_spec.rb +33 -0
- data/spec/lib/aggro/message/heartbeat_spec.rb +23 -0
- data/spec/lib/aggro/message/invalid_target_spec.rb +28 -0
- data/spec/lib/aggro/message/ok_spec.rb +27 -0
- data/spec/lib/aggro/message/publisher_endpoint_inquiry_spec.rb +23 -0
- data/spec/lib/aggro/message/query_spec.rb +50 -0
- data/spec/lib/aggro/message/start_saga_spec.rb +37 -0
- data/spec/lib/aggro/message/unhandled_operation_spec.rb +28 -0
- data/spec/lib/aggro/message/unknown_operation_spec.rb +28 -0
- data/spec/lib/aggro/message_parser_spec.rb +16 -0
- data/spec/lib/aggro/message_router_spec.rb +35 -0
- data/spec/lib/aggro/nanomsg_transport/socket_error_spec.rb +21 -0
- data/spec/lib/aggro/nanomsg_transport_spec.rb +37 -0
- data/spec/lib/aggro/node_list_spec.rb +38 -0
- data/spec/lib/aggro/node_spec.rb +44 -0
- data/spec/lib/aggro/projection_spec.rb +22 -0
- data/spec/lib/aggro/query_spec.rb +47 -0
- data/spec/lib/aggro/saga_runner_spec.rb +84 -0
- data/spec/lib/aggro/saga_spec.rb +126 -0
- data/spec/lib/aggro/saga_status_spec.rb +56 -0
- data/spec/lib/aggro/server_spec.rb +118 -0
- data/spec/lib/aggro/subscriber_spec.rb +59 -0
- data/spec/lib/aggro/subscription_spec.rb +50 -0
- data/spec/lib/aggro/transform/boolean_spec.rb +23 -0
- data/spec/lib/aggro/transform/email_spec.rb +13 -0
- data/spec/lib/aggro/transform/id_spec.rb +70 -0
- data/spec/lib/aggro/transform/integer_spec.rb +30 -0
- data/spec/lib/aggro/transform/money_spec.rb +34 -0
- data/spec/lib/aggro/transform/string_spec.rb +15 -0
- data/spec/lib/aggro/transform/time_interval_spec.rb +29 -0
- data/spec/lib/aggro_spec.rb +63 -19
- data/spec/spec_helper.rb +21 -2
- metadata +283 -3
@@ -0,0 +1,56 @@
|
|
1
|
+
RSpec.describe SagaStatus do
|
2
|
+
subject(:status) { SagaStatus.new saga_id }
|
3
|
+
let(:saga_id) { SecureRandom.uuid }
|
4
|
+
|
5
|
+
let(:event_bus) { spy subscribe: true }
|
6
|
+
|
7
|
+
before do
|
8
|
+
allow(Aggro).to receive(:event_bus).and_return event_bus
|
9
|
+
end
|
10
|
+
|
11
|
+
describe '.new' do
|
12
|
+
it 'should subscribe to the SagaRunner with the saga_runner namespace' do
|
13
|
+
status
|
14
|
+
|
15
|
+
expect(event_bus).to have_received(:subscribe).with saga_id, status
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe 'events' do
|
20
|
+
describe '#started' do
|
21
|
+
it 'should put the status into a pending state' do
|
22
|
+
status._started
|
23
|
+
|
24
|
+
expect(status.state).to eq :pending
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#rejected' do
|
29
|
+
it 'should put the status into a rejected state' do
|
30
|
+
status._rejected 'reason'
|
31
|
+
|
32
|
+
expect(status.state).to eq :rejected
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should set the reason' do
|
36
|
+
status._rejected 'reason'
|
37
|
+
|
38
|
+
expect(status.reason).to eq 'reason'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe '#rejected' do
|
43
|
+
it 'should put the status into a rejected state' do
|
44
|
+
status._resolved 'value'
|
45
|
+
|
46
|
+
expect(status.state).to eq :fulfilled
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should set the value' do
|
50
|
+
status._resolved 'value'
|
51
|
+
|
52
|
+
expect(status.value).to eq 'value'
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
RSpec.describe Server do
|
2
|
+
subject(:server) { Server.new endpoint, publisher_endpoint }
|
3
|
+
|
4
|
+
let(:endpoint) { 'tcp://127.0.0.1:5000' }
|
5
|
+
let(:publisher_endpoint) { 'tcp://127.0.0.1:6000' }
|
6
|
+
let(:transport_server) { spy }
|
7
|
+
let(:transport_pub) { spy(publish: true) }
|
8
|
+
let(:transport) { spy(server: transport_server, publisher: transport_pub) }
|
9
|
+
|
10
|
+
before do
|
11
|
+
allow(Aggro).to receive(:transport).and_return transport
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '.new' do
|
15
|
+
let(:handler) { server.method(Server::RAW_HANDLER) }
|
16
|
+
|
17
|
+
it 'should get a server which calls handler from current transport' do
|
18
|
+
server
|
19
|
+
|
20
|
+
expect(transport).to have_received(:server).with(endpoint, handler)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should designate a handler which responds to raw messages' do
|
24
|
+
raw_message = Message::Heartbeat.new(SecureRandom.uuid).to_s
|
25
|
+
|
26
|
+
expect(handler.call(raw_message)).to be_a Message::OK
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should start a publisher for the node using the current transport' do
|
30
|
+
server
|
31
|
+
|
32
|
+
expect(transport).to have_received(:publisher).with(publisher_endpoint)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe '#bind' do
|
37
|
+
it 'should start the transport server' do
|
38
|
+
server.bind
|
39
|
+
|
40
|
+
expect(transport_server).to have_received(:start)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '#publish' do
|
45
|
+
it 'publish the events to the publisher transport' do
|
46
|
+
server.publish :events
|
47
|
+
|
48
|
+
expect(transport_pub).to have_received(:publish).with :events
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe '#handle_message' do
|
53
|
+
let(:sender) { SecureRandom.uuid }
|
54
|
+
|
55
|
+
context 'message is a Command' do
|
56
|
+
let(:commandee_id) { SecureRandom.uuid }
|
57
|
+
let(:details) { { name: 'TestCommand', args: { thing: 'puppy' } } }
|
58
|
+
let(:message) { Message::Command.new(sender, commandee_id, details) }
|
59
|
+
|
60
|
+
it 'should delegate to command handler' do
|
61
|
+
handler = spy(call: true)
|
62
|
+
handler_class = spy(new: handler)
|
63
|
+
|
64
|
+
stub_const 'Aggro::Handler::Command', handler_class
|
65
|
+
|
66
|
+
server.handle_message message
|
67
|
+
|
68
|
+
expect(handler_class).to have_received(:new).with(message, server)
|
69
|
+
expect(handler).to have_received(:call)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context 'message is a CreateAggregate' do
|
74
|
+
let(:id) { SecureRandom.uuid }
|
75
|
+
let(:type) { 'Test' }
|
76
|
+
let(:message) { Message::CreateAggregate.new(sender, id, type) }
|
77
|
+
|
78
|
+
it 'should delegate to command handler' do
|
79
|
+
handler = spy(call: true)
|
80
|
+
handler_class = spy(new: handler)
|
81
|
+
|
82
|
+
stub_const 'Aggro::Handler::CreateAggregate', handler_class
|
83
|
+
|
84
|
+
server.handle_message message
|
85
|
+
|
86
|
+
expect(handler_class).to have_received(:new).with(message, server)
|
87
|
+
expect(handler).to have_received(:call)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
context 'message is a Heartbeat' do
|
92
|
+
let(:message) { Message::Heartbeat.new(sender) }
|
93
|
+
|
94
|
+
it 'should return an OK message' do
|
95
|
+
expect(server.handle_message(message)).to be_a Message::OK
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context 'message is a PublisherEndpointInquiry' do
|
100
|
+
let(:message) { Message::PublisherEndpointInquiry.new(sender) }
|
101
|
+
|
102
|
+
it 'should return an Endpoint message with the publisher endpoint' do
|
103
|
+
response = server.handle_message(message)
|
104
|
+
|
105
|
+
expect(response).to be_a Message::Endpoint
|
106
|
+
expect(response.endpoint).to eq publisher_endpoint
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
describe '#stop' do
|
112
|
+
it 'should stop the transport server' do
|
113
|
+
server.stop
|
114
|
+
|
115
|
+
expect(transport_server).to have_received(:stop)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
RSpec.describe Subscriber do
|
2
|
+
subject(:subscriber) { Subscriber.new(endpoint, callable) }
|
3
|
+
|
4
|
+
let(:callable) { spy }
|
5
|
+
let(:endpoint) { 'tcp://127.0.0.1:6000' }
|
6
|
+
let(:transport_sub) { spy }
|
7
|
+
let(:transport) { spy(subscriber: transport_sub) }
|
8
|
+
|
9
|
+
before do
|
10
|
+
allow(Aggro).to receive(:transport).and_return transport
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '.new' do
|
14
|
+
let(:handler) { subscriber.method(Subscriber::RAW_HANDLER) }
|
15
|
+
|
16
|
+
it 'should get a server which calls handler from current transport' do
|
17
|
+
subscriber
|
18
|
+
|
19
|
+
expect(transport).to have_received(:subscriber).with(endpoint, handler)
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should designate a handler which parses raw messages' do
|
23
|
+
topic = SecureRandom.uuid
|
24
|
+
raw_message = Message::Events.new(topic, []).to_s
|
25
|
+
handler.call(raw_message)
|
26
|
+
|
27
|
+
expect(callable).to have_received(:call).with(topic, [])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '#bind' do
|
32
|
+
it 'should start the transport server' do
|
33
|
+
subscriber.bind
|
34
|
+
|
35
|
+
expect(transport_sub).to have_received(:start)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe '#handle_message' do
|
40
|
+
context 'message is an Events' do
|
41
|
+
let(:topic) { SecureRandom.uuid }
|
42
|
+
let(:message) { Message::Events.new(topic, []) }
|
43
|
+
|
44
|
+
it 'should call the callback with the topic and events' do
|
45
|
+
subscriber.handle_message message
|
46
|
+
|
47
|
+
expect(callable).to have_received(:call).with(topic, [])
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe '#stop' do
|
53
|
+
it 'should stop the transport server' do
|
54
|
+
subscriber.stop
|
55
|
+
|
56
|
+
expect(transport_sub).to have_received(:stop)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
RSpec.describe Subscription do
|
2
|
+
subject(:subscription) { Subscription.new topic, subscriber, ns, filters, 0 }
|
3
|
+
|
4
|
+
let(:topic) { SecureRandom.uuid }
|
5
|
+
let(:subscriber) { double }
|
6
|
+
let(:ns) { :test }
|
7
|
+
let(:filters) { { correlation_id: correlation_id } }
|
8
|
+
|
9
|
+
let(:correlation_id) { SecureRandom.uuid }
|
10
|
+
let(:details) { { name: 'Sebastian', correlation_id: correlation_id } }
|
11
|
+
let(:event) { double(name: 'added_contact', details: details) }
|
12
|
+
|
13
|
+
let(:invokr) { spy }
|
14
|
+
before { stub_const 'Invokr', invokr }
|
15
|
+
|
16
|
+
describe '#handle_event' do
|
17
|
+
context 'subscriber can handle the event' do
|
18
|
+
before { allow(subscriber).to receive(:handles_event?).and_return true }
|
19
|
+
|
20
|
+
context 'the filters match the event details' do
|
21
|
+
it 'should call the event on the subscriber with the event details' do
|
22
|
+
subscription.handle_event event
|
23
|
+
|
24
|
+
expect(invokr).to have_received(:invoke).with \
|
25
|
+
on: subscriber, method: 'test_added_contact', using: details
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'the filters do not match the event details' do
|
30
|
+
let(:details) { { name: 'Sebastian' } }
|
31
|
+
|
32
|
+
it 'should not call the event on the subscriber' do
|
33
|
+
subscription.handle_event event
|
34
|
+
|
35
|
+
expect(invokr).to_not have_received(:invoke)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context 'subscriber cannot handle the event' do
|
41
|
+
before { allow(subscriber).to receive(:handles_event?).and_return false }
|
42
|
+
|
43
|
+
it 'should not call the event on the subscriber' do
|
44
|
+
subscription.handle_event event
|
45
|
+
|
46
|
+
expect(invokr).to_not have_received(:invoke)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
RSpec.describe Transform::Boolean do
|
2
|
+
describe '.deserialize' do
|
3
|
+
it 'should transform the value to a boolean' do
|
4
|
+
expect(Transform::Boolean.deserialize(false)).to eq false
|
5
|
+
expect(Transform::Boolean.deserialize(true)).to eq true
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'should return nil if no boolean appropriate' do
|
9
|
+
expect(Transform::Boolean.deserialize('test')).to eq nil
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '.serialize' do
|
14
|
+
it 'should pass through value if a bool' do
|
15
|
+
expect(Transform::Boolean.serialize(false)).to eq false
|
16
|
+
expect(Transform::Boolean.serialize(true)).to eq true
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should return nil if not a bool' do
|
20
|
+
expect(Transform::Boolean.serialize('test')).to eq nil
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
RSpec.describe Transform::Email do
|
2
|
+
describe '#serialize' do
|
3
|
+
it 'should return the value if valid' do
|
4
|
+
email = 'me@sebastianedwards.co.nz'
|
5
|
+
|
6
|
+
expect(Transform::Email.serialize(email)).to eq email
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should return nil if invalid' do
|
10
|
+
expect(Transform::Email.serialize('not an id')).to eq nil
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
RSpec.describe Transform::ID do
|
2
|
+
REGEX = Transform::ID::ID_REGEX
|
3
|
+
|
4
|
+
context 'generate flag is true' do
|
5
|
+
subject(:transformer) { Transform::ID.new generate: true }
|
6
|
+
|
7
|
+
describe '#deserialize' do
|
8
|
+
it 'should return the value if valid ID value' do
|
9
|
+
id = SecureRandom.uuid
|
10
|
+
|
11
|
+
expect(transformer.deserialize(id)).to eq id
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should generate a new ID if invalid value' do
|
15
|
+
expect(transformer.deserialize('not an id')).to_not eq 'not an id'
|
16
|
+
expect(transformer.deserialize('not an id')).to match REGEX
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should generate a new ID if nil value' do
|
20
|
+
expect(transformer.deserialize(nil)).to_not eq nil
|
21
|
+
expect(transformer.deserialize(nil)).to match REGEX
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#serialize' do
|
26
|
+
it 'should return the value if valid' do
|
27
|
+
id = SecureRandom.uuid
|
28
|
+
|
29
|
+
expect(transformer.serialize(id)).to eq id
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should return a generated ID if invalid' do
|
33
|
+
expect(transformer.serialize('not an id')).to_not eq 'not an id'
|
34
|
+
expect(transformer.serialize('not an id')).to match REGEX
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'generate flag is false or unset' do
|
40
|
+
subject(:transformer) { Transform::ID.new }
|
41
|
+
|
42
|
+
describe '#deserialize' do
|
43
|
+
it 'should return the value if valid ID value' do
|
44
|
+
id = SecureRandom.uuid
|
45
|
+
|
46
|
+
expect(transformer.deserialize(id)).to eq id
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should return nil if invalid value' do
|
50
|
+
expect(transformer.deserialize('not an id')).to eq nil
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should return nil if nil value' do
|
54
|
+
expect(transformer.deserialize(nil)).to eq nil
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe '#serialize' do
|
59
|
+
it 'should return the value if valid' do
|
60
|
+
id = SecureRandom.uuid
|
61
|
+
|
62
|
+
expect(transformer.serialize(id)).to eq id
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'should return nil if invalid' do
|
66
|
+
expect(transformer.serialize('not an id')).to eq nil
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
RSpec.describe Transform::Integer do
|
2
|
+
describe '.deserialize' do
|
3
|
+
it 'should transform the value to a fixnum' do
|
4
|
+
expect(Transform::Integer.deserialize(666)).to eq 666
|
5
|
+
expect(Transform::Integer.deserialize('200')).to eq 200
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'should ignore extraneous characters' do
|
9
|
+
expect(Transform::Integer.deserialize('$6,000')).to eq 6000
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should round decimals down to nearest integer' do
|
13
|
+
expect(Transform::Integer.deserialize('8.0000')).to eq 8
|
14
|
+
expect(Transform::Integer.deserialize('6.4')).to eq 6
|
15
|
+
expect(Transform::Integer.deserialize('9.6')).to eq 9
|
16
|
+
expect(Transform::Integer.deserialize(12.7)).to eq 12
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should return nil if no number appropriate' do
|
20
|
+
expect(Transform::Integer.deserialize('test')).to eq nil
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '.serialize' do
|
25
|
+
it 'should transform the value to a fixnum' do
|
26
|
+
expect(Transform::Integer.serialize(666)).to eq 666
|
27
|
+
expect(Transform::Integer.serialize('200')).to eq 200
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'money'
|
2
|
+
require 'monetize'
|
3
|
+
|
4
|
+
RSpec.describe Transform::Money do
|
5
|
+
let(:ten_usd) { Money.new(1000, 'USD') }
|
6
|
+
let(:five_nzd) { Money.new(500, 'NZD') }
|
7
|
+
|
8
|
+
describe '.deserialize' do
|
9
|
+
it 'should transform strings to a Money' do
|
10
|
+
expect(Transform::Money.deserialize('$10.00 USD')).to eq ten_usd
|
11
|
+
expect(Transform::Money.deserialize('$5.00 NZD')).to eq five_nzd
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should default to USD' do
|
15
|
+
expect(Transform::Money.deserialize('$10.00')).to eq ten_usd
|
16
|
+
expect(Transform::Money.deserialize('$5.00')).to_not eq five_nzd
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should accept an integer' do
|
20
|
+
expect(Transform::Money.deserialize(10)).to eq ten_usd
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should return nil if not a string' do
|
24
|
+
expect(Transform::Money.deserialize(true)).to eq nil
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '.serialize' do
|
29
|
+
it 'should transform the value to a string' do
|
30
|
+
expect(Transform::Money.serialize(ten_usd)).to eq '$10.00 USD'
|
31
|
+
expect(Transform::Money.serialize(five_nzd)).to eq '$5.00 NZD'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|