saxxy 0.1.0
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 +7 -0
 - data/.gitignore +22 -0
 - data/.travis.yml +5 -0
 - data/Gemfile +13 -0
 - data/LICENSE +22 -0
 - data/README.md +117 -0
 - data/Rakefile +12 -0
 - data/lib/saxxy.rb +2 -0
 - data/lib/saxxy/activatable.rb +160 -0
 - data/lib/saxxy/callbacks/libxml.rb +26 -0
 - data/lib/saxxy/callbacks/nokogiri.rb +30 -0
 - data/lib/saxxy/callbacks/ox.rb +66 -0
 - data/lib/saxxy/callbacks/sax.rb +86 -0
 - data/lib/saxxy/context.rb +88 -0
 - data/lib/saxxy/context_tree.rb +85 -0
 - data/lib/saxxy/event.rb +83 -0
 - data/lib/saxxy/event_registry.rb +122 -0
 - data/lib/saxxy/node_action.rb +59 -0
 - data/lib/saxxy/node_rule.rb +90 -0
 - data/lib/saxxy/parsers/base.rb +28 -0
 - data/lib/saxxy/parsers/libxml.rb +52 -0
 - data/lib/saxxy/parsers/nokogiri.rb +28 -0
 - data/lib/saxxy/parsers/ox.rb +30 -0
 - data/lib/saxxy/service.rb +47 -0
 - data/lib/saxxy/utils/agent.rb +66 -0
 - data/lib/saxxy/utils/callback_array.rb +27 -0
 - data/lib/saxxy/utils/helpers.rb +13 -0
 - data/lib/saxxy/version.rb +3 -0
 - data/saxxy.gemspec +21 -0
 - data/spec/saxxy/activatable_spec.rb +344 -0
 - data/spec/saxxy/callbacks/sax_spec.rb +456 -0
 - data/spec/saxxy/context_spec.rb +51 -0
 - data/spec/saxxy/context_tree_spec.rb +68 -0
 - data/spec/saxxy/event_registry_spec.rb +137 -0
 - data/spec/saxxy/event_spec.rb +49 -0
 - data/spec/saxxy/node_action_spec.rb +46 -0
 - data/spec/saxxy/node_rule_spec.rb +99 -0
 - data/spec/saxxy/parsers/libxml_spec.rb +104 -0
 - data/spec/saxxy/parsers/nokogiri_spec.rb +200 -0
 - data/spec/saxxy/parsers/ox_spec.rb +175 -0
 - data/spec/saxxy/utils/agent_spec.rb +63 -0
 - data/spec/spec_helper.rb +28 -0
 - data/spec/support/agent_macros.rb +24 -0
 - metadata +155 -0
 
| 
         @@ -0,0 +1,51 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "spec_helper"
         
     | 
| 
      
 2 
     | 
    
         
            +
            require "saxxy/node_rule"
         
     | 
| 
      
 3 
     | 
    
         
            +
            require "saxxy/node_action"
         
     | 
| 
      
 4 
     | 
    
         
            +
            require "saxxy/context"
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            describe Saxxy::Context do
         
     | 
| 
      
 8 
     | 
    
         
            +
              let(:rule) { Saxxy::NodeRule.new("div") }
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
              it "should include activatable" do
         
     | 
| 
      
 11 
     | 
    
         
            +
                Saxxy::Context.ancestors.should include(Saxxy::Activatable)
         
     | 
| 
      
 12 
     | 
    
         
            +
              end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
              describe "#initialize" do
         
     | 
| 
      
 15 
     | 
    
         
            +
                it "should start with empty child_contexts and actions" do
         
     | 
| 
      
 16 
     | 
    
         
            +
                  subject.actions.should be_empty
         
     | 
| 
      
 17 
     | 
    
         
            +
                  subject.child_contexts.should be_empty
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                it "should start with an activation rule if one is given" do
         
     | 
| 
      
 21 
     | 
    
         
            +
                  subject.activation_rule.should be_nil
         
     | 
| 
      
 22 
     | 
    
         
            +
                  Saxxy::Context.new(rule).activation_rule.should == rule
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
              # #register action is used to register either an action or a child context
         
     | 
| 
      
 27 
     | 
    
         
            +
              describe "#register" do
         
     | 
| 
      
 28 
     | 
    
         
            +
                it "should add an action in the actions array if argument is a NodeAction" do
         
     | 
| 
      
 29 
     | 
    
         
            +
                  action = Saxxy::NodeAction.new(rule)
         
     | 
| 
      
 30 
     | 
    
         
            +
                  expect { subject.register("foo") }.to_not change { subject.actions }
         
     | 
