<commit_before># coding: utf-8

require 'spec_helper'

InteractionWithFilter = Class.new(TestInteraction) do
  float :thing
end

InteractionWithDateFilter = Class.new(TestInteraction) do
  date :thing
end

AddInteraction = Class.new(TestInteraction) do
  float :x, :y

  def execute
    x + y
  end
end

InterruptInteraction = Class.new(TestInteraction) do
  object :x, :y,
    class: Object,
    default: nil

  def execute
    compose(AddInteraction, inputs)
  end
end

describe ActiveInteraction::Base do
  include_context 'interactions'

  subject(:interaction) { described_class.new(inputs) }

  describe '.new(inputs = {})' do
    it 'does not allow :_interaction_* as an option' do
      key = :"_interaction_#{SecureRandom.hex}"
      inputs.merge!(key => nil)
      expect do
        interaction
      end.to raise_error ActiveInteraction::InvalidValueError
    end

    it 'does not allow "_interaction_*" as an option' do
      key = "_interaction_#{SecureRandom.hex}"
      inputs.merge!(key => nil)
      expect do
        interaction
      end.to raise_error ActiveInteraction::InvalidValueError
    end

    context 'with invalid inputs' do
      let(:inputs) { nil }

      it 'raises an error' do
        expect { interaction }.to raise_error ArgumentError
      end
    end

    context 'with a reader' do
      let(:described_class) do
        Class.new(TestInteraction) do
          attr_reader :thing

          validates :thing, presence: true
        end
      end

      context 'validation' do
        context 'failing' do
          it 'returns an invalid outcome' do
            expect(interaction).to be_invalid
          end
        end

        context 'passing' do
          before { inputs.merge!(thing: SecureRandom.hex) }

          it 'returns a valid outcome' do
            expect(interaction).to be_valid
          end
        end
      end

      context 'with a single input' do
        let(:thing) { SecureRandom.hex }
        before { inputs.merge!(thing: thing) }

        it 'sets the attribute' do
          expect(interaction.thing).to eql thing
        end
      end
    end

    context 'with a filter' do
      let(:described_class) { InteractionWithFilter }

      context 'validation' do
        context 'failing' do
          before { inputs.merge!(thing: thing) }

          context 'with an invalid value' do
            let(:thing) { 'a' }

            it 'sets the attribute to the filtered value' do
              expect(interaction.thing).to equal thing
            end
          end

          context 'without a value' do
            let(:thing) { nil }

            it 'sets the attribute to the filtered value' do
              expect(interaction.thing).to equal thing
            end
          end
        end

        context 'passing' do
          before { inputs.merge!(thing: 1) }

          it 'returns a valid outcome' do
            expect(interaction).to be_valid
          end
        end
      end

      context 'with a single input' do
        before { inputs.merge!(thing: 1) }

        it 'sets the attribute to the filtered value' do
          expect(interaction.thing).to eql 1.0
        end
      end

      context 'with multiple inputs' do
        let(:described_class) { InteractionWithDateFilter }
        let(:year) { 2012 }
        let(:month) { 1 }
        let(:day) { 2 }

        before do
          inputs.merge!(
            'thing(1i)' => year.to_s,
            'thing(2i)' => month.to_s,
            'thing(3i)' => day.to_s
          )
        end

        it 'returns a Date' do
          expect(interaction.thing).to eql Date.new(year, month, day)
        end
      end
    end
  end

  describe '.desc' do
    let(:desc) { SecureRandom.hex }

    it 'returns nil' do
      expect(described_class.desc).to be_nil
    end

    context 'with a description' do
      it 'returns the description' do
        expect(described_class.desc(desc)).to eql desc
      end

      it 'saves the description' do
        described_class.desc(desc)
        expect(described_class.desc).to eql desc
      end
    end
  end

  describe '.method_missing(filter_type, *args, &block)' do
    it 'raises an error for an invalid filter type' do
      expect do
        Class.new(TestInteraction) do
          not_a_valid_filter_type :thing
        end
      end.to raise_error NoMethodError
    end

    it do
      expect do
        Class.new(TestInteraction) do
          float :_interaction_thing
        end
      end.to raise_error ActiveInteraction::InvalidFilterError
    end

    context 'with a filter' do
      let(:described_class) { InteractionWithFilter }

      it 'adds an attr_reader' do
        expect(interaction).to respond_to :thing
      end

      it 'adds an attr_writer' do
        expect(interaction).to respond_to :thing=
      end
    end

    context 'with multiple filters' do
      let(:described_class) do
        Class.new(TestInteraction) do
          float :thing1, :thing2
        end
      end

      %w[thing1 thing2].each do |thing|
        it "adds an attr_reader for #{thing}" do
          expect(interaction).to respond_to thing
        end

        it "adds an attr_writer for #{thing}" do
          expect(interaction).to respond_to "#{thing}="
        end
      end
    end
  end

  context 'with a filter' do
    let(:described_class) { InteractionWithFilter }
    let(:thing) { rand }

    describe '.run(inputs = {})' do
      it "returns an instance of #{described_class}" do
        expect(outcome).to be_a described_class
      end

      context 'failing validations' do
        it 'returns an invalid outcome' do
          expect(outcome).to_not be_valid
        end

        it 'sets the result to nil' do
          expect(result).to be_nil
        end
      end

      context 'passing validations' do
        before { inputs.merge!(thing: thing) }

        context 'failing runtime validations' do
          before do
            @execute = described_class.instance_method(:execute)<commit_msg>Add a spec for redefinition warning<commit_after># coding: utf-8

require 'spec_helper'

InteractionWithFilter = Class.new(TestInteraction) do
  float :thing
end

InteractionWithDateFilter = Class.new(TestInteraction) do
  date :thing
