Skip to content

Commit

Permalink
Add a rspec for operation builder.
Browse files Browse the repository at this point in the history
  • Loading branch information
Doug Youch committed May 27, 2010
1 parent 24a307a commit 1fe7a6a
Show file tree
Hide file tree
Showing 5 changed files with 170 additions and 2 deletions.
4 changes: 4 additions & 0 deletions app/models/user_segment.rb
Expand Up @@ -227,6 +227,10 @@ def to_expr
self.operations.to_expr
end

def to_builder
self.operations.to_builder
end

def after_create #:nodoc:all
self.market_segment = MarketSegment.create(:name => self.name ,:segment_type => 'user_segment',
:options => {:user_segment_id => self.id},
Expand Down
3 changes: 2 additions & 1 deletion app/models/user_segment/field_handler.rb
Expand Up @@ -23,7 +23,8 @@ def self.register_field(field, type, options={})

def self.handlers
([ self.get_handler_info(:user_segment, :fields, 'end_user_segment_field'),
self.get_handler_info(:user_segment, :fields, 'end_user_action_segment_field')] +
self.get_handler_info(:user_segment, :fields, 'end_user_action_segment_field'),
self.get_handler_info(:user_segment, :fields, 'end_user_tag_segment_field')] +
self.get_handler_info(:user_segment, :fields)).uniq
end
end
3 changes: 2 additions & 1 deletion app/models/user_segment/operation_builder.rb
Expand Up @@ -15,6 +15,7 @@ def condition_options

def validate
self.errors.add(:field, 'is invalid') unless self.user_segment_field.valid?
self.errors.add(:condition, 'is invalid') unless self.condition_options.rassoc(self.condition)
self.errors.add(:condition, 'is invalid') if ! self.condition.blank? && ! self.child_field.valid?
end

Expand All @@ -24,7 +25,7 @@ def build(opts={})
self.operation = opts[:operation]
self.condition = opts[:condition]
self.parent = opts[:parent]
unless self.field.blank?
unless self.operation_options.empty?
unless self.operation_options.rassoc(self.operation)
self.operation = self.operation_options[0][1]
@user_segment_field = nil
Expand Down
8 changes: 8 additions & 0 deletions spec/models/user_segment/field_spec.rb
Expand Up @@ -10,6 +10,14 @@
EndUser.push_target('test3@test.dev', :activated => false)
end

it "should be valid or invalid" do
@field = UserSegment::Field.new :field => 'created', :operation => 'before', :arguments => [1, 'days']
@field.valid?.should be_true

@field = UserSegment::Field.new :field => 'created', :operation => 'invalid_operation', :arguments => [1, 'days']
@field.valid?.should be_false
end

it "should be able to use handler" do
@field = UserSegment::Field.new :field => 'created', :operation => 'before', :arguments => [1, 'days']

Expand Down
154 changes: 154 additions & 0 deletions spec/models/user_segment/operation_builder_spec.rb
@@ -0,0 +1,154 @@
require File.dirname(__FILE__) + "/../../spec_helper"

describe UserSegment::OperationBuilder do

reset_domain_tables :user_segments

def build(opts=nil)
@builder = UserSegment::OperationBuilder.new nil
@builder.build(opts) if opts
@builder
end

def segment
@segment = UserSegment.create :name => 'Test', :segment_type => 'filtered', :segment_options_text => @builder.to_expr
end

it "should be valid or invalid" do
build.valid?.should be_false
build(:field => 'email', :operation => 'is', :argument0 => 'test@test.dev').valid?.should be_true
segment.valid?.should be_true

# if the field is invalid the builder is invalid
build(:field => 'invalid_email_field', :operation => 'is', :argument0 => 'test@test.dev').valid?.should be_false

# if the operation is invalid for the field it will set it to the first operation
build(:field => 'email', :operation => 'invalid_operation', :argument0 => 'test@test.dev').valid?.should be_true
@builder.operation.should == 'is'
segment.valid?.should be_true

# if the operation is missing an argument then the builder is invalid
build(:field => 'email', :operation => 'is', :argument0 => nil).valid?.should be_false

# setting the condition without the child invalidates the builder
build(:field => 'email', :operation => 'is', :argument0 => 'test@test.dev', :condition => 'and').valid?.should be_false

build(:field => 'email', :operation => 'is', :argument0 => 'test@test.dev', :condition => 'and', :child => {:field => 'created', :operation => 'since', :argument0 => '2', :argument1 => 'days'}).valid?.should be_true
segment.valid?.should be_true
end