| 
      
 31 
     | 
    
         
            +
                  expect { subject.register(action) }.to change { subject.actions }.by([action])
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                it "should add a child context and change its parent to self if argument is a Context" do
         
     | 
| 
      
 35 
     | 
    
         
            +
                  ctx = Saxxy::Context.new(rule)
         
     | 
| 
      
 36 
     | 
    
         
            +
                  ctx.parent_context.should be_nil
         
     | 
| 
      
 37 
     | 
    
         
            +
                  subject.register(ctx).child_contexts.should == [ctx]
         
     | 
| 
      
 38 
     | 
    
         
            +
                  ctx.parent_context.should == subject
         
     | 
| 
      
 39 
     | 
    
         
            +
                end
         
     | 
| 
      
 40 
     | 
    
         
            +
              end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
              describe "#has_parent?" do
         
     | 
| 
      
 43 
     | 
    
         
            +
                it "returns false if the context has no parent" do
         
     | 
| 
      
 44 
     | 
    
         
            +
                  ctx = Saxxy::Context.new(rule)
         
     | 
| 
      
 45 
     | 
    
         
            +
                  ctx.has_parent?.should be_false
         
     | 
| 
      
 46 
     | 
    
         
            +
                  subject.register(ctx)
         
     | 
| 
      
 47 
     | 
    
         
            +
                  ctx.has_parent?.should be_true
         
     | 
| 
      
 48 
     | 
    
         
            +
                end
         
     | 
| 
      
 49 
     | 
    
         
            +
              end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,68 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "spec_helper"
         
     | 
| 
      
 2 
     | 
    
         
            +
            require "saxxy/node_rule"
         
     | 
| 
      
 3 
     | 
    
         
            +
            require "saxxy/node_action"
         
     | 
| 
      
 4 
     | 
    
         
            +
            require "saxxy/context_tree"
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            describe Saxxy::ContextTree do
         
     | 
| 
      
 8 
     | 
    
         
            +
              let(:subject) { Saxxy::ContextTree.new {} }
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
              describe "#initialize" do
         
     | 
| 
      
 11 
     | 
    
         
            +
                it "sets root to a new context without a rule" do
         
     | 
| 
      
 12 
     | 
    
         
            +
                  subject.root.should be_a(Saxxy::Context)
         
     | 
| 
      
 13 
     | 
    
         
            +
                  subject.root.activation_rule.should be_nil
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                it "should call the eval_subtree! with the provided block" do
         
     | 
| 
      
 17 
     | 
    
         
            +
                  block = ->(){}
         
     | 
| 
      
 18 
     | 
    
         
            +
                  Saxxy::ContextTree.any_instance.should_receive(:eval_subtree!).with(&block)
         
     | 
| 
      
 19 
     | 
    
         
            +
                  Saxxy::ContextTree.new(&block)
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
              # Maybe we should make the #on action idempotent on the sense that it will merge
         
     | 
| 
      
 24 
     | 
    
         
            +
              # the actions (the blocks) if it is called with the same arguments more than once.
         
     | 
| 
      
 25 
     | 
    
         
            +
              describe "#on" do
         
     | 
| 
      
 26 
     | 
    
         
            +
                it "should not change the root context" do
         
     | 
| 
      
 27 
     | 
    
         
            +
                  expect { subject.on("div", { class: /foo/ }) }.to_not change { subject.root }
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                it "creates an action and registers it on the root context" do
         
     | 
| 
      
 31 
     | 
    
         
            +
                  expect { subject.on("div", { class: /foo/ }) }.to change { subject.root.actions.size }.by(1)
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                it "creates a rule for the action with the specified arguments" do
         
     | 
| 
      
 35 
     | 
    
         
            +
                  subject.on("div", { class: /foo/ })
         
     | 
| 
      
 36 
     | 
    
         
            +
                  subject.root.actions[0].activation_rule.element.should == "div"
         
     | 
| 
      
 37 
     | 
    
         
            +
                  subject.root.actions[0].activation_rule.attributes.should == { "class" => /foo/ }
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
              end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
              describe "#under" do
         
     | 
| 
      
 42 
     | 
    
         
            +
                it "should add a child context to the root" do
         
     | 
| 
      
 43 
     | 
    
         
            +
                  expect { subject.under("div", { class: /foo/ }) }.to change { subject.root.child_contexts.length }.by(1)
         
     | 
| 
      
 44 
     | 
    
         
            +
                end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                it "should create a tree of contexts if it has nested #under calls" do
         
     | 
| 
      
 47 
     | 
    
         
            +
                  subject.under("div") do
         
     | 
