<commit_before>require 'spec_helper'

describe Locomotive::ContentType do

  before(:each) do
    Locomotive::Site.any_instance.stubs(:create_default_pages!).returns(true)
  end

  context 'when validating' do

    it 'should have a valid factory' do
      content_type = FactoryGirl.build(:content_type)
      content_type.entries_custom_fields.build label: 'anything', type: 'string'
      content_type.should be_valid
    end

    # Validations ##

    %w{site name}.each do |field|
      it "requires the presence of #{field}" do
        content_type = FactoryGirl.build(:content_type, field.to_sym => nil)
        content_type.should_not be_valid
        content_type.errors[field.to_sym].should == ["can't be blank"]
      end
    end

    it 'requires the presence of slug' do
      content_type = FactoryGirl.build(:content_type, name: nil, slug: nil)
      content_type.should_not be_valid
      content_type.errors[:slug].should == ["can't be blank"]
    end

    it 'is not valid if slug is not unique' do
      content_type = FactoryGirl.build(:content_type)
      content_type.entries_custom_fields.build label: 'anything', type: 'string'
      content_type.save
      (content_type = FactoryGirl.build(:content_type, site: content_type.site,
        slug: content_type.slug)).should_not be_valid
      content_type.errors[:slug].should == ["is already taken"]
    end

    it 'is not valid if there is not at least one field' do
      content_type = FactoryGirl.build(:content_type)
      content_type.should_not be_valid
      content_type.errors[:entries_custom_fields].should == { base: ['At least, one custom field is required'] }
    end

    %w(created_at updated_at).each do |name|
      it "does not allow #{name} as name" do
        content_type = FactoryGirl.build(:content_type)
        field = content_type.entries_custom_fields.build label: 'anything', type: 'string', name: name
        field.valid?.should be_false
        field.errors[:name].should == ['is reserved']
      end
    end

    it 'sets a slug from the name before the validation' do
      content_type = FactoryGirl.build(:content_type, name: 'my content Type')
      content_type.valid?
      content_type.slug.should match /slug_of_content_type_/
    end

    it 'make sure the slug is correctly set before the validation' do
      content_type = FactoryGirl.build(:content_type, slug: 'my content-type')
      content_type.valid?
      content_type.slug.should == 'my_content_type'
    end

  end

  context '#ordered_entries' do

    before(:each) do
      (@content_type = build_content_type(order_by: 'created_at')).save
      @content_2 = @content_type.entries.create name: 'Sacha'
      @content_1 = @content_type.entries.create name: 'Did'
    end

    it 'orders with the ASC direction by default' do
      @content_type.order_direction.should == 'asc'
    end

    it 'has a getter for manual order' do
      @content_type.order_manually?.should == false
      @content_type.order_by = '_position'
      @content_type.order_manually?.should == true
    end

    it 'returns a list of entries ordered manually' do
      @content_type.order_by = '_position'
      @content_type.ordered_entries.collect(&:name).should == %w(Sacha Did)
    end

    it 'returns a list of entries ordered by a column specified by order_by (ASC)' do
      @content_type.order_by = @content_type.entries_custom_fields.where(name: 'name').first._id
      @content_type.ordered_entries.collect(&:name).should == %w(Did Sacha)
    end

    it 'returns a list of entries ordered by a column specified by order_by (DESC)' do
      @content_type.order_by = @content_type.entries_custom_fields.where(name: 'name').first._id
      @content_type.order_direction = 'desc'
      @content_type.ordered_entries.collect(&:name).should == %w(Sacha Did)
    end

    it 'returns a list of contents ordered through condition {order_by: "name asc"}' do
      @content_type.order_by = @content_type.entries_custom_fields.where(name: 'name').first._id
      @content_type.order_direction = 'desc'
      @content_type.ordered_entries(order_by: 'name asc').collect(&:name).should == %w(Did Sacha)
    end

    it 'returns a list of entries ordered by a Date column when first instance is missing the value' do
      @content_type.order_by = @content_type.entries_custom_fields.where(name: 'active_at').first._id
      @content_2.update_attribute :active_at, Date.parse('01/01/2001')
      content_3 = @content_type.entries.create name: 'Mario', active_at: Date.parse('02/02/2001')

      @content_type.ordered_entries.map(&:active_at).should == [nil, Date.parse('01/01/2001'), Date.parse('02/02/2001')]

      @content_type.order_direction = 'desc'
      @content_type.ordered_entries.map(&:active_at).should == [Date.parse('02/02/2001'), Date.parse('01/01/2001'), nil]
    end

  end

  describe 'belongs_to/has_many relationship' do

    before(:each) do
      build_belongs_to_has_many_relationship

      @category_1 = @category_content_type.entries.create name: 'Gems'
      @category_2 = @category_content_type.entries.create name: 'Service'

      @content_1 = @content_type.entries.create name: 'Github',        category: @category_2
      @content_2 = @content_type.entries.create name: 'LocomotiveCMS', category: @category_1, description: 'Lorem ipsum',  _position_in_category: 1
      @content_3 = @content_type.entries.create name: 'RubyOnRails',   category: @category_1, description: 'Zzzzzz',       _position_in_category: 2
    end

    context '#ordering in a belongs_to/has_many relationship' do

      it 'orders projects based on the default order of the Project content type' do
        @category_1.projects.metadata.order.should == %w(name desc)
        @category_1.projects.map(&:name).should == %w(RubyOnRails LocomotiveCMS)
        @category_1.projects.ordered.all.map(&:name).should == %w(RubyOnRails LocomotiveCMS)
      end

      it 'updates the information about the order of a has_many relationship if the target class changes its order' do
        @content_type.order_by = 'description'; @content_type.order_direction = 'ASC'; @content_type.save!
        @category_1 = safe_find(@category_1.class, @category_1._id)

        @category_1.projects.metadata.order.should == %w(description ASC)
        @category_1.projects.map(&:name).should == %w(LocomotiveCMS RubyOnRails)
      end

      it 'uses the order by position if the UI option is enabled' do
        field = @category_content_type.entries_custom_fields.where(name: 'projects').first
        field.ui_enabled = true;

        @category_content_type.save!; @category_1 = safe_find(@category_1.class, @category_1._id)

        @category_1.projects.metadata.order.to_s.should == 'position_in_category'
        @category_1.projects.map(&:name).should == %w(LocomotiveCMS RubyOnRails)
      end

    end

    context '#group_by belongs_to field' do

      it 'groups entries' do
        groups = @content_type.send(:group_by_belongs_to_field, @content_type.group_by_field)

        groups.map { |h| h[:name] }.should == %w(Gems Service)

        groups.first[:entries].map(&:name).should == %w(RubyOnRails LocomotiveCMS)
        groups.last[:entries].map(&:name).should == %w(Github)
      end

      it 'groups entries with a different columns order' do
        @category_content_type.update_attributes order_by: @category_content_type.entries_custom_fields.first._id, order_direction: 'desc'
        groups = @content_type.send(:group_by_belongs_to_field, @content_type.group_by_field)
