require File.dirname(__FILE__) + '/../../spec_helper'

def valid_<%=rule_name%>_rule_data
  '["Rule Title", ["word one", "word two"],"1"]'
end
  

describe RulesEngine::Rule::<%=rule_class%> do

  def valid_attributes
    {
      :<%=rule_name%>_title => 'Another Title',
      :<%=rule_name%>_match_words => {
                    "1" => { "word" => 'first word'  },
                    "2" => { "word" => 'second word' }
                  }
    }
  end
  
  it "should be discoverable" do
    RulesEngine::Discovery.rule_class("RulesEngine::Rule::<%=rule_class%>").should == RulesEngine::Rule::<%=rule_class%>
  end

  describe "the expected class options" do    
    it "should be in the 'Twitter' group" do
      RulesEngine::Rule::<%=rule_class%>.options[:group].should == "Twitter"
    end
    
    it "should have the diplay name of 'Twitter Filter'" do
      RulesEngine::Rule::<%=rule_class%>.options[:display_name].should == "Twitter Word Filter"
    end

    it "should have the help template of '/re_rules/<%=rule_name%>/help'" do
      RulesEngine::Rule::<%=rule_class%>.options[:help_partial].should == '/re_rules/<%=rule_name%>/help'
    end

    it "should have the new template of '/re_rules/<%=rule_name%>/new'" do
      RulesEngine::Rule::<%=rule_class%>.options[:new_partial].should == '/re_rules/<%=rule_name%>/new'
    end

    it "should have the edit view partial template of '/re_rules/<%=rule_name%>/edit'" do
      RulesEngine::Rule::<%=rule_class%>.options[:edit_partial].should == '/re_rules/<%=rule_name%>/edit'
    end
  end
  
  describe "setting the rule data" do
    before(:each) do
      @filter = RulesEngine::Rule::<%=rule_class%>.new
      @filter.data = valid_<%=rule_name%>_rule_data
    end  
    
    describe "the json data is valid" do
      it "should be valid" do
        @filter.should be_valid
      end
            
      it "should set the title" do
        @filter.title.should == "Rule Title"        
      end

      it "should set the match_words" do
        @filter.match_words.should == ["word one", "word two"]
      end

      it "should set match_type" do
        @filter.match_type.should == RulesEngine::Rule::<%=rule_class%>::WORD_MATCH_WORD
      end
    end

    describe "the data is nil" do
      it "should set the title to nil" do
        @filter.title.should_not be_nil
        @filter.data = nil
        @filter.title.should be_nil
      end
      
      it "should set the words to nil" do
        @filter.match_words.should_not be_nil
        @filter.data = nil
        @filter.match_words.should be_nil
      end

      it "should set match_types to false" do
        @filter.match_type.should_not == RulesEngine::Rule::<%=rule_class%>::WORD_MATCH_ANY
        @filter.data = nil
        @filter.match_type.should == RulesEngine::Rule::<%=rule_class%>::WORD_MATCH_ANY
      end
    end
  end
  
  describe "the summary" do
    it "should be singluar if there is one word" do
      filter = RulesEngine::Rule::<%=rule_class%>.new
      filter.stub!(:match_words).and_return(["one"])
      filter.summary.should == "Filter out tweets with the word one"
    end

    it "should be plural if there are multiple words" do
      filter = RulesEngine::Rule::<%=rule_class%>.new
      filter.stub!(:match_words).and_return(["one", "two", "three"])
      filter.summary.should == "Filter out tweets with the words one, two, three"
    end        
  end

  describe "the data" do
    it "should be converted to a json string" do
      filter = RulesEngine::Rule::<%=rule_class%>.new
      filter.should_receive(:title).and_return("mock title")
      filter.should_receive(:match_words).and_return(["one", "two"])
      filter.should_receive(:match_type).and_return(RulesEngine::Rule::<%=rule_class%>::WORD_MATCH_BEGIN_WITH)
      filter.data.should == '["mock title",["one","two"],"2"]'
    end
  end
  
  describe "the expected_outcomes" do
    it "should be next and stop success" do
      filter = RulesEngine::Rule::<%=rule_class%>.new
      filter.expected_outcomes[0][:outcome].should == RulesEngine::Rule::Outcome::NEXT
    end
  end
  
  describe "setting the rule attributes" do
    before(:each) do
      @filter = RulesEngine::Rule::<%=rule_class%>.new
    end  
    
    it "should be valid with valid attributes" do
      @filter.attributes = valid_attributes
      @filter.should be_valid
    end            

    describe "setting the <%=rule_name%>_title" do
      it "should set the title" do
        @filter.attributes = valid_attributes
        @filter.title.should == 'Another Title'
      end            
    
      it "should not be valid if the '<%=rule_name%>_title' attribute is missing" do
        @filter.attributes = valid_attributes.except(:<%=rule_name%>_title)
        @filter.should_not be_valid
        @filter.errors.should include(:<%=rule_name%>_title)      
      end            
    
      it "should not be valid if the '<%=rule_name%>_title' attribute is blank" do
        @filter.attributes = valid_attributes.merge(:<%=rule_name%>_title => "")
        @filter.should_not be_valid
        @filter.errors.should include(:<%=rule_name%>_title)
      end                
    end

    describe "setting the <%=rule_name%>_match_words" do
      it "should set the words" do
        @filter.attributes = valid_attributes
        @filter.match_words.should == ['first word', 'second word']
      end            
    
      it "should not be valid if the '<%=rule_name%>_match_words' attribute is missing" do
        @filter.attributes = valid_attributes.except(:<%=rule_name%>_match_words)
        @filter.should_not be_valid
        @filter.errors.should include(:<%=rule_name%>_match_words)      
      end            
    
      it "should not be valid if the '<%=rule_name%>_match_words' is not a hash" do
        @filter.attributes = valid_attributes.merge(:<%=rule_name%>_match_words => "filter word")
        @filter.should_not be_valid
        @filter.errors.should include(:<%=rule_name%>_match_words)
      end                

      it "should not be valid if the '<%=rule_name%>_match_words' is empty" do
        @filter.attributes = valid_attributes.merge(:<%=rule_name%>_match_words => {})
        @filter.should_not be_valid
        @filter.errors.should include(:<%=rule_name%>_match_words)
      end                
      
      it "should not include parameters that are marked for deletion" do
        @filter.attributes = valid_attributes.merge(:<%=rule_name%>_match_words => {
                                                                              "1" => { "word" => 'first word', "_delete" => '1'  },
                                                                              "2" => { "word" => 'second word' }
                                                                            }         
         )
        @filter.should be_valid
        @filter.match_words.should == ['second word']
      end
    end
  end

  describe "before a rule is created" do
    # xit "There is nothing to do here"
  end

  describe "before a rule is updated" do
    # xit "There is nothing to do here"
  end
  
  describe "before a rule is destroyed" do
    # xit "There is nothing to do here"
  end
  
  describe "processing the rule" do
    before(:each) do
      @filter = RulesEngine::Rule::<%=rule_class%>.new
      @filter.stub!(:match_type).and_return(RulesEngine::Rule::<%=rule_class%>::WORD_MATCH_BEGIN_WITH)
      @filter.stub!(:match_words).and_return(["mcgurgle", "sonic"])
    end
    
    it "should do nothing if there is no tweet words" do      
      @filter.process(1001, {:plan => "plan"}, {}).outcome.should == RulesEngine::Rule::Outcome::NEXT
    end        
  
    it "should do nothing if there is no match" do
      @filter.process(@job, {:plan => "plan"}, {:tweet_words => ["xmcgurgle"]}).outcome.should == RulesEngine::Rule::Outcome::NEXT
    end        
    
    describe "a match found" do
      describe "WORD_MATCH_ANY" do
        it "should remove a match" do
          @filter.stub!(:match_type).and_return(RulesEngine::Rule::<%=rule_class%>::WORD_MATCH_ANY)
          data =  {:tweet_words => ["AmcgurgleY", "i", "am"]}
          @filter.process(1001, {:plan => "plan"}, data)
          data[:tweet_words].should == ["i", "am"]
        end
      end

      describe "WORD_MATCH_WORD" do
        it "should remove a match" do
          @filter.stub!(:match_type).and_return(RulesEngine::Rule::<%=rule_class%>::WORD_MATCH_WORD)        
          data =  {:tweet_words => ["mcgurgle", "i", "am"]}
          @filter.process(1001, {:plan => "plan"}, data)
          data[:tweet_words].should == ["i", "am"]
        end
      end

      describe "WORD_MATCH_BEGIN_WITH" do
        it "should remove a match" do
          @filter.stub!(:match_type).and_return(RulesEngine::Rule::<%=rule_class%>::WORD_MATCH_BEGIN_WITH)        
          data =  {:tweet_words => ["mcgurgleX", "i", "am"]}
          @filter.process(1001, {:plan => "plan"}, data)
          data[:tweet_words].should == ["i", "am"]
        end
      end

      describe "WORD_MATCH_END_WITH" do
        it "should remove a match" do
          @filter.stub!(:match_type).and_return(RulesEngine::Rule::<%=rule_class%>::WORD_MATCH_END_WITH)        
          data =  {:tweet_words => ["Xmcgurgle", "i", "am"]}
          @filter.process(1001, {:plan => "plan"}, data)
          data[:tweet_words].should == ["i", "am"]
        end
      end      
    end    
  end