| 
      
 48 
     | 
    
         
            +
                    under("span") { under("ul") }
         
     | 
| 
      
 49 
     | 
    
         
            +
                    under("div", class: "bar") { under("ul") { under("li", class: /foo/); under("span") } }
         
     | 
| 
      
 50 
     | 
    
         
            +
                  end
         
     | 
| 
      
 51 
     | 
    
         
            +
                  subject.root.should have(1).child_contexts
         
     | 
| 
      
 52 
     | 
    
         
            +
                  subject.root.child_contexts[0].should have(2).child_contexts
         
     | 
| 
      
 53 
     | 
    
         
            +
                  subject.root.child_contexts[0].child_contexts[0].should have(1).child_contexts
         
     | 
| 
      
 54 
     | 
    
         
            +
                  subject.root.child_contexts[0].child_contexts[0].child_contexts[0].should have(0).child_contexts
         
     | 
| 
      
 55 
     | 
    
         
            +
                  subject.root.child_contexts[0].child_contexts[1].should have(1).child_contexts
         
     | 
| 
      
 56 
     | 
    
         
            +
                  subject.root.child_contexts[0].child_contexts[1].child_contexts[0].should have(2).child_contexts
         
     | 
| 
      
 57 
     | 
    
         
            +
                end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                it "should build an activation rule for the child context from arguments" do
         
     | 
| 
      
 60 
     | 
    
         
            +
                  args = ["div", { class: /foo/ }]
         
     | 
| 
      
 61 
     | 
    
         
            +
                  subject.under(*args)
         
     | 
| 
      
 62 
     | 
    
         
            +
                  ctx = subject.root.child_contexts[0]
         
     | 
| 
      
 63 
     | 
    
         
            +
                  ctx.activation_rule.element.should == "div"
         
     | 
| 
      
 64 
     | 
    
         
            +
                  ctx.activation_rule.attributes.should == { "class" => /foo/ }
         
     | 
| 
      
 65 
     | 
    
         
            +
                end
         
     | 
| 
      
 66 
     | 
    
         
            +
              end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,137 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "spec_helper"
         
     | 
| 
      
 2 
     | 
    
         
            +
            require "saxxy/node_rule"
         
     | 
| 
      
 3 
     | 
    
         
            +
            require "saxxy/node_action"
         
     | 
| 
      
 4 
     | 
    
         
            +
            require "saxxy/event_registry"
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            describe Saxxy::EventRegistry do
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
              def actions(reg = subject)
         
     | 
| 
      
 10 
     | 
    
         
            +
                reg.instance_variable_get("@actions")
         
     | 
| 
      
 11 
     | 
    
         
            +
              end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
              describe "#initialize" do
         
     | 
| 
      
 15 
     | 
    
         
            +
                it "sets the actions to an empty hash" do
         
     | 
| 
      
 16 
     | 
    
         
            +
                  actions(Saxxy::EventRegistry.new).should == {}
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
              describe "#register_event_from_action" do
         
     | 
| 
      
 22 
     | 
    
         
            +
                let(:rule) { Saxxy::NodeRule.new("div", { title: "foo" }) }
         
     | 
| 
      
 23 
     | 
    
         
            +
                let(:action) { Saxxy::NodeAction.new(rule) }
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                it "should create the action entry with events as the value if it does not exist yet" do
         
     | 
| 
      
 26 
     | 
    
         
            +
                  actions().should == {}
         
     | 
| 
      
 27 
     | 
    
         
            +
                  event = subject.register_event_from_action(action)
         
     | 
| 
      
 28 
     | 
    
         
            +
                  actions().should == { action => [event] }
         
     | 
| 
      
 29 
     | 
    
         
            +
                end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                it "should append the event to the action entry" do
         
     | 
| 
      
 32 
     | 
    
         
            +
                  ev1 = subject.register_event_from_action(action)
         
     | 
| 
      
 33 
     | 
    
         
            +
                  ev2 = subject.register_event_from_action(action)
         
     | 
| 
      
 34 
     | 
    
         
            +
                  actions()[action].should == [ev1, ev2]
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
              end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
              describe "#events" do
         
     | 
| 
      
 40 
     | 
    
         
            +
                let(:rule1) { Saxxy::NodeRule.new("div", { class: /foo/ }) }
         
     | 
| 
      
 41 
     | 
    
         
            +
                let(:rule2) { Saxxy::NodeRule.new("div", { title: "foo" }) }
         
     | 
| 
      
 42 
     | 
    
         
            +
                let(:action1) { Saxxy::NodeAction.new(rule1) }
         
     | 
