<commit_before>require 'spec_helper'
require 'test_doubles'

RSpec.describe LightService::Organizer do
  class TestWithCallback
    extend LightService::Organizer

    def self.call(context = {})
      with(context).reduce(actions)
    end

    def self.actions
      [
        SetUpContextAction,
        with_callback(IterateCollectionAction,
                      [IncrementCountAction,
                       AddToTotalAction])
      ]
    end
  end

  class SetUpContextAction
    extend LightService::Action
    promises :numbers, :counter, :total

    executed do |ctx|
      ctx.numbers = [1, 2, 3]
      ctx.counter = 0
      ctx.total = 0
    end
  end

  class IterateCollectionAction
    extend LightService::Action
    expects :numbers, :callback
    promises :number

    executed do |ctx|
      ctx.numbers.each do |number|
        ctx.number = number
        ctx.callback.call(ctx)
      end
    end
  end

  class IncrementCountAction
    extend LightService::Action
    expects :counter

    executed do |ctx|
      ctx.counter = ctx.counter + 1
    end
  end

  class AddToTotalAction
    extend LightService::Action
    expects :number, :total

    executed do |ctx|
      ctx.total += ctx.number
    end
  end

  describe 'a simple case with a single callback' do
    it 'calls the actions defined with callback' do
      TestWithCallback.before_action = [
        lambda do |ctx|
          ctx.total -= 1000 if ctx.current_action == AddToTotalAction
        end
      ]
      result = TestWithCallback.call

      expect(result.counter).to eq(3)
      expect(result.total).to eq(-2994)
    end
  end

  describe 'before_action' do
    it 'can interact with actions from the outside' do
    end
  end

  describe 'a more complex example with nested callbacks' do
    class TestWithNestedCallback
      extend LightService::Organizer

      def self.call(context = {})
        with(context).reduce(actions)
      end

      def self.actions
        [
          SetUpNestedContextAction,
          with_callback(IterateOuterCollectionAction,
                        [IncrementOuterCountAction,
                         with_callback(IterateCollectionAction,<commit_msg>Raise error to abort processing at a specific action<commit_after>require 'spec_helper'
require 'test_doubles'

RSpec.describe LightService::Organizer do
  class TestWithCallback
    extend LightService::Organizer

    def self.call(context = {})
      with(context).reduce(actions)
    end

    def self.actions
      [
        SetUpContextAction,
        with_callback(IterateCollectionAction,
                      [IncrementCountAction,
                       AddToTotalAction])
      ]
    end
  end

  class SetUpContextAction
    extend LightService::Action
    promises :numbers, :counter, :total

    executed do |ctx|
      ctx.numbers = [1, 2, 3]
      ctx.counter = 0
      ctx.total = 0
    end
  end

  class IterateCollectionAction
    extend LightService::Action
    expects :numbers, :callback
    promises :number

    executed do |ctx|
      ctx.numbers.each do |number|
        ctx.number = number
        ctx.callback.call(ctx)
      end
    end
  end

  class IncrementCountAction
    extend LightService::Action
    expects :counter

    executed do |ctx|
      ctx.counter = ctx.counter + 1
    end
  end

  class AddToTotalAction
    extend LightService::Action
    expects :number, :total

    executed do |ctx|
      ctx.total += ctx.number
    end
  end

  describe 'a simple case with a single callback' do
    it 'calls the actions defined with callback' do
      result = TestWithCallback.call

      expect(result.counter).to eq(3)
      expect(result.total).to eq(6)
    end
  end

  describe 'before_action' do
    it 'can interact with actions from the outside' do
      TestWithCallback.before_action = [
        lambda do |ctx|
          ctx.total -= 1000 if ctx.current_action == AddToTotalAction
        end
      ]
      result = TestWithCallback.call

      expect(result.counter).to eq(3)
      expect(result.total).to eq(-2994)
    end
  end

  describe 'when the hook breaks execution' do
    it 'does not call the rest of the callback steps' do
      class SkipContextError < StandardError
        attr_reader :ctx

        def initialize(msg, ctx)
          @ctx = ctx
          super(msg)
        end
      end
      TestWithCallback.before_action = [
        lambda do |ctx|
          if ctx.current_action == IncrementCountAction
            ctx.total -= 1000
            raise SkipContextError.new("stop context now", ctx)
          end
        end
      ]
      begin
        result = TestWithCallback.call
      rescue SkipContextError => e
        expect(e.ctx).not_to be_empty
      end
    end
  end

  describe 'a more complex example with nested callbacks' do
    class TestWithNestedCallback
      extend LightService::Organizer

      def self.call(context = {})
        with(context).reduce(actions)
      end

      def self.actions
        [
          SetUpNestedContextAction,
          with_callback(IterateOuterCollectionAction,
                        [IncrementOuterCountAction,
                         with_callback(IterateCollectionAction,
{'fraction_non_alphanumeric': 0.06753896478737734, 'fraction_numerical': 0.00692707331152588, 'mean_word_length': 2.1870018393623543, 'pattern_counts': {'":': 0, '<': 4, '<?xml version=': 0, '>': 4, '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': '5518853', 'n_tokens_mistral': 1474, 'n_tokens_neox': 1417, 'n_words': 401}