1use strict;
2use warnings;
3use Test::More;
4use FindBin;
5use lib ( "$FindBin::Bin/../lib", "$FindBin::Bin/../t/lib" );
6
7use Catalyst::Request::REST;
8use Catalyst::TraitFor::Request::REST;
9use Moose::Meta::Class;
10use HTTP::Headers;
11use Catalyst::Log;
12
13my $anon_class = Moose::Meta::Class->create_anon_class(
14    superclasses => ['Catalyst::Request'],
15    roles        => ['Catalyst::TraitFor::Request::REST'],
16    cache        => 1,
17)->name;
18
19# We run the tests twice to make sure Catalyst::Request::REST is
20# 100% back-compatible.
21for my $class ( $anon_class, 'Catalyst::Request::REST' ) {
22    {
23        my $request = $class->new(
24            _log => Catalyst::Log->new
25        );
26        $request->{_context} = 'MockContext';
27        $request->headers( HTTP::Headers->new );
28        $request->parameters( {} );
29        $request->method('GET');
30        $request->content_type('text/foobar');
31
32        is_deeply( $request->accepted_content_types, [ 'text/foobar' ],
33                   'content-type set in request headers is found' );
34        is( $request->preferred_content_type, 'text/foobar',
35            'preferred content type is text/foobar' );
36        ok( ! $request->accept_only, 'accept_only is false' );
37        ok( $request->accepts('text/foobar'), 'accepts text/foobar' );
38        ok( ! $request->accepts('text/html'), 'does not accept text/html' );
39    }
40
41    {
42        my $request = $class->new( _log => Catalyst::Log->new );
43        $request->{_context} = 'MockContext';
44        $request->headers( HTTP::Headers->new );
45        $request->parameters( { 'content-type' => 'text/fudge' } );
46        $request->method('GET');
47        $request->content_type('text/foobar');
48
49        is_deeply( $request->accepted_content_types, [ 'text/foobar', 'text/fudge' ],
50                   'content-type set in request headers and type in parameters is found' );
51        is( $request->preferred_content_type, 'text/foobar',
52            'preferred content type is text/foobar' );
53        ok( ! $request->accept_only, 'accept_only is false' );
54        ok( $request->accepts('text/foobar'), 'accepts text/foobar' );
55        ok( $request->accepts('text/fudge'), 'accepts text/fudge' );
56        ok( ! $request->accepts('text/html'), 'does not accept text/html' );
57    }
58
59    {
60        my $request = $class->new( _log => Catalyst::Log->new );
61        $request->{_context} = 'MockContext';
62        $request->headers( HTTP::Headers->new );
63        $request->parameters( { 'content-type' => 'text/fudge' } );
64        $request->method('POST');
65        $request->content_type('text/foobar');
66
67        ok( ! $request->accepts('text/fudge'), 'content type in parameters is ignored for POST' );
68    }
69
70    {
71        my $request = $class->new( _log => Catalyst::Log->new );
72        $request->{_context} = 'MockContext';
73        $request->headers( HTTP::Headers->new );
74        $request->parameters( {} );
75        $request->method('GET');
76        $request->headers->header(
77            'Accept' =>
78            # From Firefox 2.0 when it requests an html page
79            'text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5',
80        );
81
82        is_deeply( $request->accepted_content_types,
83                   [ qw( text/xml application/xml application/xhtml+xml
84                         image/png
85                         text/html
86                         text/plain
87                         */*
88                       ) ],
89                   'accept header is parsed properly' );
90        is( $request->preferred_content_type, 'text/xml',
91            'preferred content type is text/xml' );
92        ok( $request->accept_only, 'accept_only is true' );
93        ok( $request->accepts('text/html'), 'accepts text/html' );
94        ok( $request->accepts('image/png'), 'accepts image/png' );
95        ok( ! $request->accepts('image/svg'), 'does not accept image/svg' );
96    }
97
98    {
99        my $request = $class->new( _log => Catalyst::Log->new );
100        $request->{_context} = 'MockContext';
101        $request->headers( HTTP::Headers->new );
102        $request->parameters( {} );
103        $request->method('GET');
104        $request->content_type('application/json');
105        $request->headers->header(
106            'Accept' =>
107            # From Firefox 2.0 when it requests an html page
108            'text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5',
109        );
110
111        is_deeply( $request->accepted_content_types,
112                   [ qw( application/json
113                         text/xml application/xml application/xhtml+xml
114                         image/png
115                         text/html
116                         text/plain
117                         */*
118                       ) ],
119                   'accept header is parsed properly, and content-type header has precedence over accept' );
120        ok( ! $request->accept_only, 'accept_only is false' );
121    }
122
123    {
124        my $request = $class->new( _log => Catalyst::Log->new );
125        $request->{_context} = 'MockContext';
126        $request->headers( HTTP::Headers->new );
127        $request->parameters( {} );
128        $request->method('GET');
129        $request->content_type('application/json');
130        $request->headers->header(
131            'Accept' =>
132            # From Firefox 2.0 when it requests an html page
133            'text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5',
134        );
135
136        is_deeply( $request->accepted_content_types,
137                   [ qw( application/json
138                         text/xml application/xml application/xhtml+xml
139                         image/png
140                         text/html
141                         text/plain
142                         */*
143                       ) ],
144                   'accept header is parsed properly, and content-type header has precedence over accept' );
145        ok( ! $request->accept_only, 'accept_only is false' );
146    }
147
148    {
149        my $request = $class->new( _log => Catalyst::Log->new );
150        $request->{_context} = 'MockContext';
151        $request->headers( HTTP::Headers->new );
152        $request->parameters( {} );
153        $request->method('GET');
154        $request->content_type('text/x-json');
155        $request->headers->header(
156            'Accept' => 'text/plain,text/x-json',
157        );
158
159        is_deeply( $request->accepted_content_types,
160                   [ qw( text/x-json
161                         text/plain
162                       ) ],
163                   'each type appears only once' );
164    }
165
166    {
167        my $request = $class->new( _log => Catalyst::Log->new );
168        $request->{_context} = 'MockContext';
169        $request->headers( HTTP::Headers->new );
170        $request->parameters( {} );
171        $request->method('GET');
172        $request->content_type('application/json');
173        $request->headers->header(
174            'Accept' => 'text/plain,application/json',
175        );
176
177        is_deeply( $request->accepted_content_types,
178                   [ qw( application/json
179                         text/plain
180                       ) ],
181                   'each type appears only once' );
182    }
183}
184
185done_testing;
186
187package MockContext;
188
189sub prepare_body { }
190