# frozen_string_literal: true

require_relative '../../spec_helper'

module PacketGen
  module Header
    module HTTP
      describe Request do
        describe 'binding' do
          it 'in TCP packets' do
            expect(TCP).to know_header(HTTP::Request)
          end

          it 'parsing a HTTP::Request does not raise if some characters are not valid in encoding' do
            str = PacketGen.gen('TCP', body: "GET / HTTP/1.1\r\n\r\n\x81".b).to_s
            pkt = PacketGen.parse(str, first_header: 'TCP')
            expect(pkt.http_request.verb).to eq('GET')
            expect(pkt.http_request.path).to eq('/')
            expect(pkt.http_request.body).to eq("\x81".b)
          end

          it 'issue-112: adding a HTTP::Request does not raise' do
            pkt = PacketGen.gen('IP').add('TCP')
            expect { pkt.add('HTTP::Request') }.not_to raise_error
          end
        end

        describe '#initialize' do
          it 'creates a HTTP::Request header with default values' do
            http_req = Request.new
            expect(http_req).to be_a(Request)
          end

          it 'creates a HTTP::Request header with given options' do
            http_req = Request.new(verb: 'GET', path: '/', headers: { 'User-Agent' => 'dummy/1.0' })
            expect(http_req).to be_a(Request)
            expect(http_req.verb).to eq('GET')
            expect(http_req.path).to eq('/')
            expect(http_req.headers).to eq({ 'User-Agent' => 'dummy/1.0' })
          end
        end

        describe 'setters' do
          let(:http_req) { Request.new }

          it '#verb= accepts strings' do
            http_req.verb = 'GET'
            expect(http_req.verb).to eq('GET')
          end

          it '#path= accepts strings' do
            http_req.path = '/'
            expect(http_req.path).to eq('/')
          end

          it '#version= accepts strings' do
            http_req.version = 'HTTP/1.1'
            expect(http_req.version).to eq('HTTP/1.1')
          end
        end

        describe '#to_s' do
          let(:http_req) { Request.new }

          it 'errors out without needed fields' do
            expect { http_req.to_s }.to raise_error(FormatError)
            http_req.verb = 'GET'
            expect { http_req.to_s }.to raise_error(FormatError)
            http_req.path = '/'
            expect(http_req.to_s).to be_a(String)
          end

          it 'returns a string with the needed fields' do
            http_req.verb = 'GET'
            http_req.path = '/'
            expect(http_req.to_s).to be_a(String)
          end
        end

        describe '#read' do
          let(:http_req) { Request.new }

          it 'parses http request data from a string' do
            http_req.read("GET / HTTP/1.1\r\nUser-Agent: dummy/1.0\r\n\r\n")
            expect(http_req.verb).to eq('GET')
            expect(http_req.path).to eq('/')
            expect(http_req.version).to eq('HTTP/1.1')
            expect(http_req.headers).to eq({ 'User-Agent' => 'dummy/1.0' })
          end

          it 'parses weird http request data from a string with invalid encoding' do
            http_req.read("GET / HTTP/1.1\r\nUser-Agent: dummy/1.0\r\n\r\n\r\xD1")
            expect(http_req.verb).to eq('GET')
            expect(http_req.path).to eq('/')
            expect(http_req.version).to eq('HTTP/1.1')
            expect(http_req.headers).to eq({ 'User-Agent' => 'dummy/1.0' })
            expect(http_req.body.bytes).to eq("\r\xD1".bytes)
          end
        end

        describe '#inspect' do
          let(:http_req) { Request.new }

          it 'returns a String with all attributes' do
            expect(http_req.inspect).to be_a(String)
          end
        end
      end
    end
  end
end
