# frozen_string_literal: true

RSpec.describe CallbackHell, "with association-caused callbacks" do
  subject(:foo) { CallbackHell::Collector.new(Foo, mode: :full).collect }
  subject(:bar) { CallbackHell::Collector.new(Bar, mode: :full).collect }

  it "has collection saving-related callbacks" do
    expect(foo).to have_callback(
      callback_name: :after_create,
      method_name: :autosave_associated_records_for_bars,
      association_generated: true, origin: :rails
    )
    expect(foo).to have_callback(
      callback_name: :after_update,
      method_name: :autosave_associated_records_for_bars,
      association_generated: true, origin: :rails
    )
    expect(foo).to have_callback(
      callback_name: :around_save,
      method_name: :around_save_collection_association,
      association_generated: true, origin: :rails
    )

    expect(bar).to have_callback(
      callback_name: :before_save,
      method_name: :autosave_associated_records_for_foo,
      association_generated: true, origin: :rails
    )
  end

  it "correctly marks the validations generated by associations" do
    expect(foo).to have_validation(
      type: :associated,
      method_name: :validate_associated_records_for_bars,
      origin: :rails,
      association_generated: true
    )

    expect(bar).to have_validation(
      type: :associated,
      human_method_name: /^Presence.*\(foo\)/,
      origin: :rails,
      association_generated: true
    )
  end

  it "has a dependent: destroy callback" do
    expect(foo).to have_callback(
      callback_name: :before_destroy,
      association_generated: true, origin: :rails
    )
  end

  it "has an association validator" do
    expect(foo).to have_callback(
      callback_name: :before_validate,
      method_name: /^validate_associated/, origin: :rails
    )
  end

  it "does not cause false positives when it comes to association callbacks" do
    expect(foo).to have_callback(
      callback_name: :after_validation,
      method_name: :noop, association_generated: false
    )
    expect(foo).to have_callback(
      callback_name: :after_create,
      method_name: :noop, association_generated: false
    )
    expect(foo).to have_callback(
      callback_name: :around_create,
      method_name: :noop, association_generated: false
    )

    expect(foo).to have_validation(
      type: :presence,
      human_method_name: /Presence.*\(name\)/,
      association_generated: false
    )
    expect(foo).to have_validation(
      type: :uniqueness,
      human_method_name: /Uniqueness.*\(name\)/,
      association_generated: false
    )
  end

  context "with mode=default" do
    subject(:foo) { CallbackHell::Collector.new(Foo, mode: :default).collect }

    it "has no association callbacks" do
      expect(foo).not_to have_callback(association_generated: true)
    end
  end
end