it "should not allow invalid and conditions" do
build(:field => 'user_action', :operation => 'is', :argument0 => '/editor/auth/login').valid?.should be_true
segment.valid?.should be_true
build(:field => 'user_action', :operation => 'is', :argument0 => '/editor/auth/login', :condition => 'and', :child => {:field => 'email', :operation => 'is', :argument0 => 'test@test.dev'}).valid?.should be_false
build(:field => 'user_action', :operation => 'is', :argument0 => '/editor/auth/login', :condition => 'and', :child => {:field => 'occurred', :operation => 'before', :argument0 => '2', :argument1 => 'days'}).valid?.should be_true
segment.valid?.should be_true

build(:field => 'user_action', :operation => 'is', :argument0 => '/editor/auth/login', :condition => 'blah', :child => {:field => 'occurred', :operation => 'before', :argument0 => '2', :argument1 => 'days'}).valid?.should be_false
end

it "should or conditions" do
build(:field => 'user_action', :operation => 'is', :argument0 => '/editor/auth/login').valid?.should be_true
segment.valid?.should be_true
build(:field => 'user_action', :operation => 'is', :argument0 => '/editor/auth/login', :condition => 'or', :child => {:field => 'email', :operation => 'is', :argument0 => 'test@test.dev'}).valid?.should be_true
segment.valid?.should be_true
build(:field => 'user_action', :operation => 'is', :argument0 => '/editor/auth/login', :condition => 'or', :child => {:field => 'occurred', :operation => 'before', :argument0 => '2', :argument1 => 'days'}).valid?.should be_true
segment.valid?.should be_true
end

it "should with conditions" do
build(:field => 'user_action', :operation => 'is', :argument0 => '/editor/auth/login').valid?.should be_true
segment.valid?.should be_true
build(:field => 'user_action', :operation => 'is', :argument0 => '/editor/auth/login', :condition => 'with', :child => {:field => 'email', :operation => 'is', :argument0 => 'test@test.dev'}).valid?.should be_true
segment.valid?.should be_true
build(:field => 'user_action', :operation => 'is', :argument0 => '/editor/auth/login', :condition => 'with', :child => {:field => 'occurred', :operation => 'before', :argument0 => '2', :argument1 => 'days'}).valid?.should be_true
segment.valid?.should be_true
end

it "should write output valid expression text" do
build(:field => 'email', :operation => 'is', :argument0 => 'test@test.dev').valid?.should be_true
@builder.to_expr.should == 'email.is("test@test.dev")'
segment.valid?.should be_true

build(:field => 'user_action', :operation => 'is', :argument0 => '/editor/auth/login', :condition => 'and', :child => {:field => 'occurred', :operation => 'before', :argument0 => '2', :argument1 => 'days'}).valid?.should be_true
@builder.to_expr.should == 'user_action.is("/editor/auth/login").occurred.before(2, "days")'
segment.valid?.should be_true

build(:field => 'user_action', :operation => 'is', :argument0 => '/editor/auth/login', :condition => 'or', :child => {:field => 'email', :operation => 'is', :argument0 => 'test@test.dev'}).valid?.should be_true
@builder.to_expr.should == 'user_action.is("/editor/auth/login") + email.is("test@test.dev")'
segment.valid?.should be_true

build(:field => 'user_action', :operation => 'is', :argument0 => '/editor/auth/login', :condition => 'with', :child => {:field => 'email', :operation => 'is', :argument0 => 'test@test.dev'}).valid?.should be_true
@builder.to_expr.should == "user_action.is(\"/editor/auth/login\")\nemail.is(\"test@test.dev\")"
segment.valid?.should be_true

build(:field => 'user_action', :operation => 'is', :argument0 => '/editor/auth/login', :condition => 'with', :child => {:field => 'email', :operation => 'is', :argument0 => 'test@test.dev', :condition => 'with', :child => {:field => 'user_action', :operation => 'is', :argument0 => '/editor/auth/login', :condition => 'and', :child => {:field => 'occurred', :operation => 'before', :argument0 => '2', :argument1 => 'days', :condition => 'or', :child => {:field => 'user_action', :operation => 'is', :argument0 => '/editor/auth/login', :condition => 'or', :child => {:field => 'email', :operation => 'is', :argument0 => 'test@test.dev'}}}}}).valid?.should be_true
@builder.to_expr.should == "user_action.is(\"/editor/auth/login\")\nemail.is(\"test@test.dev\")\nuser_action.is(\"/editor/auth/login\").occurred.before(2, \"days\") + user_action.is(\"/editor/auth/login\") + email.is(\"test@test.dev\")"
segment.valid?.should be_true
end