| 
      
 43 
     | 
    
         
            +
                let(:action2) { Saxxy::NodeAction.new(rule2) }
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                it "should return an array consisting of the last event of each action" do
         
     | 
| 
      
 46 
     | 
    
         
            +
                  5.times { subject.register_event_from_action(action1) }
         
     | 
| 
      
 47 
     | 
    
         
            +
                  last_ev1 = subject.register_event_from_action(action1)
         
     | 
| 
      
 48 
     | 
    
         
            +
                  5.times { subject.register_event_from_action(action2) }
         
     | 
| 
      
 49 
     | 
    
         
            +
                  last_ev2 = subject.register_event_from_action(action2)
         
     | 
| 
      
 50 
     | 
    
         
            +
                  subject.events.should == [last_ev1, last_ev2]
         
     | 
| 
      
 51 
     | 
    
         
            +
                end
         
     | 
| 
      
 52 
     | 
    
         
            +
              end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
              describe "#push_text" do
         
     | 
| 
      
 56 
     | 
    
         
            +
                let(:rule1) { Saxxy::NodeRule.new("div", { class: /foo/ }) }
         
     | 
| 
      
 57 
     | 
    
         
            +
                let(:rule2) { Saxxy::NodeRule.new("div", { title: "foo" }) }
         
     | 
| 
      
 58 
     | 
    
         
            +
                let(:action1) { Saxxy::NodeAction.new(rule1) }
         
     | 
| 
      
 59 
     | 
    
         
            +
                let(:action2) { Saxxy::NodeAction.new(rule2) }
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                it "should add the text to the events (last events)" do
         
     | 
| 
      
 62 
     | 
    
         
            +
                  5.times { subject.register_event_from_action(action1) }
         
     | 
| 
      
 63 
     | 
    
         
            +
                  last_ev1 = subject.register_event_from_action(action1)
         
     | 
| 
      
 64 
     | 
    
         
            +
                  5.times { subject.register_event_from_action(action2) }
         
     | 
| 
      
 65 
     | 
    
         
            +
                  last_ev2 = subject.register_event_from_action(action2)
         
     | 
| 
      
 66 
     | 
    
         
            +
                  expect { subject.push_text("foo") }.to change {
         
     | 
| 
      
 67 
     | 
    
         
            +
                    [last_ev1, last_ev2].map(&:text)
         
     | 
| 
      
 68 
     | 
    
         
            +
                  }.from(["", ""]).to(["foo", "foo"])
         
     | 
| 
      
 69 
     | 
    
         
            +
                end
         
     | 
| 
      
 70 
     | 
    
         
            +
              end
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
              describe "#deactivate_events_on" do
         
     | 
| 
      
 74 
     | 
    
         
            +
                let(:rule1) { Saxxy::NodeRule.new("div", { class: /foo/ }) }
         
     | 
| 
      
 75 
     | 
    
         
            +
                let(:rule2) { Saxxy::NodeRule.new("span", { title: "foo" }) }
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                it "should call deactivate_events_on on every event with the element name as argument" do
         
     | 
| 
      
 78 
     | 
    
         
            +
                  last_ev1 = subject.register_event_from_action(a1 = Saxxy::NodeAction.new(rule1))
         
     | 
| 
      
 79 
     | 
    
         
            +
                  last_ev2 = subject.register_event_from_action(a2 = Saxxy::NodeAction.new(rule2))
         
     | 
| 
      
 80 
     | 
    
         
            +
                  last_ev1.should_receive(:deactivate_on).with("div")
         
     | 
| 
      
 81 
     | 
    
         
            +
                  last_ev2.should_receive(:deactivate_on).with("div")
         
     | 
| 
      
 82 
     | 
    
         
            +
                  subject.deactivate_events_on("div")
         
     | 
| 
      
 83 
     | 
    
         
            +
                end
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                it "should not remove inactive events" do
         
     | 
| 
      
 86 
     | 
    
         
            +
                  last_ev1 = subject.register_event_from_action(a1 = Saxxy::NodeAction.new(rule1))
         
     | 
| 
      
 87 
     | 
    
         
            +
                  last_ev2 = subject.register_event_from_action(a2 = Saxxy::NodeAction.new(rule2))
         
     | 
| 
      
 88 
     | 
    
         
            +
                  expect { subject.deactivate_events_on("div") }.to_not change { actions()[a1] }
         
     | 
| 
      
 89 
     | 
    
         
            +
                  expect { subject.deactivate_events_on("div") }.to_not change { actions()[a2] }
         
     | 
| 
      
 90 
     | 
    
         
            +
                end
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                it "should remove active events that match the element name" do
         
     | 