end

AddInteraction = Class.new(TestInteraction) do
  float :x, :y

  def execute
    x + y
  end
end

InterruptInteraction = Class.new(TestInteraction) do
  object :x, :y,
    class: Object,
    default: nil

  def execute
    compose(AddInteraction, inputs)
  end
end

describe ActiveInteraction::Base do
  include_context 'interactions'

  subject(:interaction) { described_class.new(inputs) }

  describe '.new(inputs = {})' do
    it 'does not allow :_interaction_* as an option' do
      key = :"_interaction_#{SecureRandom.hex}"
      inputs.merge!(key => nil)
      expect do
        interaction
      end.to raise_error ActiveInteraction::InvalidValueError
    end

    it 'does not allow "_interaction_*" as an option' do
      key = "_interaction_#{SecureRandom.hex}"
      inputs.merge!(key => nil)
      expect do
        interaction
      end.to raise_error ActiveInteraction::InvalidValueError
    end

    context 'with invalid inputs' do
      let(:inputs) { nil }

      it 'raises an error' do
        expect { interaction }.to raise_error ArgumentError
      end
    end

    context 'with a reader' do
      let(:described_class) do
        Class.new(TestInteraction) do
          attr_reader :thing

          validates :thing, presence: true
        end
      end

      context 'validation' do
        context 'failing' do
          it 'returns an invalid outcome' do
            expect(interaction).to be_invalid
          end
        end

        context 'passing' do
          before { inputs.merge!(thing: SecureRandom.hex) }

          it 'returns a valid outcome' do
            expect(interaction).to be_valid
          end
        end
      end

      context 'with a single input' do
        let(:thing) { SecureRandom.hex }
        before { inputs.merge!(thing: thing) }

        it 'sets the attribute' do
          expect(interaction.thing).to eql thing
        end
      end
    end

    context 'with a filter' do
      let(:described_class) { InteractionWithFilter }

      context 'validation' do
        context 'failing' do
          before { inputs.merge!(thing: thing) }

          context 'with an invalid value' do
            let(:thing) { 'a' }

            it 'sets the attribute to the filtered value' do
              expect(interaction.thing).to equal thing
            end
          end

          context 'without a value' do
            let(:thing) { nil }

            it 'sets the attribute to the filtered value' do
              expect(interaction.thing).to equal thing
            end
          end
        end

        context 'passing' do
          before { inputs.merge!(thing: 1) }

          it 'returns a valid outcome' do
            expect(interaction).to be_valid
          end
        end
      end

      context 'with a single input' do
        before { inputs.merge!(thing: 1) }

        it 'sets the attribute to the filtered value' do
          expect(interaction.thing).to eql 1.0
        end
      end

      context 'with multiple inputs' do
        let(:described_class) { InteractionWithDateFilter }
        let(:year) { 2012 }
        let(:month) { 1 }
        let(:day) { 2 }

        before do
          inputs.merge!(
            'thing(1i)' => year.to_s,
            'thing(2i)' => month.to_s,
            'thing(3i)' => day.to_s
          )
        end

        it 'returns a Date' do
          expect(interaction.thing).to eql Date.new(year, month, day)
        end
      end
    end
  end

  describe '.desc' do
    let(:desc) { SecureRandom.hex }

    it 'returns nil' do
      expect(described_class.desc).to be_nil
    end

    context 'with a description' do
      it 'returns the description' do
        expect(described_class.desc(desc)).to eql desc
      end

      it 'saves the description' do
        described_class.desc(desc)
        expect(described_class.desc).to eql desc
      end
    end
  end

  describe '.method_missing(filter_type, *args, &block)' do
    it 'raises an error for an invalid filter type' do
      expect do
        Class.new(TestInteraction) do
          not_a_valid_filter_type :thing
        end
      end.to raise_error NoMethodError
    end

    it do
      expect do
        Class.new(TestInteraction) do
          float :_interaction_thing
        end
      end.to raise_error ActiveInteraction::InvalidFilterError
    end

    context 'with a filter' do
      let(:described_class) { InteractionWithFilter }

      it 'adds an attr_reader' do
        expect(interaction).to respond_to :thing
      end

      it 'adds an attr_writer' do
        expect(interaction).to respond_to :thing=
      end
    end

    context 'with multiple filters' do
      let(:described_class) do
        Class.new(TestInteraction) do
          float :thing1, :thing2
        end
      end

      %w[thing1 thing2].each do |thing|
        it "adds an attr_reader for #{thing}" do
          expect(interaction).to respond_to thing
        end

        it "adds an attr_writer for #{thing}" do
          expect(interaction).to respond_to "#{thing}="
        end
      end
    end
  end

  context 'with a filter' do
    let(:described_class) { InteractionWithFilter }
    let(:thing) { rand }

    it 'warns when redefining a filter' do
      klass = Class.new(described_class)
      expect(klass).to receive(:warn).with(/\AWARNING:/)
      klass.boolean :thing
    end

    describe '.run(inputs = {})' do
      it "returns an instance of #{described_class}" do
        expect(outcome).to be_a described_class
      end

      context 'failing validations' do
        it 'returns an invalid outcome' do
          expect(outcome).to_not be_valid
        end

        it 'sets the result to nil' do
          expect(result).to be_nil
        end
      end

      context 'passing validations' do
        before { inputs.merge!(thing: thing) }

        context 'failing runtime validations' do
          before do
            @execute = described_class.instance_method(:execute)
{'fraction_non_alphanumeric': 0.08015360732085955, 'fraction_numerical': 0.002941416782416864, 'mean_word_length': 2.006632277081798, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 13, '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': '5920070', 'n_tokens_mistral': 3559, 'n_tokens_neox': 3425, 'n_words': 1082}