it "should have valid prebuilt filters" do
UserSegment::OperationBuilder.prebuilt_filters.each do |name, options|
build(options).valid?.should be_true
segment.valid?.should be_true
end
end

it "should handle Time arguments" do
build(:field => 'created', :operation => 'between', :argument0 => '1/2/2010', :argument1 => '2/2/2010').valid?.should be_true
@builder.argument0.should == '01/02/2010 00:00:00'
@builder.argument1.should == '02/02/2010 00:00:00'
@builder.to_expr.should == 'created.between("01/02/2010 00:00:00", "02/02/2010 00:00:00")'
segment.valid?.should be_true
end

it "should handle the not operator" do
build(:operator => 'not', :field => 'user_action', :operation => 'is', :argument0 => '/editor/auth/login', :condition => 'with', :child => {:field => 'email', :operation => 'is', :argument0 => 'test@test.dev'}).valid?.should be_true
@builder.to_expr.should == "not user_action.is(\"/editor/auth/login\")\nemail.is(\"test@test.dev\")"
segment.valid?.should be_true

build(:operator => '', :field => 'user_action', :operation => 'is', :argument0 => '/editor/auth/login', :condition => 'with', :child => {:operator => 'not', :field => 'email', :operation => 'is', :argument0 => 'test@test.dev'}).valid?.should be_true
@builder.to_expr.should == "user_action.is(\"/editor/auth/login\")\nnot email.is(\"test@test.dev\")"
segment.valid?.should be_true

build(:operator => 'not', :field => 'user_action', :operation => 'is', :argument0 => '/editor/auth/login', :condition => 'with', :child => {:operator => 'not', :field => 'email', :operation => 'is', :argument0 => 'test@test.dev'}).valid?.should be_true
@builder.to_expr.should == "not user_action.is(\"/editor/auth/login\")\nnot email.is(\"test@test.dev\")"
segment.valid?.should be_true

build(:operator => 'not', :field => 'user_action', :operation => 'is', :argument0 => '/editor/auth/login', :condition => 'or', :child => {:field => 'email', :operation => 'is', :argument0 => 'test@test.dev'}).valid?.should be_true
@builder.to_expr.should == "not user_action.is(\"/editor/auth/login\") + email.is(\"test@test.dev\")"
segment.valid?.should be_true
end

it "should be able to create a builder from a user segment" do
user_segment = UserSegment.create :name => 'Test', :segment_type => 'filtered', :segment_options_text => "user_action.is( \"/editor/auth/login\" )\nemail.is(\"test@test.dev\") \n user_action.is(\"/editor/auth/login\").occurred.before( 2, 'days' ).created.since(3,'months') + user_action.is(\"/editor/auth/login\") + email.is(\"test@test.dev\" )\nnot created.before( 3, 'years')"
user_segment.valid?.should be_true
build(user_segment.to_builder).valid?.should be_true

@builder.to_expr.should == "user_action.is(\"/editor/auth/login\")\nemail.is(\"test@test.dev\")\nuser_action.is(\"/editor/auth/login\").occurred.before(2, \"days\").created.since(3, \"months\") + user_action.is(\"/editor/auth/login\") + email.is(\"test@test.dev\")\nnot created.before(3, \"years\")"

@builder.to_expr.should == user_segment.to_expr

@builder.condition.should == 'with'
@builder.child_field.field.should == 'email'

@builder.child_field.condition.should == 'with'
@builder.child_field.child_field.field.should == 'user_action'

@builder.child_field.child_field.condition.should == 'and'
@builder.child_field.child_field.child_field.field.should == 'occurred'

@builder.child_field.child_field.child_field.condition.should == 'and'
@builder.child_field.child_field.child_field.child_field.field.should == 'created'

@builder.child_field.child_field.child_field.child_field.condition.should == 'or'
@builder.child_field.child_field.child_field.child_field.child_field.field.should == 'user_action'

@builder.child_field.child_field.child_field.child_field.child_field.condition.should == 'or'
@builder.child_field.child_field.child_field.child_field.child_field.child_field.field.should == 'email'

@builder.child_field.child_field.child_field.child_field.child_field.child_field.condition.should == 'with'
@builder.child_field.child_field.child_field.child_field.child_field.child_field.child_field.field.should == 'created'
@builder.child_field.child_field.child_field.child_field.child_field.child_field.child_field.operator.should == 'not'
end
end

0 comments on commit 1fe7a6a

Please sign in to comment.