end

describe ReWorkflowRulesController do
  include RSpec::Rails::ControllerExampleGroup
  
  render_views
  
  describe "RulesEngine::Rule::<%=rule_class%>" do
  
    before(:each) do
      controller.instance_eval { flash.stub!(:sweep) }
    
      RulesEngine::Discovery.discover!
        
      controller.stub!(:rules_engine_reader_access_required).and_return(true)
      controller.stub!(:rules_engine_editor_access_required).and_return(true)

      @re_workflow = ReWorkflow.create!(:code => "valid code", :title => 'Valid title', :description => 'Test Workflow')
      ReWorkflow.stub!(:find).and_return(@re_workflow)
    end  
  
    describe "help" do
      it "should assign the <%=rule_name%> rule class" do
        get :help, :re_workflow_id => @re_workflow.id, :rule_class_name => "RulesEngine::Rule::<%=rule_class%>"
        assigns[:rule_class].should == RulesEngine::Rule::<%=rule_class%>
      end
    end
  
    describe "new" do
      it "show the new form" do
        get :new, :re_workflow_id => @re_workflow.id, :rule_class_name => "RulesEngine::Rule::<%=rule_class%>"
        response.should have_selector("form#re_rule_new_form") do |form|
          form.should have_selector("input#<%=rule_name%>_title")
          form.should have_selector("input#<%=rule_name%>_match_words_0_word")
          form.should have_selector("select#<%=rule_name%>_match_type") do |selector|
            selector.should have_selector("option", :content => "Any Match") do |option|
              option.attr("selected").should_not be_nil
              option.attr("selected").value.should == "selected"
            end
            selector.should have_selector("option", :content => "Exact Word")
            selector.should have_selector("option", :content => "Begins With")
            selector.should have_selector("option", :content => "End With")
          end  
        end  
      end
    end

    describe "edit" do
      it "show the edit form" do
        re_rule = ReRule.create!(:re_workflow_id => @re_workflow.id, 
                              :rule_class_name => "RulesEngine::Rule::<%=rule_class%>",
                              :data => valid_<%=rule_name%>_rule_data)
        ReRule.stub!(:find).and_return(re_rule)
      
        get :edit, :re_workflow_id => @re_workflow.id, :id => 1001, :rule_class_name => "RulesEngine::Rule::<%=rule_class%>"
        response.should have_selector("form#re_rule_edit_form") do |form|
          form.should have_selector("input#<%=rule_name%>_title", :value => 'Rule Title')     
          form.should have_selector("input#<%=rule_name%>_match_words_0_word", :value => 'word one')
          form.should have_selector("input#<%=rule_name%>_match_words_1_word", :value => 'word two')
          form.should have_selector("select#<%=rule_name%>_match_type") do |selector|
            selector.should have_selector("option", :content => "Any Match")
            selector.should have_selector("option", :content => "Exact Word") do |option|
              option.attr("selected").should_not be_nil
              option.attr("selected").value.should == "selected"
            end
            selector.should have_selector("option", :content => "Begins With")
            selector.should have_selector("option", :content => "End With")
          end  
        end  
      end
    end
  end
end