more utf8 tests and fixes
[catagits/Catalyst-Runtime.git] / t / utf_incoming.t
1 use utf8;
2 use warnings;
3 use strict;
4 use Test::More;
5 use HTTP::Request::Common;
6 use Encode 2.21 'decode_utf8', 'encode_utf8';
7 use File::Spec;
8
9 # Test cases for incoming utf8 
10
11 {
12   package MyApp::Controller::Root;
13   $INC{'MyApp/Controller/Root.pm'} = __FILE__;
14
15   use base 'Catalyst::Controller';
16
17   sub heart :Path('♥') {
18     my ($self, $c) = @_;
19     $c->response->content_type('text/html');
20     $c->response->body("<p>This is path-heart action ♥</p>");
21     # We let the content length middleware find the length...
22   }
23
24   sub hat :Path('^') {
25     my ($self, $c) = @_;
26     $c->response->content_type('text/html');
27     $c->response->body("<p>This is path-hat action ^</p>");
28   }
29
30   sub uri_for :Path('uri_for') {
31     my ($self, $c) = @_;
32     $c->response->content_type('text/html');
33     $c->response->body("${\$c->uri_for($c->controller('Root')->action_for('argend'), ['♥'], '♥', {'♥'=>'♥♥'})}");
34   }
35
36   sub heart_with_arg :Path('a♥') Args(1)  {
37     my ($self, $c, $arg) = @_;
38     $c->response->content_type('text/html');
39     $c->response->body("<p>This is path-heart-arg action $arg</p>");
40     Test::More::is $c->req->args->[0], '♥';
41   }
42
43   sub base :Chained('/') CaptureArgs(0) { }
44     sub link :Chained('base') PathPart('♥') Args(0) {
45       my ($self, $c) = @_;
46       $c->response->content_type('text/html');
47       $c->response->body("<p>This is base-link action ♥</p>");
48     }
49     sub arg :Chained('base') PathPart('♥') Args(1) {
50       my ($self, $c, $arg) = @_;
51       $c->response->content_type('text/html');
52       $c->response->body("<p>This is base-link action ♥ $arg</p>");
53     }
54     sub capture :Chained('base') PathPart('♥') CaptureArgs(1) {
55       my ($self, $c, $arg) = @_;
56       $c->stash(capture=>$arg);
57     }
58       sub argend :Chained('capture') PathPart('♥') Args(1) {
59         my ($self, $c, $arg) = @_;
60         $c->response->content_type('text/html');
61
62         Test::More::is $c->req->args->[0], '♥';
63         Test::More::is $c->req->captures->[0], '♥';
64
65         $c->response->body("<p>This is base-link action ♥ ${\$c->req->args->[0]}</p>");
66
67         # Test to make sure redirect can now take an object (sorry don't have a better place for it
68         # but wanted test coverage.
69         my $location = $c->res->redirect( $c->uri_for($c->controller('Root')->action_for('uri_for')) );
70         Test::More::ok !ref $location; 
71       }
72
73   sub stream_write :Local {
74     my ($self, $c) = @_;
75     $c->response->content_type('text/html');
76     $c->response->write("<p>This is stream_write action ♥</p>");
77   }
78
79   sub stream_write_fh :Local {
80     my ($self, $c) = @_;
81     $c->response->content_type('text/html');
82
83     my $writer = $c->res->write_fh;
84
85     $writer->write(Encode::encode_utf8('<p>This is stream_write_fh action ♥</p>'));
86     $writer->close;
87   }
88
89   sub stream_body_fh :Local {
90     my ($self, $c) = @_;
91
92     my $path = File::Spec->catfile('t', 'utf8.txt');
93     open(my $fh, '<', $path) || die "trouble: $!";
94     $c->response->content_type('text/html');
95     $c->response->body($fh);
96   }
97
98   package MyApp;
99   use Catalyst;
100
101   # Default encoding is now UTF-8
102   # MyApp->config(encoding=>'UTF-8');
103
104   Test::More::ok(MyApp->setup, 'setup app');
105 }
106
107 ok my $psgi = MyApp->psgi_app, 'build psgi app';
108
109 use Catalyst::Test 'MyApp';
110
111 {
112   my $res = request "/root/♥";
113
114   is $res->code, 200, 'OK';
115   is decode_utf8($res->content), '<p>This is path-heart action ♥</p>', 'correct body';
116   is $res->content_length, 36, 'correct length';
117   is $res->content_charset, 'UTF-8';
118 }
119
120 {
121   my $res = request "/root/a♥/♥";
122
123   is $res->code, 200, 'OK';
124   is decode_utf8($res->content), '<p>This is path-heart-arg action ♥</p>', 'correct body';
125   is $res->content_length, 40, 'correct length';
126   is $res->content_charset, 'UTF-8';
127 }
128
129 {
130   my $res = request "/root/^";
131
132   is $res->code, 200, 'OK';
133   is decode_utf8($res->content), '<p>This is path-hat action ^</p>', 'correct body';
134   is $res->content_length, 32, 'correct length';
135   is $res->content_charset, 'UTF-8';
136 }
137
138 {
139   my $res = request "/base/♥";
140
141   is $res->code, 200, 'OK';
142   is decode_utf8($res->content), '<p>This is base-link action ♥</p>', 'correct body';
143   is $res->content_length, 35, 'correct length';
144   is $res->content_charset, 'UTF-8';
145 }
146
147 {
148   my ($res, $c) = ctx_request POST "/base/♥?♥=♥&♥=♥♥", [a=>1, b=>'', '♥'=>'♥', '♥'=>'♥♥'];
149
150   is $res->code, 200, 'OK';
151   is decode_utf8($res->content), '<p>This is base-link action ♥</p>', 'correct body';
152   is $res->content_length, 35, 'correct length';
153   is $c->req->parameters->{'♥'}[0], '♥';
154   is $c->req->query_parameters->{'♥'}[0], '♥';
155   is $c->req->body_parameters->{'♥'}[0], '♥';
156   is $c->req->parameters->{'♥'}[0], '♥';
157   is $c->req->parameters->{a}, 1;
158   is $c->req->body_parameters->{a}, 1;
159   is $res->content_charset, 'UTF-8';
160 }
161
162 {
163   my ($res, $c) = ctx_request GET "/base/♥?♥♥♥";
164
165   is $res->code, 200, 'OK';
166   is decode_utf8($res->content), '<p>This is base-link action ♥</p>', 'correct body';
167   is $res->content_length, 35, 'correct length';
168   is $c->req->query_keywords, '♥♥♥';
169   is $res->content_charset, 'UTF-8';
170 }
171
172 {
173   my $res = request "/base/♥/♥";
174
175   is $res->code, 200, 'OK';
176   is decode_utf8($res->content), '<p>This is base-link action ♥ ♥</p>', 'correct body';
177   is $res->content_length, 39, 'correct length';
178   is $res->content_charset, 'UTF-8';
179 }
180
181 {
182   my $res = request "/base/♥/♥/♥/♥";
183
184   is decode_utf8($res->content), '<p>This is base-link action ♥ ♥</p>', 'correct body';
185   is $res->content_length, 39, 'correct length';
186   is $res->content_charset, 'UTF-8';
187 }
188
189 {
190   my ($res, $c) = ctx_request POST "/base/♥/♥/♥/♥?♥=♥♥", [a=>1, b=>'2', '♥'=>'♥♥'];
191
192   ## Make sure that the urls we generate work the same
193   my $uri_for = $c->uri_for($c->controller('Root')->action_for('argend'), ['♥'], '♥', {'♥'=>'♥♥'});
194   my $uri = $c->req->uri;
195
196   is "$uri", "$uri_for";
197
198   {
199     my ($res, $c) = ctx_request POST "$uri_for", [a=>1, b=>'2', '♥'=>'♥♥'];
200     is $c->req->query_parameters->{'♥'}, '♥♥';
201     is $c->req->body_parameters->{'♥'}, '♥♥';
202     is $c->req->parameters->{'♥'}[0], '♥♥'; #combined with query and body
203     is $res->content_charset, 'UTF-8';
204
205   }
206 }
207
208 {
209   my ($res, $c) = ctx_request "/root/uri_for";
210   my $url = $c->uri_for($c->controller('Root')->action_for('argend'), ['♥'], '♥', {'♥'=>'♥♥'});
211
212   is $res->code, 200, 'OK';
213   is decode_utf8($res->content), "$url", 'correct body'; #should do nothing
214   is $res->content, "$url", 'correct body';
215   is $res->content_length, 90, 'correct length';
216   is $res->content_charset, 'UTF-8';
217 }
218
219 {
220   my $res = request "/root/stream_write";
221
222   is $res->code, 200, 'OK';
223   is decode_utf8($res->content), '<p>This is stream_write action ♥</p>', 'correct body';
224   is $res->content_charset, 'UTF-8';
225 }
226
227 {
228   my $res = request "/root/stream_body_fh";
229
230   is $res->code, 200, 'OK';
231   is decode_utf8($res->content), "<p>This is stream_body_fh action ♥</p>\n", 'correct body';
232   is $res->content_charset, 'UTF-8';
233   # Not sure why there is a trailing newline above... its not in catalyst code I can see. Not sure
234   # if is a problem or just an artifact of the why the test stuff works - JNAP
235 }
236
237 {
238   my $res = request "/root/stream_write_fh";
239
240   is $res->code, 200, 'OK';
241   is decode_utf8($res->content), '<p>This is stream_write_fh action ♥</p>', 'correct body';
242   is $res->content_length, 41, 'correct length';
243   is $res->content_charset, 'UTF-8';
244 }
245
246 done_testing;
247
248 MyApp->to_app;