| 
      
 93 
     | 
    
         
            +
                  last_ev11 = subject.register_event_from_action(a1 = Saxxy::NodeAction.new(rule1)).tap do |e|
         
     | 
| 
      
 94 
     | 
    
         
            +
                    e.activate_on("div", "class" => "foo")
         
     | 
| 
      
 95 
     | 
    
         
            +
                  end
         
     | 
| 
      
 96 
     | 
    
         
            +
                  last_ev12 = subject.register_event_from_action(a1).tap { |e| e.activate_on("div", "class" => "foo") }
         
     | 
| 
      
 97 
     | 
    
         
            +
                  last_ev21 = subject.register_event_from_action(a2 = Saxxy::NodeAction.new(rule2))
         
     | 
| 
      
 98 
     | 
    
         
            +
                  expect {
         
     | 
| 
      
 99 
     | 
    
         
            +
                    subject.deactivate_events_on("div")
         
     | 
| 
      
 100 
     | 
    
         
            +
                  }.to change { actions()[a1] }.from([last_ev11, last_ev12]).to([last_ev11])
         
     | 
| 
      
 101 
     | 
    
         
            +
                end
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
                it "should delete the action if the last event gets removed" do
         
     | 
| 
      
 104 
     | 
    
         
            +
                  last_ev1 = subject.register_event_from_action(a1 = Saxxy::NodeAction.new(rule1)).tap do |e|
         
     | 
| 
      
 105 
     | 
    
         
            +
                    e.activate_on("div", "class" => "foo")
         
     | 
| 
      
 106 
     | 
    
         
            +
                  end
         
     | 
| 
      
 107 
     | 
    
         
            +
                  last_ev2 = subject.register_event_from_action(a2 = Saxxy::NodeAction.new(rule2))
         
     | 
| 
      
 108 
     | 
    
         
            +
                  expect {
         
     | 
| 
      
 109 
     | 
    
         
            +
                    subject.deactivate_events_on("div")
         
     | 
| 
      
 110 
     | 
    
         
            +
                  }.to change { actions()[a1] }.from([last_ev1]).to(nil)
         
     | 
| 
      
 111 
     | 
    
         
            +
                end
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
                it "should not remove already activated events that don't match the element name" do
         
     | 
| 
      
 114 
     | 
    
         
            +
                  last_ev1 = subject.register_event_from_action(a1 = Saxxy::NodeAction.new(rule1)).tap do |e|
         
     | 
| 
      
 115 
     | 
    
         
            +
                    e.activate_on("div", "class" => "foo")
         
     | 
| 
      
 116 
     | 
    
         
            +
                  end
         
     | 
| 
      
 117 
     | 
    
         
            +
                  last_ev2 = subject.register_event_from_action(a2 = Saxxy::NodeAction.new(rule2))
         
     | 
| 
      
 118 
     | 
    
         
            +
                  expect { subject.deactivate_events_on("span") }.to_not change { actions()[a1] }
         
     | 
| 
      
 119 
     | 
    
         
            +
                  expect { subject.deactivate_events_on("span") }.to_not change { actions()[a2] }
         
     | 
| 
      
 120 
     | 
    
         
            +
                end
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
                it "should append the text of the removed event to the next one in the queue" do
         
     | 
| 
      
 123 
     | 
    
         
            +
                  last_ev11 = subject.register_event_from_action(a1 = Saxxy::NodeAction.new(rule1)).tap do |e|
         
     | 
| 
      
 124 
     | 
    
         
            +
                    e.append_text("foo")
         
     | 
| 
      
 125 
     | 
    
         
            +
                    e.activate_on("div", "class" => "foo")
         
     | 
| 
      
 126 
     | 
    
         
            +
                  end
         
     | 
| 
      
 127 
     | 
    
         
            +
                  last_ev12 = subject.register_event_from_action(a1).tap do |e|
         
     | 
| 
      
 128 
     | 
    
         
            +
                    e.append_text(" bar")
         
     | 
| 
      
 129 
     | 
    
         
            +
                    e.activate_on("div", "class" => "foo")
         
     | 
| 
      
 130 
     | 
    
         
            +
                  end
         
     | 
| 
      
 131 
     | 
    
         
            +
                  last_ev21 = subject.register_event_from_action(a2 = Saxxy::NodeAction.new(rule2))
         
     | 
| 
      
 132 
     | 
    
         
            +
                  expect {
         
     | 
| 
      
 133 
     | 
    
         
            +
                    subject.deactivate_events_on("div")
         
     | 
| 
      
 134 
     | 
    
         
            +
                  }.to change { last_ev11.text }.from("foo").to("foo bar")
         
     | 
