# frozen_string_literal: true

require 'gir_ffi_test_helper'
require 'gir_ffi/unintrospectable_type_info'

describe GirFFI::UnintrospectableTypeInfo do
  describe '#info_type' do
    it 'returns :unintrospectable' do
      info = GirFFI::UnintrospectableTypeInfo.new :some_type
      info.info_type.must_equal :unintrospectable
    end
  end

  describe '#parent' do
    describe 'when the GIR knows about the parent gtype' do
      it "finds the parent's info by gtype" do
        gobject = Object.new
        gir = Object.new

        expect(gobject).to receive(:type_parent).with(:some_type).and_return :foo
        expect(gir).to receive(:find_by_gtype).with(:foo).and_return :foo_info

        info = GirFFI::UnintrospectableTypeInfo.new(:some_type, gir, gobject)

        info.parent.must_equal :foo_info
      end
    end

    describe 'when the GIR does not know about the parent gtype' do
      it 'creates a new UnintrospectableTypeInfo from the parent gtype' do
        gobject = Object.new
        gir = Object.new

        expect(gobject).to receive(:type_parent).with(:some_type).and_return :foo
        expect(gir).to receive(:find_by_gtype).with(:foo).and_return nil

        info = GirFFI::UnintrospectableTypeInfo.new(:some_type, gir, gobject)

        info.parent.g_type.must_equal :foo
      end
    end
  end

  describe '#interfaces' do
    it 'finds interface infos by gtype' do
      gobject = Object.new
      gir = Object.new

      expect(gobject).to receive(:type_interfaces).with(:some_type).and_return [:foo, :bar]
      expect(gir).to receive(:find_by_gtype).with(:foo).and_return :foo_info
      expect(gir).to receive(:find_by_gtype).with(:bar).and_return :bar_info

      info = GirFFI::UnintrospectableTypeInfo.new(:some_type, gir, gobject)

      info.interfaces.must_equal [:foo_info, :bar_info]
    end

    it 'skips interfaces that have no introspection data' do
      gobject = Object.new
      gir = Object.new

      expect(gobject).to receive(:type_interfaces).with(:some_type).and_return [:foo, :bar]
      expect(gir).to receive(:find_by_gtype).with(:foo).and_return :foo_info
      expect(gir).to receive(:find_by_gtype).with(:bar).and_return nil

      info = GirFFI::UnintrospectableTypeInfo.new(:some_type, gir, gobject)

      info.interfaces.must_equal [:foo_info]
    end
  end

  describe '#g_type' do
    it 'returns the passed-in gtype' do
      info = GirFFI::UnintrospectableTypeInfo.new(:some_type)
      info.g_type.must_equal :some_type
    end
  end

  describe '#fields' do
    it 'returns an empty array' do
      info = GirFFI::UnintrospectableTypeInfo.new(:some_type)
      info.fields.must_equal []
    end
  end

  describe '#namespace' do
    it "returns the parent class' namespace" do
      gobject = Object.new
      gir = Object.new
      parent_info = Object.new

      expect(gobject).to receive(:type_parent).with(:some_type).and_return :foo
      expect(gir).to receive(:find_by_gtype).with(:foo).and_return parent_info
      expect(parent_info).to receive(:namespace).and_return 'FooNamespace'

      info = GirFFI::UnintrospectableTypeInfo.new(:some_type, gir, gobject)

      info.namespace.must_equal 'FooNamespace'
    end
  end

  describe '#safe_name' do
    it 'finds the class name by gtype' do
      gobject = Object.new

      expect(gobject).to receive(:type_name).with(:some_type).and_return 'GSomeType'

      info = GirFFI::UnintrospectableTypeInfo.new(:some_type, nil, gobject)

      info.safe_name.must_equal 'GSomeType'
    end
  end

  describe '#find_signal' do
    it 'indicates that no signals can be found' do
      info = GirFFI::UnintrospectableTypeInfo.new(:some_type)
      result = info.find_signal 'any'
      result.must_be_nil
    end
  end
end
