# encoding: UTF-8 require 'test_helper' describe Vines::Stanza::PubSub::Publish do subject { Vines::Stanza::PubSub::Publish.new(xml, stream) } let(:user) { Vines::User.new(jid: 'alice@wonderland.lit/tea') } let(:stream) { MiniTest::Mock.new } let(:config) do Vines::Config.new do host 'wonderland.lit' do storage(:fs) { dir Dir.tmpdir } pubsub 'games' end end end before do class << stream attr_accessor :config, :nodes, :user def write(node) @nodes ||= [] @nodes << node end end stream.config = config stream.user = user end describe 'when missing a to address' do let(:xml) { publish('') } it 'raises a feature-not-implemented stanza error' do stream.expect(:domain, 'wonderland.lit') -> { subject.process }.must_raise Vines::StanzaErrors::FeatureNotImplemented stream.verify end end describe 'when addressed to bare server domain' do let(:xml) { publish('wonderland.lit') } it 'raises a feature-not-implemented stanza error' do -> { subject.process }.must_raise Vines::StanzaErrors::FeatureNotImplemented stream.verify end end describe 'when addressed to a non-pubsub component' do let(:router) { MiniTest::Mock.new } let(:xml) { publish('bogus.wonderland.lit') } before do router.expect :route, nil, [xml] stream.expect :router, router end it 'routes rather than handle locally' do subject.process stream.verify router.verify end end describe 'when publishing to multiple nodes' do let(:xml) do node(%q{ Test This is a summary. Test This is a summary. }) end it 'raises a bad-request stanza error' do -> { subject.process }.must_raise Vines::StanzaErrors::BadRequest stream.verify end end describe 'when publishing multiple items' do let(:pubsub) { MiniTest::Mock.new } let(:xml) do node(%q{ Test This is a summary. bad }) end it 'raises a bad-request stanza error' do pubsub.expect :node?, true, ['game_13'] subject.stub :pubsub, pubsub do -> { subject.process }.must_raise Vines::StanzaErrors::BadRequest end stream.verify pubsub.verify end end describe 'when publishing one item with multiple payloads' do let(:pubsub) { MiniTest::Mock.new } let(:xml) do node(%q{ Test This is a summary. bad }) end it 'raises a bad-request stanza error' do pubsub.expect :node?, true, ['game_13'] subject.stub :pubsub, pubsub do -> { subject.process }.must_raise Vines::StanzaErrors::BadRequest end stream.verify pubsub.verify end end describe 'when publishing with no payload' do let(:pubsub) { MiniTest::Mock.new } let(:xml) do node(%q{ }) end it 'raises a bad-request stanza error' do pubsub.expect :node?, true, ['game_13'] subject.stub :pubsub, pubsub do -> { subject.process }.must_raise Vines::StanzaErrors::BadRequest end stream.verify pubsub.verify end end describe 'when publishing to a missing node' do let(:xml) { publish('games.wonderland.lit') } it 'raises an item-not-found stanza error' do -> { subject.process }.must_raise Vines::StanzaErrors::ItemNotFound stream.verify end end describe 'when publishing an item without an id' do let(:pubsub) { MiniTest::Mock.new } let(:xml) { publish('games.wonderland.lit', '') } let(:broadcast) { message_broadcast('') } let(:response) do node(%q{ }) end before do pubsub.expect :node?, true, ['game_13'] def pubsub.published; @published; end def pubsub.publish(node, message) @published ||= [] @published << [node, message] end end it 'generates an item id in the response' do subject.stub :pubsub, pubsub do subject.process end stream.verify pubsub.verify stream.nodes.size.must_equal 1 # id is random item = stream.nodes.first.xpath('ns:pubsub/ns:publish/ns:item', 'ns' => 'http://jabber.org/protocol/pubsub').first item['id'].wont_be_nil item.remove_attribute('id') stream.nodes.first.must_equal response end it 'broadcasts the message with the generated item id' do subject.stub :pubsub, pubsub do subject.process end stream.verify pubsub.verify stream.nodes.size.must_equal 1 published_node, published_message = *pubsub.published[0] published_node.must_equal 'game_13' # id is random item = published_message.xpath('ns:event/ns:items/ns:item', 'ns' => 'http://jabber.org/protocol/pubsub#event').first item['id'].wont_be_nil item.remove_attribute('id') published_message.must_equal broadcast end end describe 'when publishing a valid stanza' do let(:pubsub) { MiniTest::Mock.new } let(:xml) { publish('games.wonderland.lit') } let(:response) { result(user.jid, 'games.wonderland.lit') } let(:broadcast) { message_broadcast('item_42') } it 'broadcasts and returns result to sender' do pubsub.expect :node?, true, ['game_13'] pubsub.expect :publish, nil, ['game_13', broadcast] subject.stub :pubsub, pubsub do subject.process end stream.nodes.size.must_equal 1 stream.nodes.first.must_equal response stream.verify pubsub.verify end end private def message_broadcast(item_id) item_id = (item_id.nil? || item_id.empty?) ? ' ' : " id='#{item_id}' " node(%Q{ Test This is a summary. }) end def publish(to, item_id='item_42') item_id = "id='#{item_id}'" unless item_id.nil? || item_id.empty? body = %Q{ Test This is a summary. } iq(type: 'set', to: to, id: 42, body: body) end def result(to, from) iq(from: from, id: 42, to: to, type: 'result') end end