| 
      
 135 
     | 
    
         
            +
                end
         
     | 
| 
      
 136 
     | 
    
         
            +
              end
         
     | 
| 
      
 137 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,49 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "spec_helper"
         
     | 
| 
      
 2 
     | 
    
         
            +
            require "saxxy/node_action"
         
     | 
| 
      
 3 
     | 
    
         
            +
            require "saxxy/node_rule"
         
     | 
| 
      
 4 
     | 
    
         
            +
            require "saxxy/event"
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            describe Saxxy::Event do
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
              def event(action = Saxxy::NodeAction.new(Saxxy::NodeRule.new("div")))
         
     | 
| 
      
 10 
     | 
    
         
            +
                Saxxy::Event.new(action)
         
     | 
| 
      
 11 
     | 
    
         
            +
              end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              it "should include activatable" do
         
     | 
| 
      
 14 
     | 
    
         
            +
                Saxxy::Event.ancestors.should include(Saxxy::Activatable)
         
     | 
| 
      
 15 
     | 
    
         
            +
              end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
              describe "#initialize" do
         
     | 
| 
      
 18 
     | 
    
         
            +
                it "should set the action to the argument" do
         
     | 
| 
      
 19 
     | 
    
         
            +
                  action = Saxxy::NodeAction.new(Saxxy::NodeRule.new("div"))
         
     | 
| 
      
 20 
     | 
    
         
            +
                  event(action).action.should == action
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                it "should call initialize_activatable with the activation rule that action has" do
         
     | 
| 
      
 24 
     | 
    
         
            +
                  rule = Saxxy::NodeRule.new("div")
         
     | 
| 
      
 25 
     | 
    
         
            +
                  Saxxy::Event.any_instance.should_receive(:initialize_activatable).with(rule)
         
     | 
| 
      
 26 
     | 
    
         
            +
                  event(Saxxy::NodeAction.new(rule))
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                it "should set the text instance variable to an empty string" do
         
     | 
| 
      
 30 
     | 
    
         
            +
                  event().text.should == ""
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
              end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
              describe "#append_text" do
         
     | 
| 
      
 35 
     | 
    
         
            +
                it "appends the text provided as an argument to the @text instance variable" do
         
     | 
| 
      
 36 
     | 
    
         
            +
                  e = event()
         
     | 
| 
      
 37 
     | 
    
         
            +
                  expect { e.append_text("foo") }.to change { e.text }.from("").to("foo")
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
              end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
              describe "#fire" do
         
     | 
| 
      
 42 
     | 
    
         
            +
                it "should delegate the call to the action with the text as the argument" do
         
     | 
| 
      
 43 
     | 
    
         
            +
                  e = event()
         
     | 
| 
      
 44 
     | 
    
         
            +
                  e.action.should_receive(:call).with(e.text, nil, {})
         
     | 
| 
      
 45 
     | 
    
         
            +
                  e.fire
         
     | 
| 
      
 46 
     | 
    
         
            +
                end
         
     | 
| 
      
 47 
     | 
    
         
            +
              end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,46 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "spec_helper"
         
     | 
| 
      
 2 
     | 
    
         
            +
            require "saxxy/node_rule"
         
     | 
| 
      
 3 
     | 
    
         
            +
            require "saxxy/node_action"
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            describe Saxxy::NodeAction do
         
     | 
| 
      
 7 
     | 
    
         
            +
              let(:rule) { Saxxy::NodeRule.new("div") }
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
              describe "#initialize" do
         
     | 
| 
      
 10 
     | 
    
         
            +
                it "initializes with an activation rule and with a block" do
         
     | 
| 
      
 11 
     | 
    
         
            +
                  block = ->() { "this is a test block" }
         
     | 
| 
      
 12 
     | 
    
         
            +
                  action = Saxxy::NodeAction.new(rule, &block)
         
     | 
| 
      
 13 
     | 
    
         
            +
                  action.action.should == block
         
     | 
| 
      
 14 
     | 
    
         
            +
                  action.activation_rule.should == rule
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                it "initializes with the id block if none is given" do
         
     | 
| 
      
 18 
     | 
    
         
            +
                  Saxxy::NodeAction.new(rule).action.call("foo").should == "foo"
         
     | 
| 
      
 19 
     | 
    
         
            +
                end
         
     | 
| 
      
 20 
     | 
    
         
            +
              end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
              describe "#matches" do
         
     | 
| 
      
 23 
     | 
    
         
            +
                it "should delegate the call to activation_rule" do
         
     | 
