shared_examples_for 'versioning' do
  it 'sets the API version' do
    subject.format :txt
    subject.version 'v1', macro_options
    subject.get :hello do
      "Version: #{request.env['api.version']}"
    end
    versioned_get '/hello', 'v1', macro_options
    expect(last_response.body).to eql 'Version: v1'
  end

  it 'adds the prefix before the API version' do
    subject.format :txt
    subject.prefix 'api'
    subject.version 'v1', macro_options
    subject.get :hello do
      "Version: #{request.env['api.version']}"
    end
    versioned_get '/hello', 'v1', macro_options.merge(prefix: 'api')
    expect(last_response.body).to eql 'Version: v1'
  end

  it 'is able to specify version as a nesting' do
    subject.version 'v2', macro_options
    subject.get '/awesome' do
      'Radical'
    end

    subject.version 'v1', macro_options do
      get '/legacy' do
        'Totally'
      end
    end

    versioned_get '/awesome', 'v1', macro_options
    expect(last_response.status).to eql 404

    versioned_get '/awesome', 'v2', macro_options
    expect(last_response.status).to eql 200
    versioned_get '/legacy', 'v1', macro_options
    expect(last_response.status).to eql 200
    versioned_get '/legacy', 'v2', macro_options
    expect(last_response.status).to eql 404
  end

  it 'is able to specify multiple versions' do
    subject.version 'v1', 'v2', macro_options
    subject.get 'awesome' do
      'I exist'
    end

    versioned_get '/awesome', 'v1', macro_options
    expect(last_response.status).to eql 200
    versioned_get '/awesome', 'v2', macro_options
    expect(last_response.status).to eql 200
    versioned_get '/awesome', 'v3', macro_options
    expect(last_response.status).to eql 404
  end

  context 'with different versions for the same endpoint' do
    context 'without a prefix' do
      it 'allows the same endpoint to be implemented' do
        subject.format :txt
        subject.version 'v2', macro_options
        subject.get 'version' do
          request.env['api.version']
        end

        subject.version 'v1', macro_options do
          get 'version' do
            'version ' + request.env['api.version']
          end
        end

        versioned_get '/version', 'v2', macro_options
        expect(last_response.status).to eq(200)
        expect(last_response.body).to eq('v2')
        versioned_get '/version', 'v1', macro_options
        expect(last_response.status).to eq(200)
        expect(last_response.body).to eq('version v1')
      end
    end

    context 'with a prefix' do
      it 'allows the same endpoint to be implemented' do
        subject.format :txt
        subject.prefix 'api'
        subject.version 'v2', macro_options
        subject.get 'version' do
          request.env['api.version']
        end

        subject.version 'v1', macro_options do
          get 'version' do
            'version ' + request.env['api.version']
          end
        end

        versioned_get '/version', 'v1', macro_options.merge(prefix: subject.prefix)
        expect(last_response.status).to eq(200)
        expect(last_response.body).to eq('version v1')

        versioned_get '/version', 'v2', macro_options.merge(prefix: subject.prefix)
        expect(last_response.status).to eq(200)
        expect(last_response.body).to eq('v2')
      end
    end
  end

  context 'with before block defined within a version block' do
    it 'calls before block that is defined within the version block' do
      subject.format :txt
      subject.prefix 'api'
      subject.version 'v2', macro_options do
        before do
          @output ||= 'v2-'
        end
        get 'version' do
          @output += 'version'
        end
      end

      subject.version 'v1', macro_options do
        before do
          @output ||= 'v1-'
        end
        get 'version' do
          @output += 'version'
        end
      end

      versioned_get '/version', 'v1', macro_options.merge(prefix: subject.prefix)
      expect(last_response.status).to eq(200)
      expect(last_response.body).to eq('v1-version')

      versioned_get '/version', 'v2', macro_options.merge(prefix: subject.prefix)
      expect(last_response.status).to eq(200)
      expect(last_response.body).to eq('v2-version')
    end
  end

  it 'does not overwrite version parameter with API version' do
    subject.format :txt
    subject.version 'v1', macro_options
    subject.params { requires :version }
    subject.get :api_version_with_version_param do
      params[:version]
    end
    versioned_get '/api_version_with_version_param?version=1', 'v1', macro_options
    expect(last_response.body).to eql '1'
  end
end
