ably 0.7.0 → 0.7.1
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.
- data/.travis.yml +2 -2
- data/Rakefile +2 -0
- data/SPEC.md +230 -194
- data/ably.gemspec +2 -0
- data/lib/ably/auth.rb +7 -5
- data/lib/ably/models/idiomatic_ruby_wrapper.rb +5 -7
- data/lib/ably/models/paginated_resource.rb +14 -21
- data/lib/ably/models/protocol_message.rb +1 -1
- data/lib/ably/modules/ably.rb +4 -0
- data/lib/ably/modules/async_wrapper.rb +2 -2
- data/lib/ably/modules/channels_collection.rb +31 -8
- data/lib/ably/modules/conversions.rb +10 -0
- data/lib/ably/modules/enum.rb +2 -3
- data/lib/ably/modules/state_emitter.rb +8 -8
- data/lib/ably/modules/state_machine.rb +7 -3
- data/lib/ably/realtime/channel.rb +6 -5
- data/lib/ably/realtime/channel/channel_manager.rb +11 -10
- data/lib/ably/realtime/channel/channel_state_machine.rb +10 -9
- data/lib/ably/realtime/channels.rb +3 -0
- data/lib/ably/realtime/client/incoming_message_dispatcher.rb +11 -1
- data/lib/ably/realtime/connection.rb +55 -16
- data/lib/ably/realtime/connection/connection_manager.rb +25 -8
- data/lib/ably/realtime/connection/connection_state_machine.rb +9 -9
- data/lib/ably/realtime/connection/websocket_transport.rb +2 -2
- data/lib/ably/realtime/presence.rb +16 -17
- data/lib/ably/util/crypto.rb +1 -1
- data/lib/ably/version.rb +1 -1
- data/spec/acceptance/realtime/channel_history_spec.rb +6 -5
- data/spec/acceptance/realtime/connection_failures_spec.rb +103 -27
- data/spec/acceptance/realtime/connection_spec.rb +81 -17
- data/spec/acceptance/realtime/presence_spec.rb +82 -30
- data/spec/acceptance/rest/auth_spec.rb +22 -19
- data/spec/acceptance/rest/client_spec.rb +4 -4
- data/spec/acceptance/rest/presence_spec.rb +12 -6
- data/spec/rspec_config.rb +9 -0
- data/spec/shared/model_behaviour.rb +1 -1
- data/spec/spec_helper.rb +4 -1
- data/spec/support/event_machine_helper.rb +26 -37
- data/spec/support/markdown_spec_formatter.rb +96 -68
- data/spec/support/rest_testapp_before_retry.rb +15 -0
- data/spec/support/test_app.rb +4 -0
- data/spec/unit/models/idiomatic_ruby_wrapper_spec.rb +20 -2
- data/spec/unit/models/message_spec.rb +1 -1
- data/spec/unit/models/paginated_resource_spec.rb +15 -1
- data/spec/unit/modules/enum_spec.rb +10 -0
- data/spec/unit/realtime/channels_spec.rb +30 -0
- data/spec/unit/rest/channels_spec.rb +30 -0
- metadata +101 -35
- checksums.yaml +0 -7
@@ -5,17 +5,19 @@ describe Ably::Auth do
|
|
5
5
|
include Ably::Modules::Conversions
|
6
6
|
|
7
7
|
def hmac_for(token_request, secret)
|
8
|
-
|
8
|
+
ruby_named_token_request = Ably::Models::IdiomaticRubyWrapper.new(token_request)
|
9
|
+
|
10
|
+
text = [
|
9
11
|
:id,
|
10
12
|
:ttl,
|
11
13
|
:capability,
|
12
14
|
:client_id,
|
13
15
|
:timestamp,
|
14
16
|
:nonce
|
15
|
-
|
17
|
+
].map { |key| "#{ruby_named_token_request[key]}\n" }.join("")
|
16
18
|
|
17
19
|
encode64(
|
18
|
-
|
20
|
+
OpenSSL::HMAC.digest(OpenSSL::Digest::SHA256.new, secret, text)
|
19
21
|
)
|
20
22
|
end
|
21
23
|
|
@@ -38,7 +40,7 @@ describe Ably::Auth do
|
|
38
40
|
else
|
39
41
|
JSON.parse(request.body)
|
40
42
|
end
|
41
|
-
body[key
|
43
|
+
body[convert_to_mixed_case(key)].to_s == val.to_s
|
42
44
|
end
|
43
45
|
|
44
46
|
def serialize(object, protocol)
|
@@ -50,7 +52,7 @@ describe Ably::Auth do
|
|
50
52
|
end
|
51
53
|
|
52
54
|
it 'has immutable options' do
|
53
|
-
expect { auth.options['key_id'] = 'new_id' }.to raise_error RuntimeError, /can't modify frozen
|
55
|
+
expect { auth.options['key_id'] = 'new_id' }.to raise_error RuntimeError, /can't modify frozen.*Hash/
|
54
56
|
end
|
55
57
|
|
56
58
|
describe '#request_token' do
|
@@ -70,7 +72,7 @@ describe Ably::Auth do
|
|
70
72
|
end
|
71
73
|
|
72
74
|
%w(client_id capability nonce timestamp ttl).each do |option|
|
73
|
-
context "option :#{option}", :webmock do
|
75
|
+
context "with option :#{option}", :webmock do
|
74
76
|
let(:random) { random_int_str }
|
75
77
|
let(:options) { { option.to_sym => random } }
|
76
78
|
|
@@ -88,7 +90,7 @@ describe Ably::Auth do
|
|
88
90
|
|
89
91
|
before { auth.request_token options }
|
90
92
|
|
91
|
-
it 'overrides default' do
|
93
|
+
it 'overrides default and uses camelCase notation for all attributes' do
|
92
94
|
expect(request_token_stub).to have_been_requested
|
93
95
|
end
|
94
96
|
end
|
@@ -134,7 +136,7 @@ describe Ably::Auth do
|
|
134
136
|
context 'without :query_time option' do
|
135
137
|
let(:options) { { query_time: false } }
|
136
138
|
|
137
|
-
it '
|
139
|
+
it 'does not query the server for the time' do
|
138
140
|
expect(client).to_not receive(:time)
|
139
141
|
auth.request_token(options)
|
140
142
|
end
|
@@ -356,25 +358,25 @@ describe Ably::Auth do
|
|
356
358
|
subject { auth.create_token_request(options) }
|
357
359
|
|
358
360
|
it 'uses the key ID from the client' do
|
359
|
-
expect(subject[
|
361
|
+
expect(subject['id']).to eql(key_id)
|
360
362
|
end
|
361
363
|
|
362
364
|
it 'uses the default TTL' do
|
363
|
-
expect(subject[
|
365
|
+
expect(subject['ttl']).to eql(Ably::Models::Token::DEFAULTS[:ttl])
|
364
366
|
end
|
365
367
|
|
366
368
|
it 'uses the default capability' do
|
367
|
-
expect(subject[
|
369
|
+
expect(subject['capability']).to eql(Ably::Models::Token::DEFAULTS[:capability].to_json)
|
368
370
|
end
|
369
371
|
|
370
372
|
context 'the nonce' do
|
371
373
|
it 'is unique for every request' do
|
372
|
-
unique_nonces = 100.times.map { auth.create_token_request[
|
374
|
+
unique_nonces = 100.times.map { auth.create_token_request['nonce'] }
|
373
375
|
expect(unique_nonces.uniq.length).to eql(100)
|
374
376
|
end
|
375
377
|
|
376
378
|
it 'is at least 16 characters' do
|
377
|
-
expect(subject[
|
379
|
+
expect(subject['nonce'].length).to be >= 16
|
378
380
|
end
|
379
381
|
end
|
380
382
|
|
@@ -385,7 +387,7 @@ describe Ably::Auth do
|
|
385
387
|
options[attribute.to_sym] = option_value
|
386
388
|
end
|
387
389
|
it "overrides default" do
|
388
|
-
expect(subject[attribute
|
390
|
+
expect(subject[convert_to_mixed_case(attribute)].to_s).to eql(option_value.to_s)
|
389
391
|
end
|
390
392
|
end
|
391
393
|
end
|
@@ -394,8 +396,9 @@ describe Ably::Auth do
|
|
394
396
|
let(:options) { { nonce: 'valid', is_not_used_by_token_request: 'invalid' } }
|
395
397
|
specify 'are ignored' do
|
396
398
|
expect(subject.keys).to_not include(:is_not_used_by_token_request)
|
397
|
-
expect(subject.keys).
|
398
|
-
expect(subject
|
399
|
+
expect(subject.keys).to_not include(convert_to_mixed_case(:is_not_used_by_token_request))
|
400
|
+
expect(subject.keys).to include('nonce')
|
401
|
+
expect(subject['nonce']).to eql('valid')
|
399
402
|
end
|
400
403
|
end
|
401
404
|
|
@@ -417,7 +420,7 @@ describe Ably::Auth do
|
|
417
420
|
|
418
421
|
it 'queries the server for the timestamp' do
|
419
422
|
expect(client).to receive(:time).and_return(time)
|
420
|
-
expect(subject[
|
423
|
+
expect(subject['timestamp']).to eql(time.to_i)
|
421
424
|
end
|
422
425
|
end
|
423
426
|
|
@@ -426,7 +429,7 @@ describe Ably::Auth do
|
|
426
429
|
let(:options) { { timestamp: token_request_time } }
|
427
430
|
|
428
431
|
it 'uses the provided timestamp in the token request' do
|
429
|
-
expect(subject[
|
432
|
+
expect(subject['timestamp']).to eql(token_request_time.to_i)
|
430
433
|
end
|
431
434
|
end
|
432
435
|
|
@@ -444,7 +447,7 @@ describe Ably::Auth do
|
|
444
447
|
|
445
448
|
it 'generates a valid HMAC' do
|
446
449
|
hmac = hmac_for(options, key_secret)
|
447
|
-
expect(subject[
|
450
|
+
expect(subject['mac']).to eql(hmac)
|
448
451
|
end
|
449
452
|
end
|
450
453
|
end
|
@@ -54,12 +54,12 @@ describe Ably::Rest::Client do
|
|
54
54
|
|
55
55
|
it 'creates a new token automatically when the old token expires' do
|
56
56
|
expect { client.channel('channel_name').publish('event', 'message') }.to change { client.auth.current_token }
|
57
|
-
expect(client.auth.current_token.client_id).to eql(token_request_1[
|
57
|
+
expect(client.auth.current_token.client_id).to eql(token_request_1['clientId'])
|
58
58
|
|
59
59
|
sleep 1
|
60
60
|
|
61
61
|
expect { client.channel('channel_name').publish('event', 'message') }.to change { client.auth.current_token }
|
62
|
-
expect(client.auth.current_token.client_id).to eql(token_request_2[
|
62
|
+
expect(client.auth.current_token.client_id).to eql(token_request_2['clientId'])
|
63
63
|
end
|
64
64
|
end
|
65
65
|
|
@@ -68,12 +68,12 @@ describe Ably::Rest::Client do
|
|
68
68
|
|
69
69
|
it 'reuses the existing token for every request' do
|
70
70
|
expect { client.channel('channel_name').publish('event', 'message') }.to change { client.auth.current_token }
|
71
|
-
expect(client.auth.current_token.client_id).to eql(token_request_1[
|
71
|
+
expect(client.auth.current_token.client_id).to eql(token_request_1['clientId'])
|
72
72
|
|
73
73
|
sleep 1
|
74
74
|
|
75
75
|
expect { client.channel('channel_name').publish('event', 'message') }.to_not change { client.auth.current_token }
|
76
|
-
expect(client.auth.current_token.client_id).to eql(token_request_1[
|
76
|
+
expect(client.auth.current_token.client_id).to eql(token_request_1['clientId'])
|
77
77
|
end
|
78
78
|
end
|
79
79
|
end
|
@@ -18,13 +18,13 @@ describe Ably::Rest::Presence do
|
|
18
18
|
end
|
19
19
|
|
20
20
|
context 'tested against presence fixture data set up in test app' do
|
21
|
-
before(:context) do
|
22
|
-
# When this test is run as a part of a test suite, the presence data injected in the test app may have expired
|
23
|
-
WebMock.disable!
|
24
|
-
TestApp.reload
|
25
|
-
end
|
26
|
-
|
27
21
|
describe '#get' do
|
22
|
+
before(:context) do
|
23
|
+
# When this test is run as a part of a test suite, the presence data injected in the test app may have expired
|
24
|
+
WebMock.disable!
|
25
|
+
TestApp.reload
|
26
|
+
end
|
27
|
+
|
28
28
|
let(:channel) { client.channel('persisted:presence_fixtures') }
|
29
29
|
let(:presence) { channel.presence.get }
|
30
30
|
|
@@ -52,6 +52,12 @@ describe Ably::Rest::Presence do
|
|
52
52
|
end
|
53
53
|
|
54
54
|
describe '#history' do
|
55
|
+
before(:context) do
|
56
|
+
# When this test is run as a part of a test suite, the presence data injected in the test app may have expired
|
57
|
+
WebMock.disable!
|
58
|
+
TestApp.reload
|
59
|
+
end
|
60
|
+
|
55
61
|
let(:channel) { client.channel('persisted:presence_fixtures') }
|
56
62
|
let(:presence_history) { channel.presence.history }
|
57
63
|
|
data/spec/rspec_config.rb
CHANGED
@@ -5,6 +5,8 @@
|
|
5
5
|
#
|
6
6
|
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
7
7
|
|
8
|
+
require 'rspec/retry'
|
9
|
+
|
8
10
|
RSpec.configure do |config|
|
9
11
|
config.run_all_when_everything_filtered = true
|
10
12
|
config.filter_run :focus
|
@@ -45,4 +47,11 @@ RSpec.configure do |config|
|
|
45
47
|
end
|
46
48
|
|
47
49
|
config.add_formatter Ably::RSpec::PrivateApiFormatter
|
50
|
+
|
51
|
+
if ENV['RSPEC_RETRY']
|
52
|
+
puts 'Running tests using RSpec retry'
|
53
|
+
config.verbose_retry = true # show retry status in spec process
|
54
|
+
config.default_retry_count = 3
|
55
|
+
config.default_sleep_interval = 2
|
56
|
+
end
|
48
57
|
end
|
@@ -74,7 +74,7 @@ shared_examples 'a model' do |shared_options = {}|
|
|
74
74
|
let(:model_options) { { channel: 'name' } }
|
75
75
|
|
76
76
|
it 'prevents changes' do
|
77
|
-
expect { model.hash[:channel] = 'new' }.to raise_error RuntimeError, /can't modify frozen
|
77
|
+
expect { model.hash[:channel] = 'new' }.to raise_error RuntimeError, /can't modify frozen.*Hash/
|
78
78
|
end
|
79
79
|
|
80
80
|
it 'dups options' do
|
data/spec/spec_helper.rb
CHANGED
@@ -9,9 +9,12 @@ require 'webmock/rspec'
|
|
9
9
|
require 'ably'
|
10
10
|
|
11
11
|
require 'support/api_helper'
|
12
|
-
require 'support/event_machine_helper'
|
13
12
|
require 'support/private_api_formatter'
|
14
13
|
require 'support/protocol_helper'
|
15
14
|
require 'support/random_helper'
|
16
15
|
|
17
16
|
require 'rspec_config'
|
17
|
+
|
18
|
+
# EM Helper must be loaded after rspec_config to ensure around block occurs before RSpec retry
|
19
|
+
require 'support/event_machine_helper'
|
20
|
+
require 'support/rest_testapp_before_retry'
|
@@ -6,7 +6,7 @@ module RSpec
|
|
6
6
|
module EventMachine
|
7
7
|
extend self
|
8
8
|
|
9
|
-
DEFAULT_TIMEOUT =
|
9
|
+
DEFAULT_TIMEOUT = 10
|
10
10
|
|
11
11
|
def run_reactor(timeout = DEFAULT_TIMEOUT)
|
12
12
|
Timeout::timeout(timeout + 0.5) do
|
@@ -24,8 +24,8 @@ module RSpec
|
|
24
24
|
|
25
25
|
# Allows multiple Deferrables to be passed in and calls the provided block when
|
26
26
|
# all success callbacks have completed
|
27
|
-
def when_all(*deferrables
|
28
|
-
raise
|
27
|
+
def when_all(*deferrables)
|
28
|
+
raise ArgumentError, 'Block required' unless block_given?
|
29
29
|
|
30
30
|
options = if deferrables.last.kind_of?(Hash)
|
31
31
|
deferrables.pop
|
@@ -40,9 +40,9 @@ module RSpec
|
|
40
40
|
successful_deferrables[deferrable.object_id] = true
|
41
41
|
if successful_deferrables.keys.sort == deferrables.map(&:object_id).sort
|
42
42
|
if options[:and_wait]
|
43
|
-
::EventMachine.add_timer(options[:and_wait]) {
|
43
|
+
::EventMachine.add_timer(options[:and_wait]) { yield }
|
44
44
|
else
|
45
|
-
|
45
|
+
yield
|
46
46
|
end
|
47
47
|
end
|
48
48
|
end
|
@@ -52,6 +52,15 @@ module RSpec
|
|
52
52
|
end
|
53
53
|
end
|
54
54
|
end
|
55
|
+
|
56
|
+
def wait_until(condition_block, &block)
|
57
|
+
raise ArgumentError, 'Block required' unless block_given?
|
58
|
+
|
59
|
+
yield if condition_block.call
|
60
|
+
::EventMachine.add_timer(0.1) do
|
61
|
+
wait_until condition_block, &block
|
62
|
+
end
|
63
|
+
end
|
55
64
|
end
|
56
65
|
end
|
57
66
|
|
@@ -62,32 +71,11 @@ RSpec.configure do |config|
|
|
62
71
|
end
|
63
72
|
end
|
64
73
|
|
65
|
-
#
|
66
|
-
# does not
|
67
|
-
#
|
74
|
+
# Run the test block wrapped in an EventMachine reactor that has a configured timeout.
|
75
|
+
# As RSpec does not provide an API to wrap blocks, accessing the instance variables is required.
|
76
|
+
# Note, if you start a reactor and simply run the example with example#run then the example
|
77
|
+
# will run and not wait for the reactor to stop thus triggering after callbacks prematurely.
|
68
78
|
#
|
69
|
-
# As there is no public API to inject around blocks correctly without calling the after blocks,
|
70
|
-
# we have to monkey patch the run_after_example method at https://github.com/rspec/rspec-core/blob/master/lib/rspec/core/example.rb#L376
|
71
|
-
# so that it does not run until we explicitly call it once the EventMachine reactor loop is finished.
|
72
|
-
#
|
73
|
-
def patch_example_block_with_surrounding_eventmachine_reactor(example)
|
74
|
-
example.example.class.class_eval do
|
75
|
-
alias_method :run_after_example_original, :run_after_example
|
76
|
-
public :run_after_example_original
|
77
|
-
|
78
|
-
# prevent after hooks being run for example until EventMachine reactor has finished
|
79
|
-
def run_after_example; end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
def remove_patch_example_block(example)
|
84
|
-
example.example.class.class_eval do
|
85
|
-
remove_method :run_after_example
|
86
|
-
alias_method :run_after_example, :run_after_example_original
|
87
|
-
remove_method :run_after_example_original
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
79
|
config.around(:example, :event_machine) do |example|
|
92
80
|
timeout = if example.metadata[:em_timeout].is_a?(Numeric)
|
93
81
|
example.metadata[:em_timeout]
|
@@ -95,17 +83,18 @@ RSpec.configure do |config|
|
|
95
83
|
RSpec::EventMachine::DEFAULT_TIMEOUT
|
96
84
|
end
|
97
85
|
|
98
|
-
|
86
|
+
example_block = example.example.instance_variable_get('@example_block')
|
87
|
+
example_group_instance = example.example.instance_variable_get('@example_group_instance')
|
99
88
|
|
100
|
-
|
89
|
+
event_machine_block = Proc.new do
|
101
90
|
RSpec::EventMachine.run_reactor(timeout) do
|
102
|
-
example
|
103
|
-
raise example.exception if example.exception
|
91
|
+
example_group_instance.instance_exec(example, &example_block)
|
104
92
|
end
|
105
|
-
ensure
|
106
|
-
example.example.run_after_example_original
|
107
|
-
remove_patch_example_block example
|
108
93
|
end
|
94
|
+
|
95
|
+
example.example.instance_variable_set('@example_block', event_machine_block)
|
96
|
+
|
97
|
+
example.run
|
109
98
|
end
|
110
99
|
|
111
100
|
config.before(:example) do
|
@@ -1,89 +1,117 @@
|
|
1
|
-
module Ably
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
1
|
+
module Ably
|
2
|
+
module RSpec
|
3
|
+
# Generate Markdown Specification from the RSpec public API tests
|
4
|
+
#
|
5
|
+
class MarkdownSpecFormatter
|
6
|
+
::RSpec::Core::Formatters.register self, :start, :close,
|
7
|
+
:example_group_started, :example_group_finished,
|
8
|
+
:example_passed, :example_failed, :example_pending,
|
9
|
+
:dump_summary
|
10
|
+
|
11
|
+
def initialize(output)
|
12
|
+
@output = if documenting_rest_only?
|
13
|
+
File.open(File.expand_path('../../../../../../SPEC.md', __FILE__), 'w')
|
14
|
+
else
|
15
|
+
File.open(File.expand_path('../../../SPEC.md', __FILE__), 'w')
|
16
|
+
end
|
17
|
+
|
18
|
+
@indent = 0
|
19
|
+
@passed = 0
|
20
|
+
@pending = 0
|
21
|
+
@failed = 0
|
22
|
+
end
|
17
23
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
24
|
+
def start(notification)
|
25
|
+
puts "\n\e[33m --> Creating SPEC.md <--\e[0m\n"
|
26
|
+
scope = if defined?(Ably::Realtime)
|
27
|
+
'Real-time & REST'
|
28
|
+
else
|
29
|
+
'REST'
|
30
|
+
end
|
31
|
+
output.write "# Ably #{scope} Client Library #{Ably::VERSION} Specification\n"
|
32
|
+
end
|
22
33
|
|
23
|
-
|
24
|
-
|
25
|
-
|
34
|
+
def close(notification)
|
35
|
+
output.close
|
36
|
+
end
|
26
37
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
38
|
+
def example_group_started(notification)
|
39
|
+
output.write "#{indent_prefix}#{notification.group.description}\n"
|
40
|
+
output.write "_(see #{heading_location_path(notification)})_\n" if indent == 0
|
41
|
+
@indent += 1
|
42
|
+
end
|
32
43
|
|
33
|
-
|
34
|
-
|
35
|
-
|
44
|
+
def example_group_finished(notification)
|
45
|
+
@indent -= 1
|
46
|
+
end
|
36
47
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
48
|
+
def example_passed(notification)
|
49
|
+
unless notification.example.metadata[:api_private]
|
50
|
+
output.write "#{indent_prefix}#{example_name_and_link(notification)}\n"
|
51
|
+
@passed += 1
|
52
|
+
end
|
41
53
|
end
|
42
|
-
end
|
43
54
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
55
|
+
def example_failed(notification)
|
56
|
+
unless notification.example.metadata[:api_private]
|
57
|
+
output.write "#{indent_prefix}FAILED: ~~#{example_name_and_link(notification)}~~\n"
|
58
|
+
@failed += 1
|
59
|
+
end
|
48
60
|
end
|
49
|
-
end
|
50
61
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
62
|
+
def example_pending(notification)
|
63
|
+
unless notification.example.metadata[:api_private]
|
64
|
+
output.write "#{indent_prefix}PENDING: *#{example_name_and_link(notification)}*\n"
|
65
|
+
@pending += 1
|
66
|
+
end
|
55
67
|
end
|
56
|
-
end
|
57
68
|
|
58
|
-
|
59
|
-
|
69
|
+
def dump_summary(notification)
|
70
|
+
output.write <<-EOF.gsub(' ', '')
|
60
71
|
|
61
|
-
|
72
|
+
-------
|
62
73
|
|
63
|
-
|
74
|
+
## Test summary
|
64
75
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
76
|
+
* Passing tests: #{@passed}
|
77
|
+
* Pending tests: #{@pending}
|
78
|
+
* Failing tests: #{@failed}
|
79
|
+
EOF
|
80
|
+
end
|
70
81
|
|
71
|
-
|
72
|
-
|
82
|
+
private
|
83
|
+
attr_reader :output, :indent
|
73
84
|
|
74
|
-
|
75
|
-
|
76
|
-
|
85
|
+
def documenting_rest_only?
|
86
|
+
File.exists?(File.expand_path('../../../../../../ably-rest.gemspec', __FILE__))
|
87
|
+
end
|
77
88
|
|
78
|
-
|
79
|
-
|
80
|
-
|
89
|
+
def example_name_and_link(notification)
|
90
|
+
"[#{notification.example.metadata[:description]}](#{path_for(notification.example.location).gsub(/\:(\d+)/, '#L\1')})"
|
91
|
+
end
|
92
|
+
|
93
|
+
def heading_location_path(notification)
|
94
|
+
"[#{notification.group.location.gsub(/\:(\d+)/, '').gsub(%r{^\.\/}, '')}](#{path_for(notification.group.location).gsub(/\:(\d+)/, '')})"
|
95
|
+
end
|
96
|
+
|
97
|
+
def path_for(location)
|
98
|
+
if documenting_rest_only?
|
99
|
+
"https://github.com/ably/ably-ruby/tree/#{submodule_sha}#{location.gsub(%r{^\./lib/submodules/ably-ruby}, '')}"
|
100
|
+
else
|
101
|
+
location
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def submodule_sha
|
106
|
+
@sha ||= `git ls-tree HEAD:lib/submodules grep ably-ruby`[/^\w+\s+\w+\s+(\w+)/, 1]
|
107
|
+
end
|
81
108
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
109
|
+
def indent_prefix
|
110
|
+
if indent > 0
|
111
|
+
"#{' ' * indent}* "
|
112
|
+
else
|
113
|
+
"\n### "
|
114
|
+
end
|
87
115
|
end
|
88
116
|
end
|
89
117
|
end
|