| 
      
 24 
     | 
    
         
            +
                  action = Saxxy::NodeAction.new(rule)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  args = ["div", { class: /foo/ }]
         
     | 
| 
      
 26 
     | 
    
         
            +
                  action.activation_rule.should_receive(:matches).with(*args)
         
     | 
| 
      
 27 
     | 
    
         
            +
                  action.matches(*args)
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
              end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
              describe "#call" do
         
     | 
| 
      
 32 
     | 
    
         
            +
                it "should delegate the call to an instance exec on the binding i.e. context if a context is given" do
         
     | 
| 
      
 33 
     | 
    
         
            +
                  a_context = Object.new
         
     | 
| 
      
 34 
     | 
    
         
            +
                  action = Saxxy::NodeAction.new(rule, a_context)
         
     | 
| 
      
 35 
     | 
    
         
            +
                  a_context.should_receive(:instance_exec).with(["foo"], &action.action)
         
     | 
| 
      
 36 
     | 
    
         
            +
                  action.call("foo")
         
     | 
| 
      
 37 
     | 
    
         
            +
                end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                it "should delegate the call to an instance exec on itself if no context is given" do
         
     | 
| 
      
 40 
     | 
    
         
            +
                  action = Saxxy::NodeAction.new(rule)
         
     | 
| 
      
 41 
     | 
    
         
            +
                  action.should_receive(:instance_exec).with(["foo"], &action.action)
         
     | 
| 
      
 42 
     | 
    
         
            +
                  action.call("foo")
         
     | 
| 
      
 43 
     | 
    
         
            +
                end
         
     | 
| 
      
 44 
     | 
    
         
            +
              end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,99 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "spec_helper"
         
     | 
| 
      
 2 
     | 
    
         
            +
            require "saxxy/node_rule"
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            describe Saxxy::NodeRule do
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
              describe "#matches" do
         
     | 
| 
      
 8 
     | 
    
         
            +
                it "should return false if @element does not match first argument as string" do
         
     | 
| 
      
 9 
     | 
    
         
            +
                  nr = Saxxy::NodeRule.new("div")
         
     | 
| 
      
 10 
     | 
    
         
            +
                  nr.element.should eql("div")
         
     | 
| 
      
 11 
     | 
    
         
            +
                  nr.matches("span").should be_false
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                it "should return false if @element does not match first argument as regexp" do
         
     | 
| 
      
 15 
     | 
    
         
            +
                  nr = Saxxy::NodeRule.new(/div/)
         
     | 
| 
      
 16 
     | 
    
         
            +
                  nr.element.should be_a(Regexp)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  nr.matches("span").should be_false
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                it "should return true if @element matches first argument as string and empty @attributes" do
         
     | 
| 
      
 21 
     | 
    
         
            +
                  nr = Saxxy::NodeRule.new("div")
         
     | 
| 
      
 22 
     | 
    
         
            +
                  nr.attributes.should be_empty
         
     | 
| 
      
 23 
     | 
    
         
            +
                  nr.matches("div").should be_true
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                it "should return true if @element matches first argument as regexp and empty @attributes" do
         
     | 
| 
      
 27 
     | 
    
         
            +
                  nr = Saxxy::NodeRule.new(/^d[iv]+?/)
         
     | 
| 
      
 28 
     | 
    
         
            +
                  nr.attributes.should be_empty
         
     | 
| 
      
 29 
     | 
    
         
            +
                  nr.matches("div").should be_true
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                it "should return false if @element matches first argument as string
         
     | 
| 
      
 33 
     | 
    
         
            +
                    and non-empty @attributes with keys not in second argument's keys" do
         
     | 
| 
      
 34 
     | 
    
         
            +
                  nr = Saxxy::NodeRule.new("div", { class: /fooo?/ })
         
     | 
| 
      
 35 
     | 
    
         
            +
                  nr.attributes.should_not be_empty
         
     | 
| 
      
 36 
     | 
    
         
            +
                  nr.matches("div", { foo: "bar" }).should be_false
         
     | 
| 
      
 37 
     | 
    
         
            +
                end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                it "should return false if @element matches first argument as regexp
         
     | 
| 
      
 40 
     | 
    
         
            +
                    and non-empty @attributes with keys not in second argument's keys" do
         
     | 
| 
      
 41 
     | 
    
         
            +
                  nr = Saxxy::NodeRule.new(/div/, { class: /fooo?/ })
         
     | 
| 
      
 42 
     | 
    
         
            +
                  nr.attributes.should_not be_empty
         
     | 
| 
      
 43 
     | 
    
         
            +
                  nr.matches("div", { foo: "bar" }).should be_false
         
     | 
