Commit | Line | Data |
0ca510f0 |
1 | use utf8; |
2 | use warnings; |
3 | use strict; |
4 | use Test::More; |
b9d96e27 |
5 | use HTTP::Request::Common; |
59e11cd7 |
6 | use Encode 2.21 'decode_utf8', 'encode_utf8'; |
7 | use File::Spec; |
0ca510f0 |
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 | |
e5a5e80b |
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 | |
0ca510f0 |
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 | } |
e5a5e80b |
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>"); |
dd096a3a |
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; |
e5a5e80b |
71 | } |
0ca510f0 |
72 | |
dd096a3a |
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 | |
fe1dfeaf |
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; |
e8361cf8 |
84 | $writer->write_encoded('<p>This is stream_write_fh action ♥</p>'); |
59e11cd7 |
85 | $writer->close; |
86 | } |
87 | |
e8361cf8 |
88 | # Stream a file with utf8 chars directly, you don't need to decode |
59e11cd7 |
89 | sub stream_body_fh :Local { |
90 | my ($self, $c) = @_; |
59e11cd7 |
91 | my $path = File::Spec->catfile('t', 'utf8.txt'); |
92 | open(my $fh, '<', $path) || die "trouble: $!"; |
93 | $c->response->content_type('text/html'); |
94 | $c->response->body($fh); |
fe1dfeaf |
95 | } |
96 | |
e8361cf8 |
97 | # If you pull the file contents into a var, NOW you need to specify the |
98 | # IO encoding on the FH. Ultimately Plack at the end wants bytes... |
99 | sub stream_body_fh2 :Local { |
100 | my ($self, $c) = @_; |
101 | my $path = File::Spec->catfile('t', 'utf8.txt'); |
102 | open(my $fh, '<:encoding(UTF-8)', $path) || die "trouble: $!"; |
103 | my $contents = do { local $/; <$fh> }; |
104 | |
105 | $c->response->content_type('text/html'); |
106 | $c->response->body($contents); |
107 | } |
108 | |
109 | |
0ca510f0 |
110 | package MyApp; |
111 | use Catalyst; |
112 | |
7b39dea1 |
113 | # Default encoding is now UTF-8 |
114 | # MyApp->config(encoding=>'UTF-8'); |
0ca510f0 |
115 | |
116 | Test::More::ok(MyApp->setup, 'setup app'); |
117 | } |
118 | |
119 | ok my $psgi = MyApp->psgi_app, 'build psgi app'; |
120 | |
121 | use Catalyst::Test 'MyApp'; |
0ca510f0 |
122 | |
123 | { |
124 | my $res = request "/root/♥"; |
125 | |
126 | is $res->code, 200, 'OK'; |
127 | is decode_utf8($res->content), '<p>This is path-heart action ♥</p>', 'correct body'; |
128 | is $res->content_length, 36, 'correct length'; |
4a64c27b |
129 | is $res->content_charset, 'UTF-8'; |
0ca510f0 |
130 | } |
131 | |
132 | { |
e5a5e80b |
133 | my $res = request "/root/a♥/♥"; |
134 | |
135 | is $res->code, 200, 'OK'; |
136 | is decode_utf8($res->content), '<p>This is path-heart-arg action ♥</p>', 'correct body'; |
137 | is $res->content_length, 40, 'correct length'; |
4a64c27b |
138 | is $res->content_charset, 'UTF-8'; |
e5a5e80b |
139 | } |
140 | |
141 | { |
0ca510f0 |
142 | my $res = request "/root/^"; |
143 | |
144 | is $res->code, 200, 'OK'; |
145 | is decode_utf8($res->content), '<p>This is path-hat action ^</p>', 'correct body'; |
146 | is $res->content_length, 32, 'correct length'; |
4a64c27b |
147 | is $res->content_charset, 'UTF-8'; |
0ca510f0 |
148 | } |
149 | |
150 | { |
151 | my $res = request "/base/♥"; |
152 | |
153 | is $res->code, 200, 'OK'; |
154 | is decode_utf8($res->content), '<p>This is base-link action ♥</p>', 'correct body'; |
155 | is $res->content_length, 35, 'correct length'; |
4a64c27b |
156 | is $res->content_charset, 'UTF-8'; |
0ca510f0 |
157 | } |
158 | |
159 | { |
b9d96e27 |
160 | my ($res, $c) = ctx_request POST "/base/♥?♥=♥&♥=♥♥", [a=>1, b=>'', '♥'=>'♥', '♥'=>'♥♥']; |
0ca510f0 |
161 | |
162 | is $res->code, 200, 'OK'; |
163 | is decode_utf8($res->content), '<p>This is base-link action ♥</p>', 'correct body'; |
164 | is $res->content_length, 35, 'correct length'; |
b9d96e27 |
165 | is $c->req->parameters->{'♥'}[0], '♥'; |
166 | is $c->req->query_parameters->{'♥'}[0], '♥'; |
167 | is $c->req->body_parameters->{'♥'}[0], '♥'; |
168 | is $c->req->parameters->{'♥'}[0], '♥'; |
4a62800d |
169 | is $c->req->parameters->{a}, 1; |
170 | is $c->req->body_parameters->{a}, 1; |
4a64c27b |
171 | is $res->content_charset, 'UTF-8'; |
e5a5e80b |
172 | } |
4a62800d |
173 | |
e5a5e80b |
174 | { |
175 | my ($res, $c) = ctx_request GET "/base/♥?♥♥♥"; |
4a62800d |
176 | |
e5a5e80b |
177 | is $res->code, 200, 'OK'; |
178 | is decode_utf8($res->content), '<p>This is base-link action ♥</p>', 'correct body'; |
179 | is $res->content_length, 35, 'correct length'; |
180 | is $c->req->query_keywords, '♥♥♥'; |
4a64c27b |
181 | is $res->content_charset, 'UTF-8'; |
0ca510f0 |
182 | } |
183 | |
e5a5e80b |
184 | { |
185 | my $res = request "/base/♥/♥"; |
186 | |
187 | is $res->code, 200, 'OK'; |
188 | is decode_utf8($res->content), '<p>This is base-link action ♥ ♥</p>', 'correct body'; |
189 | is $res->content_length, 39, 'correct length'; |
4a64c27b |
190 | is $res->content_charset, 'UTF-8'; |
e5a5e80b |
191 | } |
b9d96e27 |
192 | |
e5a5e80b |
193 | { |
194 | my $res = request "/base/♥/♥/♥/♥"; |
195 | |
e5a5e80b |
196 | is decode_utf8($res->content), '<p>This is base-link action ♥ ♥</p>', 'correct body'; |
197 | is $res->content_length, 39, 'correct length'; |
4a64c27b |
198 | is $res->content_charset, 'UTF-8'; |
e5a5e80b |
199 | } |
200 | |
201 | { |
202 | my ($res, $c) = ctx_request POST "/base/♥/♥/♥/♥?♥=♥♥", [a=>1, b=>'2', '♥'=>'♥♥']; |
203 | |
204 | ## Make sure that the urls we generate work the same |
b063a165 |
205 | my $uri_for1 = $c->uri_for($c->controller('Root')->action_for('argend'), ['♥'], '♥', {'♥'=>'♥♥'}); |
206 | my $uri_for2 = $c->uri_for($c->controller('Root')->action_for('argend'), ['♥', '♥'], {'♥'=>'♥♥'}); |
e5a5e80b |
207 | my $uri = $c->req->uri; |
208 | |
b063a165 |
209 | is "$uri_for1", "$uri_for2"; |
210 | is "$uri", "$uri_for1"; |
e5a5e80b |
211 | |
212 | { |
b063a165 |
213 | my ($res, $c) = ctx_request POST "$uri_for1", [a=>1, b=>'2', '♥'=>'♥♥']; |
e5a5e80b |
214 | is $c->req->query_parameters->{'♥'}, '♥♥'; |
215 | is $c->req->body_parameters->{'♥'}, '♥♥'; |
216 | is $c->req->parameters->{'♥'}[0], '♥♥'; #combined with query and body |
4a64c27b |
217 | is $res->content_charset, 'UTF-8'; |
e5a5e80b |
218 | } |
219 | } |
220 | |
221 | { |
222 | my ($res, $c) = ctx_request "/root/uri_for"; |
223 | my $url = $c->uri_for($c->controller('Root')->action_for('argend'), ['♥'], '♥', {'♥'=>'♥♥'}); |
224 | |
225 | is $res->code, 200, 'OK'; |
226 | is decode_utf8($res->content), "$url", 'correct body'; #should do nothing |
227 | is $res->content, "$url", 'correct body'; |
228 | is $res->content_length, 90, 'correct length'; |
4a64c27b |
229 | is $res->content_charset, 'UTF-8'; |
b063a165 |
230 | |
231 | { |
232 | my $url = $c->uri_for($c->controller->action_for('heart_with_arg'), '♥'); |
233 | is "$url", 'http://localhost/root/a%E2%99%A5/%E2%99%A5'; |
234 | } |
235 | |
236 | { |
237 | my $url = $c->uri_for($c->controller->action_for('heart_with_arg'), ['♥']); |
238 | is "$url", 'http://localhost/root/a%E2%99%A5/%E2%99%A5'; |
239 | } |
dd096a3a |
240 | } |
241 | |
242 | { |
243 | my $res = request "/root/stream_write"; |
00038a21 |
244 | |
dd096a3a |
245 | is $res->code, 200, 'OK'; |
246 | is decode_utf8($res->content), '<p>This is stream_write action ♥</p>', 'correct body'; |
4a64c27b |
247 | is $res->content_charset, 'UTF-8'; |
e5a5e80b |
248 | } |
0ca510f0 |
249 | |
fe1dfeaf |
250 | { |
59e11cd7 |
251 | my $res = request "/root/stream_body_fh"; |
252 | |
253 | is $res->code, 200, 'OK'; |
254 | is decode_utf8($res->content), "<p>This is stream_body_fh action ♥</p>\n", 'correct body'; |
4a64c27b |
255 | is $res->content_charset, 'UTF-8'; |
59e11cd7 |
256 | # Not sure why there is a trailing newline above... its not in catalyst code I can see. Not sure |
257 | # if is a problem or just an artifact of the why the test stuff works - JNAP |
258 | } |
259 | |
260 | { |
7b39dea1 |
261 | my $res = request "/root/stream_write_fh"; |
fe1dfeaf |
262 | |
263 | is $res->code, 200, 'OK'; |
264 | is decode_utf8($res->content), '<p>This is stream_write_fh action ♥</p>', 'correct body'; |
8a79126d |
265 | #is $res->content_length, 41, 'correct length'; |
4a64c27b |
266 | is $res->content_charset, 'UTF-8'; |
fe1dfeaf |
267 | } |
dd096a3a |
268 | |
e8361cf8 |
269 | { |
270 | my $res = request "/root/stream_body_fh2"; |
271 | |
272 | is $res->code, 200, 'OK'; |
273 | is decode_utf8($res->content), "<p>This is stream_body_fh action ♥</p>\n", 'correct body'; |
274 | is $res->content_length, 41, 'correct length'; |
275 | is $res->content_charset, 'UTF-8'; |
276 | } |
277 | |
0ca510f0 |
278 | done_testing; |