spec/acceptance/rest/channel_spec.rb in ably-0.8.2 vs spec/acceptance/rest/channel_spec.rb in ably-0.8.3
- old
+ new
@@ -3,22 +3,102 @@
describe Ably::Rest::Channel do
include Ably::Modules::Conversions
vary_by_protocol do
+ let(:default_options) { { key: api_key, environment: environment, protocol: protocol} }
+ let(:client_options) { default_options }
let(:client) do
- Ably::Rest::Client.new(key: api_key, environment: environment, protocol: protocol)
+ Ably::Rest::Client.new(client_options)
end
describe '#publish' do
- let(:channel) { client.channel('test') }
- let(:event) { 'foo' }
- let(:message) { 'woop!' }
+ let(:channel) { client.channel(random_str) }
+ let(:name) { 'foo' }
+ let(:data) { 'woop!' }
- it 'should publish the message and return true indicating success' do
- expect(channel.publish(event, message)).to eql(true)
+ context 'with name and data arguments' do
+ it 'publishes the message and return true indicating success' do
+ expect(channel.publish(name, data)).to eql(true)
+ expect(channel.history.items.first.name).to eql(name)
+ expect(channel.history.items.first.data).to eql(data)
+ end
end
+
+ context 'with an array of Hash objects with :name and :data attributes' do
+ let(:messages) do
+ 10.times.map do |index|
+ { name: index.to_s, data: { "index" => index + 10 } }
+ end
+ end
+
+ it 'publishes an array of messages in one HTTP request' do
+ expect(client).to receive(:post).once.and_call_original
+ expect(channel.publish(messages)).to eql(true)
+ expect(channel.history.items.map(&:name)).to match_array(messages.map { |message| message[:name] })
+ expect(channel.history.items.map(&:data)).to match_array(messages.map { |message| message[:data] })
+ end
+ end
+
+ context 'with an array of Message objects' do
+ let(:messages) do
+ 10.times.map do |index|
+ Ably::Models::Message(name: index.to_s, data: { "index" => index + 10 })
+ end
+ end
+
+ it 'publishes an array of messages in one HTTP request' do
+ expect(client).to receive(:post).once.and_call_original
+ expect(channel.publish(messages)).to eql(true)
+ expect(channel.history.items.map(&:name)).to match_array(messages.map(&:name))
+ expect(channel.history.items.map(&:data)).to match_array(messages.map(&:data))
+ end
+ end
+
+ context 'without adequate permissions on the channel' do
+ let(:capability) { { onlyChannel: ['subscribe'] } }
+ let(:client_options) { default_options.merge(use_token_auth: true, token_params: { capability: capability }) }
+
+ it 'raises a permission error when publishing' do
+ expect { channel.publish(name, data) }.to raise_error(Ably::Exceptions::InvalidRequest, /not permitted/)
+ end
+ end
+
+ context 'null attributes' do
+ context 'when name is null' do
+ let(:data) { random_str }
+
+ it 'publishes the message without a name attribute in the payload' do
+ expect(client).to receive(:post).with(anything, { "data" => data }).once.and_call_original
+ expect(channel.publish(nil, data)).to eql(true)
+ expect(channel.history.items.first.name).to be_nil
+ expect(channel.history.items.first.data).to eql(data)
+ end
+ end
+
+ context 'when data is null' do
+ let(:name) { random_str }
+
+ it 'publishes the message without a data attribute in the payload' do
+ expect(client).to receive(:post).with(anything, { "name" => name }).once.and_call_original
+ expect(channel.publish(name)).to eql(true)
+ expect(channel.history.items.first.name).to eql(name)
+ expect(channel.history.items.first.data).to be_nil
+ end
+ end
+
+ context 'with neither name or data attributes' do
+ let(:name) { random_str }
+
+ it 'publishes the message without any attributes in the payload' do
+ expect(client).to receive(:post).with(anything, {}).once.and_call_original
+ expect(channel.publish(nil)).to eql(true)
+ expect(channel.history.items.first.name).to be_nil
+ expect(channel.history.items.first.data).to be_nil
+ end
+ end
+ end
end
describe '#history' do
let(:channel) { client.channel("persisted:#{random_str(4)}") }
let(:expected_history) do
@@ -34,11 +114,15 @@
expected_history.each do |message|
channel.publish(message[:name], message[:data]) || raise('Unable to publish message')
end
end
- it 'should return the current message history for the channel' do
+ it 'returns a PaginatedResult model' do
+ expect(channel.history).to be_a(Ably::Models::PaginatedResult)
+ end
+
+ it 'returns the current message history for the channel' do
actual_history_items = channel.history.items
expect(actual_history_items.size).to eql(3)
expected_history.each do |message|
@@ -47,47 +131,72 @@
expect(matching_message).to be_a(Ably::Models::Message)
end
end
context 'message timestamps' do
- it 'should all be after the messages were published' do
+ specify 'are after the messages were published' do
channel.history.items.each do |message|
expect(before_published.to_f).to be < message.timestamp.to_f
end
end
end
context 'message IDs' do
- it 'should be unique' do
+ it 'is unique' do
message_ids = channel.history.items.map(&:id).compact
expect(message_ids.count).to eql(3)
expect(message_ids.uniq.count).to eql(3)
end
end
- it 'should return paged history using the PaginatedResult model' do
+ it 'returns paged history using the PaginatedResult model' do
page_1 = channel.history(limit: 1)
page_2 = page_1.next
page_3 = page_2.next
all_items = [page_1.items[0].id, page_2.items[0].id, page_3.items[0].id]
expect(all_items.uniq).to eql(all_items)
expect(page_1.items.size).to eql(1)
expect(page_1).to_not be_last
- expect(page_1).to be_first
# Page 2
expect(page_2.items.size).to eql(1)
expect(page_2).to_not be_last
- expect(page_2).to_not be_first
# Page 3
expect(page_3.items.size).to eql(1)
expect(page_3).to be_last
- expect(page_3).to_not be_first
end
+
+ context 'direction' do
+ it 'returns paged history backwards by default' do
+ items = channel.history.items
+ expect(items.first.name).to eql(expected_history.last.fetch(:name))
+ expect(items.last.name).to eql(expected_history.first.fetch(:name))
+ end
+
+ it 'returns history forward if specified in the options' do
+ items = channel.history(direction: :forwards).items
+ expect(items.first.name).to eql(expected_history.first.fetch(:name))
+ expect(items.last.name).to eql(expected_history.last.fetch(:name))
+ end
+ end
+
+ context 'limit' do
+ before do
+ channel.publish 120.times.to_a.map { |i| { name: 'event' } }
+ end
+
+ it 'defaults to 100' do
+ page = channel.history
+ expect(page.items.count).to eql(100)
+ next_page = page.next
+ expect(next_page.items.count).to be >= 20
+ expect(next_page.items.count).to be < 100
+ end
+ end
end
describe '#history option' do
let(:channel_name) { "persisted:#{random_str(4)}" }
let(:channel) { client.channel(channel_name) }
@@ -95,21 +204,22 @@
client.endpoint.tap do |client_end_point|
client_end_point.user = key_name
client_end_point.password = key_secret
end
end
- let(:default_options) do
+ let(:default_history_options) do
{
direction: :backwards,
limit: 100
}
end
[:start, :end].each do |option|
describe ":#{option}", :webmock do
let!(:history_stub) {
- query_params = default_options.merge(option => milliseconds).map { |k, v| "#{k}=#{v}" }.join('&')
+ query_params = default_history_options
+ .merge(option => milliseconds).map { |k, v| "#{k}=#{v}" }.join('&')
stub_request(:get, "#{endpoint}/channels/#{CGI.escape(channel_name)}/messages?#{query_params}").
to_return(:body => '{}', :headers => { 'Content-Type' => 'application/json' })
}
before do
@@ -133,9 +243,26 @@
it 'converts the value to milliseconds since epoch in the hisotry request' do
expect(history_stub).to have_been_requested
end
end
end
+ end
+
+ context 'when argument start is after end' do
+ let(:subject) { channel.history(start: as_since_epoch(Time.now), end: Time.now - 120) }
+
+ it 'should raise an exception' do
+ expect { subject.items }.to raise_error ArgumentError
+ end
+ end
+ end
+
+ context '#presence' do
+ let(:channel_name) { "persisted:#{random_str(4)}" }
+ let(:channel) { client.channel(channel_name) }
+
+ it 'returns a REST Presence object' do
+ expect(channel.presence).to be_a(Ably::Rest::Presence)
end
end
end
end