| 
      
 44 
     | 
    
         
            +
                end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                it "should return true if @element matches first argument as string
         
     | 
| 
      
 48 
     | 
    
         
            +
                    and non-empty @attributes with keys in second argument's keys and
         
     | 
| 
      
 49 
     | 
    
         
            +
                    at the same time same values should match" do
         
     | 
| 
      
 50 
     | 
    
         
            +
                  nr = Saxxy::NodeRule.new("div", { class: /fooo?/ })
         
     | 
| 
      
 51 
     | 
    
         
            +
                  nr.attributes.should_not be_empty
         
     | 
| 
      
 52 
     | 
    
         
            +
                  nr.matches("div", { foo: "bar", class: "foo" }).should be_true
         
     | 
| 
      
 53 
     | 
    
         
            +
                end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                it "should return true if @element matches first argument as regexp
         
     | 
| 
      
 56 
     | 
    
         
            +
                    and non-empty @attributes with keys in second argument's keys and
         
     | 
| 
      
 57 
     | 
    
         
            +
                    at the same time same values should match" do
         
     | 
| 
      
 58 
     | 
    
         
            +
                  nr = Saxxy::NodeRule.new(/div/, { class: "foo" })
         
     | 
| 
      
 59 
     | 
    
         
            +
                  nr.attributes.should_not be_empty
         
     | 
| 
      
 60 
     | 
    
         
            +
                  nr.matches("div", { foo: "bar", class: "foo" }).should be_true
         
     | 
| 
      
 61 
     | 
    
         
            +
                end
         
     | 
| 
      
 62 
     | 
    
         
            +
              end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
              describe "#match_attributes" do
         
     | 
| 
      
 66 
     | 
    
         
            +
                it "should return true on any attrs hash if the attributes are empty" do
         
     | 
| 
      
 67 
     | 
    
         
            +
                  nr = Saxxy::NodeRule.new(/div/)
         
     | 
| 
      
 68 
     | 
    
         
            +
                  nr.match_attributes({class: "some class", title: "bar"}).should be_true
         
     | 
| 
      
 69 
     | 
    
         
            +
                end
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                it "should return true if an attribute exists and is nil
         
     | 
| 
      
 72 
     | 
    
         
            +
                    and the matching does not contain this attribute" do
         
     | 
| 
      
 73 
     | 
    
         
            +
                  nr = Saxxy::NodeRule.new(/div/, class: nil)
         
     | 
| 
      
 74 
     | 
    
         
            +
                  nr.match_attributes({}).should be_true
         
     | 
| 
      
 75 
     | 
    
         
            +
                end
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                it "should return true if an attribute exists and is nil
         
     | 
| 
      
 78 
     | 
    
         
            +
                    and the matching does contain this attribute and is nil" do
         
     | 
| 
      
 79 
     | 
    
         
            +
                  nr = Saxxy::NodeRule.new(/div/, class: nil)
         
     | 
| 
      
 80 
     | 
    
         
            +
                  nr.match_attributes({ class: nil }).should be_true
         
     | 
| 
      
 81 
     | 
    
         
            +
                end
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
                it "should return false if an attribute exists and is nil
         
     | 
| 
      
 84 
     | 
    
         
            +
                    and the matching does contain this attribute and is not nil" do
         
     | 
| 
      
 85 
     | 
    
         
            +
                  nr = Saxxy::NodeRule.new(/div/, class: nil)
         
     | 
| 
      
 86 
     | 
    
         
            +
                  nr.match_attributes({ class: "foo" }).should be_false
         
     | 
| 
      
 87 
     | 
    
         
            +
                end
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                it "should return true if it has a subset of the matching attributes" do
         
     | 
| 
      
 90 
     | 
    
         
            +
                  nr = Saxxy::NodeRule.new(/div/, title: "foo", class: "bar")
         
     | 
| 
      
 91 
     | 
    
         
            +
                  nr.match_attributes({ title: "foo", class: "bar", rel: "baz" }).should be_true
         
     | 
| 
      
 92 
     | 
    
         
            +
                end
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
                it "should return false if it has a superset of the matching attributes" do
         
     | 
| 
      
 95 
     | 
    
         
            +
                  nr = Saxxy::NodeRule.new(/div/, title: "foo", class: "bar", rel: "baz")
         
     | 
| 
      
 96 
     | 
    
         
            +
                  nr.match_attributes({ title: "foo", class: "bar" }).should be_false
         
     | 
| 
      
 97 
     | 
    
         
            +
                end
         
     | 
| 
      
 98 
     | 
    
         
            +
              end
         
     | 
| 
      
 99 
     | 
    
         
            +
            end
         
     |