require 'spec_helper'

require 'docker'
require 'docker/image'

require 'docker/porcelain/image'

describe Docker::Porcelain::Image do
  describe '.[]' do
    it "returns the specified image" do
      image = double 'image'
      allow(Docker::Image).to receive(:get).with('some-id').and_return image
      expect(Docker::Porcelain::Image['some-id']).to eq image
    end

    it "returns nil if image not found" do
      allow(Docker::Image).to receive(:get).with('some-id').and_raise Docker::Error::NotFoundError
      expect(Docker::Porcelain::Image['some-id']).to be_nil
    end
  end

  let(:image) do
    instance_double(Docker::Image, info: info)\
        .tap { |image| image.extend Docker::Porcelain::Image }
  end
  let(:info) { {} }

  describe '#parent' do
    let(:parent_sha) do
      'e812272a2b62a25ef54e8a0088ced5bc74cc6108551643404656f1a612cad46e'
    end
    let(:info) { { 'Parent' => parent_sha } }
    let(:parent) { instance_double(Docker::Image) }
    before do
      allow(Docker::Porcelain::Image).to receive(:[]).with(parent_sha)\
          .and_return parent
    end

    it 'returns the parent image' do
      expect(image.parent).to eq parent
    end

    context 'when the image is from scratch' do
      let(:parent_sha) { '' }
      it 'returns nil' do
        expect(image.parent).to be_nil
      end
    end
  end

  describe '#tag' do
    let(:image) do
      # we can't use the instance double here since we can't stub super
      spy.extend(Docker::Porcelain::Image)
    end

    it 'allows calling with just the hash' do
      image.tag repo: 'foo', tag: 'bar'
      expect(image).to have_received(:tag)\
          .with repo: 'foo', tag: 'bar'
    end

    it 'splits the tag if appropriate' do
      image.tag 'foo:bar'
      expect(image).to have_received(:tag)\
          .with 'repo' => 'foo', 'tag' => 'bar'
    end

    it 'works with just the repo too' do
      image.tag 'foo'
      expect(image).to have_received(:tag).with 'repo' => 'foo', 'tag' => nil
    end

    it 'accepts two strings' do
      image.tag 'foo', 'bar', force: true
      expect(image).to have_received(:tag)\
          .with 'repo' => 'foo', 'tag' => 'bar', :force => true
    end
  end

  describe '#tags' do
    let(:info) { { 'RepoTags' => tags } }
    context "with a tagged image" do
      let(:tags) { ['foo:bar', 'baz:bar'] }
      it "returns the list of tags" do
        expect(image.tags).to eq tags
      end
    end

    context "with an untagged image" do
      let(:tags) do
        # that's really what docker returns
        ['<none>:<none>']
      end

      it "returns an empty list" do
        expect(image.tags).to be_empty
      end
    end

    context 'with an image with incomplete info' do
      # sometimes an Image doesn't have tags in its info
      let(:tags) do
        nil
      end

      before do
        allow(image).to receive(:refresh!) do
          # refresh! fetches the missing info from the server
          image.info['RepoTags'] = %w(foo bar)
          image
        end
      end

      it 'refreshes the info before returning' do
        expect(image.tags).to eq %w(foo bar)
      end
    end
  end
end
