
#
# CBRAIN Project
#
# Copyright (C) 2008-2012
# The Royal Institution for the Advancement of Learning
# McGill University
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#

require 'rails_helper'

describe TaskCustomFilter do
  let(:filter)  {create(:task_custom_filter)}
  let(:task_scope) { double("task_scope").as_null_object }

  let(:user1)     { create(:normal_user) }
  let(:user2)     { create(:normal_user) }
  let(:bourreau1) { create(:bourreau) }
  let(:bourreau2) { create(:bourreau) }

  let(:cbrain_task1) {
    create(:cbrain_task, :description => "desc1", :user_id => user1.id, :bourreau_id => bourreau1.id,
                    :created_at => "2011-04-04", :status => "New",
                    :updated_at => "2011-05-04")
  }

  let(:cbrain_task2) {
    create(:cbrain_task, :description => "desc2", :user_id => user2.id, :bourreau_id => bourreau2.id,
                    :created_at => "2011-04-29", :status => "Completed",
                    :updated_at => "2011-05-29")
  }

  describe "#filter_scope" do
    it "should scope type if type filter given" do
      filter.data = { :types => [ "CbrainTask::Diagnostics" ] }
      expect(filter).to receive(:scope_types).and_return(task_scope)
      filter.filter_scope(task_scope)
    end

    it "should not scope type if type filter not given" do
      expect(filter).not_to receive(:scope_types)
      filter.filter_scope(task_scope)
    end

    it "should filter tasks by user_ids" do
      filter.data = { :user_ids => [ cbrain_task1.user_id.to_s ] }
      expect(filter.filter_scope(CbrainTask.where(nil))).to match_array([cbrain_task1])
    end

    it "should filter tasks by bourreau_ids" do
      filter.data = { :bourreau_id => [ cbrain_task1.bourreau_id.to_s ] }
      expect(filter.filter_scope(CbrainTask.where(nil))).to match_array([cbrain_task1])
    end

    it "should filter tasks by status" do
      filter.data = { :status => [ cbrain_task1.status ] }
      expect(filter.filter_scope(CbrainTask.where(nil))).to match_array([cbrain_task1])
    end

    context "with date" do

      it "should only keep task created between 'data[:absolute_from] and 'data[:absolute_to]'" do
        filter.data = { :date_attribute => "created_at", :absolute_or_relative_from=>"absolute", :absolute_or_relative_to=>"absolute", :absolute_from => "04/04/2011", :absolute_to => "04/04/2011" }
        expect(filter.filter_scope(CbrainTask.where(nil))).to match_array([cbrain_task1])
      end

      it "should only keep task updates between 'data[:absolute_from] and 'data[:absolute_to]'" do
        filter.data = { :date_attribute => "updated_at", :absolute_or_relative_from=>"absolute", :absolute_or_relative_to=>"absolute", :absolute_from => "04/05/2011", :absolute_to => "04/05/2011" }
        expect(filter.filter_scope(CbrainTask.where(nil))).to match_array([cbrain_task1])
      end

      it "should only keep task created between 'data[:absolute_from] and 'data[:relative_date_to]'" do
        filter.data = { :date_attribute => "created_at", :absolute_or_relative_from=>"absolute", :absolute_or_relative_to=>"relative", :absolute_from => "29/04/2011", :relative_to => "0" }
        expect(filter.filter_scope(CbrainTask.where(nil))).to match_array([cbrain_task2])
      end

      it "should only keep task updated between 'data[:absolute_from] and 'data[:relative_date_to]'" do
        filter.data = { :date_attribute => "updated_at", :absolute_or_relative_from=>"absolute", :absolute_or_relative_to=>"relative", :absolute_from => "29/05/2011", :relative_to => "0" }
        expect(filter.filter_scope(CbrainTask.where(nil))).to match_array([cbrain_task2])
      end

      it "should only keep task updated last week" do
        filter.data = { :date_attribute => "updated_at", :absolute_or_relative_from=>"relative", :absolute_or_relative_to=>"relative", :relative_from => "#{1.week}", :relative_to => "0" }
        cbrain_task1.updated_at = Date.today - 1.day
        cbrain_task1.save!
        expect(filter.filter_scope(CbrainTask.where(nil))).to match_array([cbrain_task1])
      end

    end

    context "with description scope" do
      it "should remove all task doesn't match with 'data[:description_term]'" do
        filter.data = { :description_type => "match", :description_term => cbrain_task1.description }
        expect(filter.filter_scope(CbrainTask.where(nil))).to match_array([cbrain_task1])
      end

      it "should remove all task doesn't begin with 'data[:description_term]'" do
        filter.data = { :description_type => "begin", :description_term => cbrain_task1.description[0..2] }
        expect(filter.filter_scope(CbrainTask.where(nil))).to match_array([cbrain_task1,cbrain_task2])
      end

      it "should remove all task doesn't end with 'data[:description_term]'" do
        filter.data = { :description_type => "end", :description_term => cbrain_task1.description[-1].chr }
        expect(filter.filter_scope(CbrainTask.where(nil))).to match_array([cbrain_task1])
      end

      it "should remove all task doesn't contain 'data[:description_term]'" do
        filter.data = { :description_type => "contain", :description_term => cbrain_task1.description[1..3] }
        expect(filter.filter_scope(CbrainTask.where(nil))).to match_array([cbrain_task1,cbrain_task2])
      end
    end
  end

end

