require 'volt/models' describe EventChain do before do @a = ReactiveValue.new(1) @b = ReactiveValue.new(2) end it "should chain events when we use add_object" do count = 0 @b.on('changed') { count += 1 } @b.reactive_manager.event_chain.add_object(@a) expect(count).to eq(0) @a.trigger!('changed') expect(count).to eq(1) end it "should chain events after add_object is called" do @b.reactive_manager.event_chain.add_object(@a) add_count = 0 @b.on('added') { add_count += 1 } expect(add_count).to eq(0) @a.trigger!('added') expect(add_count).to eq(1) end it "should remove events" do @b.reactive_manager.event_chain.add_object(@a) add_count = 0 listener = @b.on('added') { add_count += 1 } expect(add_count).to eq(0) @a.trigger!('added') expect(add_count).to eq(1) # Make sure the event is registered # TODO: currently fails # expect(@a.reactive_manager.listeners.size).to eq(1) expect(@b.reactive_manager.event_chain.instance_variable_get('@event_chain').values[0].keys.include?(:added)).to eq(true) listener.remove # Make sure its removed # TODO: also fails # expect(@a.reactive_manager.listeners.size).to eq(0) expect(@b.reactive_manager.event_chain.instance_variable_get('@event_chain').values[0].keys.include?(:added)).to eq(false) @a.trigger!('added') expect(add_count).to eq(1) end it "should unchain directly" do count = 0 a = ReactiveValue.new(Model.new) b = a._name listener = b.on('changed') { count += 1 } expect(b.reactive_manager.listeners[:changed].size).to eq(1) # TODO: ideally this would only bind 1 to a expect(a.reactive_manager.listeners[:changed].size).to eq(1) listener.remove expect(b.reactive_manager.listeners[:changed]).to eq(nil) expect(a.reactive_manager.listeners[:changed]).to eq(nil) end it "should unchain" do count = 0 @b.on('changed') { count += 1 } b_object_listener = @b.reactive_manager.event_chain.add_object(@a) expect(count).to eq(0) @a.trigger!('changed') expect(count).to eq(1) b_object_listener.remove @a.trigger!('changed') expect(count).to eq(1) end it "should unchain up the chain" do count = 0 a = ReactiveValue.new(Model.new) b = a._list expect(a.reactive_manager.listeners.size).to eq(0) listener = b.on('changed') { count += 1 } expect(a.reactive_manager.listeners.size).to eq(1) listener.remove expect(a.reactive_manager.listeners.size).to eq(0) end describe "double add/removes" do it "should unchain" do c = ReactiveValue.new(3) count = 0 @b.on('changed') { count += 1 } c.on('changed') { count += 1 } # Chain b to a b_object_listener = @b.reactive_manager.event_chain.add_object(@a) c_object_listener = c.reactive_manager.event_chain.add_object(@a) expect(count).to eq(0) @a.trigger!('changed') expect(count).to eq(2) b_object_listener.remove @a.trigger!('changed') expect(count).to eq(3) c_object_listener.remove @a.trigger!('changed') expect(count).to eq(3) end end it "should free events when events are unbound" do a = ReactiveValue.new('cool') b = a + 'dude' expect(a.reactive_manager.event_chain.instance_variable_get('@event_counts')).to eq({}) listener1 = b.on('changed') { } expect(a.reactive_manager.event_chain.instance_variable_get('@event_counts')).to_not eq({}) listener2 = b.on('changed') { } listener1.remove expect(a.reactive_manager.event_chain.instance_variable_get('@event_counts')).to_not eq({}) listener2.remove expect(a.reactive_manager.event_chain.instance_variable_get('@event_counts')).to eq({}) end end