<commit_msg>use public API instead of private<commit_after>require 'spec_helper'

describe Locomotive::ContentType do

  before(:each) do
    Locomotive::Site.any_instance.stubs(:create_default_pages!).returns(true)
  end

  context 'when validating' do

    it 'should have a valid factory' do
      content_type = FactoryGirl.build(:content_type)
      content_type.entries_custom_fields.build label: 'anything', type: 'string'
      content_type.should be_valid
    end

    # Validations ##

    %w{site name}.each do |field|
      it "requires the presence of #{field}" do
        content_type = FactoryGirl.build(:content_type, field.to_sym => nil)
        content_type.should_not be_valid
        content_type.errors[field.to_sym].should == ["can't be blank"]
      end
    end

    it 'requires the presence of slug' do
      content_type = FactoryGirl.build(:content_type, name: nil, slug: nil)
      content_type.should_not be_valid
      content_type.errors[:slug].should == ["can't be blank"]
    end

    it 'is not valid if slug is not unique' do
      content_type = FactoryGirl.build(:content_type)
      content_type.entries_custom_fields.build label: 'anything', type: 'string'
      content_type.save
      (content_type = FactoryGirl.build(:content_type, site: content_type.site,
        slug: content_type.slug)).should_not be_valid
      content_type.errors[:slug].should == ["is already taken"]
    end

    it 'is not valid if there is not at least one field' do
      content_type = FactoryGirl.build(:content_type)
      content_type.should_not be_valid
      content_type.errors[:entries_custom_fields].should == { base: ['At least, one custom field is required'] }
    end

    %w(created_at updated_at).each do |name|
      it "does not allow #{name} as name" do
        content_type = FactoryGirl.build(:content_type)
        field = content_type.entries_custom_fields.build label: 'anything', type: 'string', name: name
        field.valid?.should be_false
        field.errors[:name].should == ['is reserved']
      end
    end

    it 'sets a slug from the name before the validation' do
      content_type = FactoryGirl.build(:content_type, name: 'my content Type')
      content_type.valid?
      content_type.slug.should match /slug_of_content_type_/
    end

    it 'make sure the slug is correctly set before the validation' do
      content_type = FactoryGirl.build(:content_type, slug: 'my content-type')
      content_type.valid?
      content_type.slug.should == 'my_content_type'
    end

  end

  context '#ordered_entries' do

    before(:each) do
      (@content_type = build_content_type(order_by: 'created_at')).save
      @content_2 = @content_type.entries.create name: 'Sacha'
      @content_1 = @content_type.entries.create name: 'Did'
    end

    it 'orders with the ASC direction by default' do
      @content_type.order_direction.should == 'asc'
    end

    it 'has a getter for manual order' do
      @content_type.order_manually?.should == false
      @content_type.order_by = '_position'
      @content_type.order_manually?.should == true
    end

    it 'returns a list of entries ordered manually' do
      @content_type.order_by = '_position'
      @content_type.ordered_entries.collect(&:name).should == %w(Sacha Did)
    end

    it 'returns a list of entries ordered by a column specified by order_by (ASC)' do
      @content_type.order_by = @content_type.entries_custom_fields.where(name: 'name').first._id
      @content_type.ordered_entries.collect(&:name).should == %w(Did Sacha)
    end

    it 'returns a list of entries ordered by a column specified by order_by (DESC)' do
      @content_type.order_by = @content_type.entries_custom_fields.where(name: 'name').first._id
      @content_type.order_direction = 'desc'
      @content_type.ordered_entries.collect(&:name).should == %w(Sacha Did)
    end

    it 'returns a list of contents ordered through condition {order_by: "name asc"}' do
      @content_type.order_by = @content_type.entries_custom_fields.where(name: 'name').first._id
      @content_type.order_direction = 'desc'
      @content_type.ordered_entries(order_by: 'name asc').collect(&:name).should == %w(Did Sacha)
    end

    it 'returns a list of entries ordered by a Date column when first instance is missing the value' do
      @content_type.order_by = @content_type.entries_custom_fields.where(name: 'active_at').first._id
      @content_2.update_attribute :active_at, Date.parse('01/01/2001')
      content_3 = @content_type.entries.create name: 'Mario', active_at: Date.parse('02/02/2001')

      @content_type.ordered_entries.map(&:active_at).should == [nil, Date.parse('01/01/2001'), Date.parse('02/02/2001')]

      @content_type.order_direction = 'desc'
      @content_type.ordered_entries.map(&:active_at).should == [Date.parse('02/02/2001'), Date.parse('01/01/2001'), nil]
    end

  end

  describe 'belongs_to/has_many relationship' do

    before(:each) do
      build_belongs_to_has_many_relationship

      @category_1 = @category_content_type.entries.create name: 'Gems'
      @category_2 = @category_content_type.entries.create name: 'Service'

      @content_1 = @content_type.entries.create name: 'Github',        category: @category_2
      @content_2 = @content_type.entries.create name: 'LocomotiveCMS', category: @category_1, description: 'Lorem ipsum',  _position_in_category: 1
      @content_3 = @content_type.entries.create name: 'RubyOnRails',   category: @category_1, description: 'Zzzzzz',       _position_in_category: 2
    end

    context '#ordering in a belongs_to/has_many relationship' do

      it 'orders projects based on the default order of the Project content type' do
        @category_1.projects.relation_metadata.order.should == %w(name desc)
        @category_1.projects.sort.map(&:name).should == %w(RubyOnRails LocomotiveCMS).sort
        @category_1.projects.ordered.all.map(&:name).should == %w(RubyOnRails LocomotiveCMS)
      end

      it 'updates the information about the order of a has_many relationship if the target class changes its order' do
        @content_type.order_by = 'description'; @content_type.order_direction = 'ASC'; @content_type.save!
        @category_1 = safe_find(@category_1.class, @category_1._id)

        @category_1.projects.relation_metadata.order.should == %w(description ASC)
        @category_1.projects.map(&:name).should == %w(LocomotiveCMS RubyOnRails)
      end

      it 'uses the order by position if the UI option is enabled' do
        field = @category_content_type.entries_custom_fields.where(name: 'projects').first
        field.ui_enabled = true;

        @category_content_type.save!; @category_1 = safe_find(@category_1.class, @category_1._id)

        @category_1.projects.relation_metadata.order.to_s.should == 'position_in_category'
        @category_1.projects.map(&:name).should == %w(LocomotiveCMS RubyOnRails)
      end

    end

    context '#group_by belongs_to field' do

      it 'groups entries' do
        groups = @content_type.send(:group_by_belongs_to_field, @content_type.group_by_field)

        groups.map { |h| h[:name] }.should == %w(Gems Service)

        groups.first[:entries].map(&:name).should == %w(RubyOnRails LocomotiveCMS)
        groups.last[:entries].map(&:name).should == %w(Github)
      end

      it 'groups entries with a different columns order' do
        @category_content_type.update_attributes order_by: @category_content_type.entries_custom_fields.first._id, order_direction: 'desc'
        groups = @content_type.send(:group_by_belongs_to_field, @content_type.group_by_field)

{'fraction_non_alphanumeric': 0.1092398124298263, 'fraction_numerical': 0.009906875371507827, 'mean_word_length': 3.656211562115621, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3822359', 'n_tokens_mistral': 4829, 'n_tokens_neox': 4606, 'n_words': 1113}