require 'spec_helper'
require 'roar_extensions'

module RoarExtensions
  describe Presenter do

    class TestPhotoPresenter
      include Presenter

      root_element :photo

      delegated_property :position
    end

    class TestProductPresenter
      include Presenter

      root_element :product

      delegated_property :id,             :always_include => true
      delegated_property :name
      delegated_property :is_buying,      :from => :buying?
      delegated_property :msrp,           :as => MoneyPresenter
      property :possible_variants_count
      property :min_sell_price,           :as => MoneyPresenter
      property :catalog_links,            :from => :catalog_links_as_json
      delegated_collection :photos,       :as => TestPhotoPresenter, :embedded => true

      link(:rel => "self")             { "/v1/products/#{record.id}" }
      link(:rel => "category")         { "/v1/categories/#{record.category_id}" }
      link(:rel => "related_products") { "/v1/products/#{record.id}/related" }

      def initialize(record, options = {})
        super(record)

        @embedded = options.fetch(:embedded, [])
      end

      private

      def min_sell_price
        OpenStruct.new(:cents => 499,
                       :currency => OpenStruct.new(:iso_code => 'USD'))
      end

      def possible_variants_count
        3
      end

      def catalog_links_as_json
        {'omg' => 'wtf'}
      end
    end

    let(:product) {
      mock("Product Record",
           :id          => 9001,
           :category_id => 800,
           :name        => "Worship",
           :photos      => [photo],
           :msrp        => stub(:cents => 300, :currency => stub(:iso_code => 'USD')),
           :buying?     => true)
    }
    
    let(:photo) {
      mock("Photo", :position => 1)
    }

    let(:options) { {} }
    let(:json_options) { {} }

    let(:presenter) {  TestProductPresenter.new(product, options) }

    subject { presenter }

    it "aliases to_hash to as_json" do
      subject.to_hash.should == subject.as_json
    end

    context "as_json" do
      subject { presenter.as_json(json_options)['product'] }

      it "has a name" do
        subject['name'].should == 'Worship'
      end

      it "has a possible_variants_count" do
        subject['possible_variants_count'].should == 3
      end

      it "has a catalog_links" do
        subject['catalog_links'].should == {'omg' => 'wtf'}
      end

      it "has an msrp as money" do
        subject['msrp'].should == {
          'money' => {
            'cents'    => 300,
            'currency' => 'USD'
          }
        }
      end

      it "has a min sell price as money" do
        subject['min_sell_price'].should == {
          'money' => {
            'cents'    => 499,
            'currency' => 'USD'
          }
        }
      end

      it "has an id" do
        subject['id'].should == 9001
      end

      it "has the buyingness" do
        subject['is_buying'].should == true
      end


      it "has api _links" do
        subject['_links'].should == {
          'self' => { "href" => "/v1/products/9001" },
          'related_products' => { "href" => "/v1/products/9001/related" },
          'category' => { "href" => '/v1/categories/800'}
        }
      end

      it "does not embed" do
        subject.should_not have_key('_embedded')
      end

      context "embedding of photos enabled" do
        let(:options) { {:embedded => [:photos]} }

        it "has embedded photos" do
          subject['_embedded']['photos'].should == [
            {
              'photo' => {
                'position' => 1
              }
            }
          ]
        end
      end

      context "always renders nil attributes" do
        before(:each) do
          product.stub(:name).and_return(nil)
        end

        it "has a null name" do
          subject.fetch('name').should == nil
        end
      end

      context "limiting attributes returned" do
        let(:json_options) {{ :include => [:name] }}

        it "limits to the attributes requested, plus required attributes" do
          subject.keys.sort.should == ['id', 'name']
        end
      end
    end
  end
end