Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 625 lines (560 sloc) 24.429 kb
c98e665 @theory Add `log` command.
authored
1 #!/usr/bin/perl -w
2
3 use strict;
4 use warnings;
5 use utf8;
23e9a41 @theory Add `%r`, `%R`, `%x`, and `%X` formats to log.
authored
6 use Test::More tests => 220;
c510535 @theory Complete testing of `log`.
authored
7 #use Test::More 'no_plan';
c98e665 @theory Add `log` command.
authored
8 use App::Sqitch;
9 use Locale::TextDomain qw(App-Sqitch);
10 use Test::NoWarnings;
11 use Test::Exception;
12 use Test::MockModule;
13 use Path::Class;
52f68fc @theory Test named log formats.
authored
14 use Term::ANSIColor qw(color);
c98e665 @theory Add `log` command.
authored
15 use lib 't/lib';
16 use MockOutput;
17
18 my $CLASS = 'App::Sqitch::Command::log';
19 require_ok $CLASS;
20
21 ok my $sqitch = App::Sqitch->new(
22 top_dir => Path::Class::Dir->new('sql'),
c510535 @theory Complete testing of `log`.
authored
23 _engine => 'sqlite',
c98e665 @theory Add `log` command.
authored
24 ), 'Load a sqitch sqitch object';
25 my $config = $sqitch->config;
26 isa_ok my $log = App::Sqitch::Command->load({
27 sqitch => $sqitch,
28 command => 'log',
29 config => $config,
30 }), $CLASS, 'log command';
31
32 can_ok $log, qw(
33 change_pattern
58a9272 @theory Switch term from "actor" to "committer".
authored
34 committer_pattern
3c37fe1 @theory Add `strftime:` and `cldr:` options to `--date-format`.
authored
35 max_count
c98e665 @theory Add `log` command.
authored
36 skip
37 reverse
3c37fe1 @theory Add `strftime:` and `cldr:` options to `--date-format`.
authored
38 abbrev
c98e665 @theory Add `log` command.
authored
39 format
40 date_format
3c37fe1 @theory Add `strftime:` and `cldr:` options to `--date-format`.
authored
41 color
c98e665 @theory Add `log` command.
authored
42 options
43 execute
44 configure
45 );
46
3577a9e @theory Test `log` color configuration.
authored
47 is_deeply [$CLASS->options], [qw(
48 event=s@
58a9272 @theory Switch term from "actor" to "committer".
authored
49 change-pattern|change=s
50 committer-pattern|committer=s
931f9b4 @theory Update `sqitch-log.pod`.
authored
51 format|f=s
52 date-format|date=s
3577a9e @theory Test `log` color configuration.
authored
53 max-count|n=i
54 skip=i
55 reverse!
56 color=s
57 no-color
58 abbrev=i
59 )], 'Options should be correct';
60
c98e665 @theory Add `log` command.
authored
61 ##############################################################################
62 # Test configure().
63 my $cmock = Test::MockModule->new('App::Sqitch::Config');
64
65 # Test date_format validation.
66 is_deeply $CLASS->configure($config, {}), {},
67 'Should get empty hash for no config or options';
68 $cmock->mock( get => 'nonesuch' );
69 throws_ok { $CLASS->configure($config, {}), {} } 'App::Sqitch::X',
70 'Should get error for invalid date format in config';
71 is $@->ident, 'datetime',
72 'Invalid date format error ident should be "datetime"';
73 is $@->message, __x(
74 'Unknown date format "{format}"',
75 format => 'nonesuch',
76 ), 'Invalid date format error message should be correct';
77 $cmock->unmock_all;
78
79 throws_ok { $CLASS->configure($config, { 'date-format' => 'non'}), {} }
80 'App::Sqitch::X',
81 'Should get error for invalid date format in optsions';
82 is $@->ident, 'datetime',
83 'Invalid date format error ident should be "log"';
84 is $@->message, __x(
85 'Unknown date format "{format}"',
86 format => 'non',
87 ), 'Invalid date format error message should be correct';
88
89 # Test format validation.
90 $cmock->mock( get => sub {
91 my ($self, %p) = @_;
92 return 'nonesuch' if $p{key} eq 'log.format';
93 return undef;
94 });
95 throws_ok { $CLASS->configure($config, {}), {} } 'App::Sqitch::X',
96 'Should get error for invalid format in config';
97 is $@->ident, 'log',
98 'Invalid format error ident should be "log"';
99 is $@->message, __x(
100 'Unknown log format "{format}"',
101 format => 'nonesuch',
102 ), 'Invalid format error message should be correct';
103 $cmock->unmock_all;
104
105 throws_ok { $CLASS->configure($config, { format => 'non'}), {} }
106 'App::Sqitch::X',
107 'Should get error for invalid format in optsions';
108 is $@->ident, 'log',
109 'Invalid format error ident should be "log"';
110 is $@->message, __x(
111 'Unknown log format "{format}"',
112 format => 'non',
113 ), 'Invalid format error message should be correct';
114
3577a9e @theory Test `log` color configuration.
authored
115 # Test color configuration.
116 is_deeply$CLASS->configure( $config, {'no-color', 1 } ), {
117 color => 'never'
118 }, 'Configuration should respect --no-color, setting "never"';
119
120 my $config_color = 'auto';
121 $cmock->mock( get => sub {
122 my ($self, %p) = @_;
123 return $config_color if $p{key} eq 'log.color';
124 return undef;
125 });
126
127 my $log_config = {};
128 $cmock->mock( get_section => sub { $log_config } );
129
130 is_deeply $CLASS->configure( $config, {'no-color', 1 } ), {
131 color => 'never'
132 }, 'Configuration should respect --no-color even when configure is set';
133
134 NEVER: {
135 local $ENV{ANSI_COLORS_DISABLED};
136 $config_color = 'never';
137 $log_config = { color => $config_color };
138 is_deeply $CLASS->configure( $config, $log_config ), { color => 'never' },
139 'Configuration should respect color option';
140 ok $ENV{ANSI_COLORS_DISABLED}, 'Colors should be disabled for "never"';
141
142 # Try it with config.
143 delete $ENV{ANSI_COLORS_DISABLED};
144 $log_config = { color => $config_color };
145 is_deeply $CLASS->configure( $config, {} ), { color => 'never' },
146 'Configuration should respect color config';
147 ok $ENV{ANSI_COLORS_DISABLED}, 'Colors should be disabled for "never"';
148 }
149
150 ALWAYS: {
151 local $ENV{ANSI_COLORS_DISABLED};
152 $config_color = 'always';
153 $log_config = { color => $config_color };
154 is_deeply $CLASS->configure( $config, $log_config ), { color => 'always' },
155 'Configuration should respect color option';
156 ok !$ENV{ANSI_COLORS_DISABLED}, 'Colors should be enabled for "always"';
157
158 # Try it with config.
159 delete $ENV{ANSI_COLORS_DISABLED};
160 $log_config = { color => $config_color };
161 is_deeply $CLASS->configure( $config, {} ), { color => 'always' },
162 'Configuration should respect color config';
163 ok !$ENV{ANSI_COLORS_DISABLED}, 'Colors should be enabled for "always"';
164 }
165
166 AUTO: {
167 $config_color = 'auto';
168 $log_config = { color => $config_color };
169 for my $enabled (0, 1) {
170 local $ENV{ANSI_COLORS_DISABLED} = $enabled;
171 is_deeply $CLASS->configure( $config, $log_config ), { color => 'auto' },
172 'Configuration should respect color option';
173 is $ENV{ANSI_COLORS_DISABLED}, $enabled,
174 'Auto color option should change nothing';
175
176 # Try it with config.
177 $log_config = { color => $config_color };
178 is_deeply $CLASS->configure( $config, {} ), { color => 'auto' },
179 'Configuration should respect color config';
180 is $ENV{ANSI_COLORS_DISABLED}, $enabled,
181 'Auto color config should change nothing';
182 }
183 }
184
185 $cmock->unmock_all;
52f68fc @theory Test named log formats.
authored
186
187 ###############################################################################
192f813 @theory Test individual log format codes.
authored
188 # Test named formats.
385f92c @theory Update `log` formats for new metadata.
authored
189 my $cdt = App::Sqitch::DateTime->now;
190 my $pdt = $cdt->clone->subtract(days => 1);
52f68fc @theory Test named log formats.
authored
191 my $event = {
385f92c @theory Update `log` formats for new metadata.
authored
192 event => 'deploy',
193 change_id => '000011112222333444',
194 change => 'lolz',
195 tags => [ '@beta', '@gamma' ],
196 committer_name => 'larry',
197 committer_email => 'larry@example.com',
198 committed_at => $cdt,
4ff5fc9 @theory Integrate new formats into the default formats.
authored
199 planner_name => 'damian',
200 planner_email => 'damian@example.com',
385f92c @theory Update `log` formats for new metadata.
authored
201 planned_at => $pdt,
4ff5fc9 @theory Integrate new formats into the default formats.
authored
202 note => "For the LOLZ.\n\nYou know, funny stuff and cute kittens, right?",
001e728 @theory Add required and conflicting changes to "full" format.
authored
203 requires => [qw(foo bar)],
204 conflicts => []
52f68fc @theory Test named log formats.
authored
205 };
206
4ff5fc9 @theory Integrate new formats into the default formats.
authored
207 my $ciso = $cdt->as_string( format => 'iso' );
208 my $craw = $cdt->as_string( format => 'raw' );
209 my $piso = $pdt->as_string( format => 'iso' );
210 my $praw = $pdt->as_string( format => 'raw' );
52f68fc @theory Test named log formats.
authored
211 for my $spec (
58a9272 @theory Switch term from "actor" to "committer".
authored
212 [ raw => "event deploy\n"
4ff5fc9 @theory Integrate new formats into the default formats.
authored
213 . "change 000011112222333444 (\@beta, \@gamma)\n"
214 . "name lolz\n"
215 . "planner damian <damian\@example.com>\n"
216 . "planned $praw\n"
217 . "committer larry <larry\@example.com>\n"
218 . "committed $craw\n\n"
219 . " For the LOLZ.\n \n You know, funny stuff and cute kittens, right?\n"
52f68fc @theory Test named log formats.
authored
220 ],
4ff5fc9 @theory Integrate new formats into the default formats.
authored
221 [ full => __ 'Change:' . " 000011112222333444 (\@beta, \@gamma)\n"
58a9272 @theory Switch term from "actor" to "committer".
authored
222 . __ 'Event:' . " deploy\n"
223 . __ 'Name:' . " lolz\n"
001e728 @theory Add required and conflicting changes to "full" format.
authored
224 . __ 'Requires: ' . " foo, bar\n"
4ff5fc9 @theory Integrate new formats into the default formats.
authored
225 . __ 'Planner:' . " damian <damian\@example.com>\n"
226 . __ 'Planned:' . " __PDATE__\n"
227 . __ 'Committer:' . " larry <larry\@example.com>\n"
228 . __ 'Committed:' . " __CDATE__\n\n"
229 . " For the LOLZ.\n \n You know, funny stuff and cute kittens, right?\n"
52f68fc @theory Test named log formats.
authored
230 ],
4ff5fc9 @theory Integrate new formats into the default formats.
authored
231 [ long => __ 'Deploy' . " 000011112222333444 (\@beta, \@gamma)\n"
58a9272 @theory Switch term from "actor" to "committer".
authored
232 . __ 'Name:' . " lolz\n"
4ff5fc9 @theory Integrate new formats into the default formats.
authored
233 . __ 'Planner:' . " damian <damian\@example.com>\n"
234 . __ 'Committer:' . " larry <larry\@example.com>\n\n"
235 . " For the LOLZ.\n \n You know, funny stuff and cute kittens, right?\n"
52f68fc @theory Test named log formats.
authored
236 ],
4ff5fc9 @theory Integrate new formats into the default formats.
authored
237 [ medium => __ 'Deploy' . " 000011112222333444\n"
58a9272 @theory Switch term from "actor" to "committer".
authored
238 . __ 'Name:' . " lolz\n"
4ff5fc9 @theory Integrate new formats into the default formats.
authored
239 . __ 'Committer:' . " larry <larry\@example.com>\n"
240 . __ 'Date:' . " __CDATE__\n\n"
241 . " For the LOLZ.\n \n You know, funny stuff and cute kittens, right?\n"
52f68fc @theory Test named log formats.
authored
242 ],
4ff5fc9 @theory Integrate new formats into the default formats.
authored
243 [ short => __ 'Deploy' . " 000011112222333444\n"
244 . __ 'Name:' . " lolz\n"
245 . __ 'Committer:' . " larry <larry\@example.com>\n\n"
246 . " For the LOLZ.\n",
52f68fc @theory Test named log formats.
authored
247 ],
4ff5fc9 @theory Integrate new formats into the default formats.
authored
248 [ oneline => '000011112222333444 deploy lolz For the LOLZ.' ],
52f68fc @theory Test named log formats.
authored
249 ) {
250 my $format = $CLASS->configure( $config, { format => $spec->[0] } )->{format};
251 ok my $log = $CLASS->new( sqitch => $sqitch, format => $format ),
252 qq{Instantiate with format "$spec->[0]"};
4ff5fc9 @theory Integrate new formats into the default formats.
authored
253 (my $exp = $spec->[1]) =~ s/__CDATE__/$ciso/;
254 $exp =~ s/__PDATE__/$piso/;
52f68fc @theory Test named log formats.
authored
255 is $log->formatter->format( $log->format, $event ), $exp,
256 qq{Format "$spec->[0]" should output correctly};
257
4ff5fc9 @theory Integrate new formats into the default formats.
authored
258 if ($spec->[1] =~ /__CDATE__/) {
52f68fc @theory Test named log formats.
authored
259 # Test different date formats.
260 for my $date_format (qw(rfc long medium)) {
261 ok my $log = $CLASS->new(
262 sqitch => $sqitch,
263 format => $format,
264 date_format => $date_format,
265 ), qq{Instantiate with format "$spec->[0]" and date format "$date_format"};
385f92c @theory Update `log` formats for new metadata.
authored
266 my $date = $cdt->as_string( format => $date_format );
4ff5fc9 @theory Integrate new formats into the default formats.
authored
267 (my $exp = $spec->[1]) =~ s/__CDATE__/$date/;
268 $date = $pdt->as_string( format => $date_format );
269 $exp =~ s/__PDATE__/$date/;
52f68fc @theory Test named log formats.
authored
270 is $log->formatter->format( $log->format, $event ), $exp,
271 qq{Format "$spec->[0]" and date format "$date_format" should output correctly};
272 }
273 }
274
192f813 @theory Test individual log format codes.
authored
275 if ($spec->[1] =~ s/\s+[(]?[@]beta,\s+[@]gamma[)]?//) {
276 # Test without tags.
277 local $event->{tags} = [];
4ff5fc9 @theory Integrate new formats into the default formats.
authored
278 (my $exp = $spec->[1]) =~ s/__CDATE__/$ciso/;
279 $exp =~ s/__PDATE__/$piso/;
192f813 @theory Test individual log format codes.
authored
280 is $log->formatter->format( $log->format, $event ), $exp,
281 qq{Format "$spec->[0]" should output correctly without tags};
282 }
283 }
284
285 ###############################################################################
286 # Test all formatting characters.
385f92c @theory Update `log` formats for new metadata.
authored
287 my $local_cdt = $cdt->clone;
288 $local_cdt->set_time_zone('local');
289 my $local_pdt = $pdt->clone;
290 $local_pdt->set_time_zone('local');
291
192f813 @theory Test individual log format codes.
authored
292 my $formatter = $log->formatter;
293 for my $spec (
294 ['%e', { event => 'deploy' }, 'deploy' ],
295 ['%e', { event => 'revert' }, 'revert' ],
296 ['%e', { event => 'fail' }, 'fail' ],
297
298 ['%L', { event => 'deploy' }, __ 'Deploy' ],
299 ['%L', { event => 'revert' }, __ 'Revert' ],
300 ['%L', { event => 'fail' }, __ 'Fail' ],
301
302 ['%l', { event => 'deploy' }, __ 'deploy' ],
303 ['%l', { event => 'revert' }, __ 'revert' ],
304 ['%l', { event => 'fail' }, __ 'fail' ],
305
58a9272 @theory Switch term from "actor" to "committer".
authored
306 ['%{event}_', {}, __ 'Event: ' ],
307 ['%{change}_', {}, __ 'Change: ' ],
308 ['%{committer}_', {}, __ 'Committer:' ],
385f92c @theory Update `log` formats for new metadata.
authored
309 ['%{planner}_', {}, __ 'Planner: ' ],
58a9272 @theory Switch term from "actor" to "committer".
authored
310 ['%{by}_', {}, __ 'By: ' ],
311 ['%{date}_', {}, __ 'Date: ' ],
385f92c @theory Update `log` formats for new metadata.
authored
312 ['%{committed}_', {}, __ 'Committed:' ],
313 ['%{planned}_', {}, __ 'Planned: ' ],
58a9272 @theory Switch term from "actor" to "committer".
authored
314 ['%{name}_', {}, __ 'Name: ' ],
385f92c @theory Update `log` formats for new metadata.
authored
315 ['%{email}_', {}, __ 'Email: ' ],
23e9a41 @theory Add `%r`, `%R`, `%x`, and `%X` formats to log.
authored
316 ['%{requires}_', {}, __ 'Requires: ' ],
317 ['%{conflicts}_', {}, __ 'Conflicts:' ],
192f813 @theory Test individual log format codes.
authored
318
319 ['%H', { change_id => '123456789' }, '123456789' ],
320 ['%h', { change_id => '123456789' }, '123456789' ],
321 ['%{5}h', { change_id => '123456789' }, '12345' ],
322 ['%{7}h', { change_id => '123456789' }, '1234567' ],
323
385f92c @theory Update `log` formats for new metadata.
authored
324 ['%n', { change => 'foo' }, 'foo'],
325 ['%n', { change => 'bar' }, 'bar'],
326
4ff5fc9 @theory Integrate new formats into the default formats.
authored
327 ['%c', { committer_name => 'larry', committer_email => 'larry@example.com' }, 'larry <larry@example.com>'],
385f92c @theory Update `log` formats for new metadata.
authored
328 ['%{n}c', { committer_name => 'damian' }, 'damian'],
329 ['%{name}c', { committer_name => 'chip' }, 'chip'],
330 ['%{e}c', { committer_email => 'larry@example.com' }, 'larry@example.com'],
331 ['%{email}c', { committer_email => 'damian@example.com' }, 'damian@example.com'],
332
333 ['%{date}c', { committed_at => $cdt }, $cdt->as_string( format => 'iso' ) ],
334 ['%{date:rfc}c', { committed_at => $cdt }, $cdt->as_string( format => 'rfc' ) ],
335 ['%{d:long}c', { committed_at => $cdt }, $cdt->as_string( format => 'long' ) ],
336 ["%{d:cldr:HH'h' mm'm'}c", { committed_at => $cdt }, $local_cdt->format_cldr( q{HH'h' mm'm'} ) ],
337 ["%{d:strftime:%a at %H:%M:%S}c", { committed_at => $cdt }, $local_cdt->strftime('%a at %H:%M:%S') ],
338
4ff5fc9 @theory Integrate new formats into the default formats.
authored
339 ['%p', { planner_name => 'larry', planner_email => 'larry@example.com' }, 'larry <larry@example.com>'],
385f92c @theory Update `log` formats for new metadata.
authored
340 ['%{n}p', { planner_name => 'damian' }, 'damian'],
341 ['%{name}p', { planner_name => 'chip' }, 'chip'],
342 ['%{e}p', { planner_email => 'larry@example.com' }, 'larry@example.com'],
343 ['%{email}p', { planner_email => 'damian@example.com' }, 'damian@example.com'],
344
345 ['%{date}p', { planned_at => $pdt }, $pdt->as_string( format => 'iso' ) ],
346 ['%{date:rfc}p', { planned_at => $pdt }, $pdt->as_string( format => 'rfc' ) ],
347 ['%{d:long}p', { planned_at => $pdt }, $pdt->as_string( format => 'long' ) ],
348 ["%{d:cldr:HH'h' mm'm'}p", { planned_at => $pdt }, $local_pdt->format_cldr( q{HH'h' mm'm'} ) ],
349 ["%{d:strftime:%a at %H:%M:%S}p", { planned_at => $pdt }, $local_pdt->strftime('%a at %H:%M:%S') ],
192f813 @theory Test individual log format codes.
authored
350
351 ['%t', { tags => [] }, '' ],
352 ['%t', { tags => ['@foo'] }, ' @foo' ],
353 ['%t', { tags => ['@foo', '@bar'] }, ' @foo, @bar' ],
354 ['%{|}t', { tags => [] }, '' ],
355 ['%{|}t', { tags => ['@foo'] }, ' @foo' ],
356 ['%{|}t', { tags => ['@foo', '@bar'] }, ' @foo|@bar' ],
357
358 ['%T', { tags => [] }, '' ],
359 ['%T', { tags => ['@foo'] }, ' (@foo)' ],
360 ['%T', { tags => ['@foo', '@bar'] }, ' (@foo, @bar)' ],
361 ['%{|}T', { tags => [] }, '' ],
362 ['%{|}T', { tags => ['@foo'] }, ' (@foo)' ],
363 ['%{|}T', { tags => ['@foo', '@bar'] }, ' (@foo|@bar)' ],
364
23e9a41 @theory Add `%r`, `%R`, `%x`, and `%X` formats to log.
authored
365 ['%r', { requires => [] }, '' ],
366 ['%r', { requires => ['foo'] }, ' foo' ],
367 ['%r', { requires => ['foo', 'bar'] }, ' foo, bar' ],
368 ['%{|}r', { requires => [] }, '' ],
369 ['%{|}r', { requires => ['foo'] }, ' foo' ],
370 ['%{|}r', { requires => ['foo', 'bar'] }, ' foo|bar' ],
371
372 ['%R', { requires => [] }, '' ],
001e728 @theory Add required and conflicting changes to "full" format.
authored
373 ['%R', { requires => ['foo'] }, __('Requires: ') . " foo\n" ],
374 ['%R', { requires => ['foo', 'bar'] }, __('Requires: ') . " foo, bar\n" ],
23e9a41 @theory Add `%r`, `%R`, `%x`, and `%X` formats to log.
authored
375 ['%{|}R', { requires => [] }, '' ],
001e728 @theory Add required and conflicting changes to "full" format.
authored
376 ['%{|}R', { requires => ['foo'] }, __('Requires: ') . " foo\n" ],
377 ['%{|}R', { requires => ['foo', 'bar'] }, __('Requires: ') . " foo|bar\n" ],
23e9a41 @theory Add `%r`, `%R`, `%x`, and `%X` formats to log.
authored
378
379 ['%x', { conflicts => [] }, '' ],
380 ['%x', { conflicts => ['foo'] }, ' foo' ],
381 ['%x', { conflicts => ['foo', 'bax'] }, ' foo, bax' ],
382 ['%{|}x', { conflicts => [] }, '' ],
383 ['%{|}x', { conflicts => ['foo'] }, ' foo' ],
384 ['%{|}x', { conflicts => ['foo', 'bax'] }, ' foo|bax' ],
385
386 ['%X', { conflicts => [] }, '' ],
001e728 @theory Add required and conflicting changes to "full" format.
authored
387 ['%X', { conflicts => ['foo'] }, __('Conflicts:') . " foo\n" ],
388 ['%X', { conflicts => ['foo', 'bar'] }, __('Conflicts:') . " foo, bar\n" ],
23e9a41 @theory Add `%r`, `%R`, `%x`, and `%X` formats to log.
authored
389 ['%{|}X', { conflicts => [] }, '' ],
001e728 @theory Add required and conflicting changes to "full" format.
authored
390 ['%{|}X', { conflicts => ['foo'] }, __('Conflicts:') . " foo\n" ],
391 ['%{|}X', { conflicts => ['foo', 'bar'] }, __('Conflicts:') . " foo|bar\n" ],
23e9a41 @theory Add `%r`, `%R`, `%x`, and `%X` formats to log.
authored
392
192f813 @theory Test individual log format codes.
authored
393 ['%{yellow}C', {}, '' ],
f7ced1f @theory Add `:event` arg to `%C` format.
authored
394 ['%{:event}C', { event => 'deploy' }, '' ],
385f92c @theory Update `log` formats for new metadata.
authored
395 ['%v', {}, "\n" ],
396 ['%%', {}, '%' ],
397
7159c43 @theory Add the %s, %b, and %B formats.
authored
398 ['%s', { note => 'hi there' }, 'hi there' ],
399 ['%s', { note => "hi there\nyo" }, 'hi there' ],
400 ['%s', { note => "subject line\n\nfirst graph\n\nsecond graph\n\n" }, 'subject line' ],
4ff5fc9 @theory Integrate new formats into the default formats.
authored
401 ['%{ }s', { note => 'hi there' }, ' hi there' ],
402 ['%{xx}s', { note => 'hi there' }, 'xxhi there' ],
7159c43 @theory Add the %s, %b, and %B formats.
authored
403
404 ['%b', { note => 'hi there' }, '' ],
405 ['%b', { note => "hi there\nyo" }, 'yo' ],
406 ['%b', { note => "subject line\n\nfirst graph\n\nsecond graph\n\n" }, "first graph\n\nsecond graph\n\n" ],
4ff5fc9 @theory Integrate new formats into the default formats.
authored
407 ['%{ }b', { note => 'hi there' }, '' ],
408 ['%{xxx }b', { note => "hi there\nyo" }, "xxx yo" ],
409 ['%{x}b', { note => "subject line\n\nfirst graph\n\nsecond graph\n\n" }, "xfirst graph\nx\nxsecond graph\nx\n" ],
410 ['%{ }b', { note => "hi there\r\nyo" }, " yo" ],
7159c43 @theory Add the %s, %b, and %B formats.
authored
411
412 ['%B', { note => 'hi there' }, 'hi there' ],
413 ['%B', { note => "hi there\nyo" }, "hi there\nyo" ],
414 ['%B', { note => "subject line\n\nfirst graph\n\nsecond graph\n\n" }, "subject line\n\nfirst graph\n\nsecond graph\n\n" ],
415 ['%{ }B', { note => 'hi there' }, ' hi there' ],
416 ['%{xxx }B', { note => "hi there\nyo" }, "xxx hi there\nxxx yo" ],
417 ['%{x}B', { note => "subject line\n\nfirst graph\n\nsecond graph\n\n" }, "xsubject line\nx\nxfirst graph\nx\nxsecond graph\nx\n" ],
418 ['%{ }B', { note => "hi there\r\nyo" }, " hi there\r\n yo" ],
419
192f813 @theory Test individual log format codes.
authored
420 ) {
421 (my $desc = $spec->[2]) =~ s/\n/[newline]/g;
422 is $formatter->format( $spec->[0], $spec->[1] ), $spec->[2],
423 qq{Format "$spec->[0]" should output "$desc"};
424 }
425
426 throws_ok { $formatter->format( '%_', {} ) } 'App::Sqitch::X',
427 'Should get exception for format "%_"';
428 is $@->ident, 'log', '%_ error ident should be "log"';
429 is $@->message, __ 'No label passed to the _ format',
430 '%_ error message should be correct';
431
432 ok $log = $CLASS->new( sqitch => $sqitch, abbrev => 4 ),
433 'Instantiate with abbrev => 4';
434 is $log->formatter->format( '%h', { change_id => '123456789' } ),
435 '1234', '%h should respect abbrev';
436 is $log->formatter->format( '%H', { change_id => '123456789' } ),
437 '123456789', '%H should not respect abbrev';
438
439 ok $log = $CLASS->new( sqitch => $sqitch, date_format => 'rfc' ),
440 'Instantiate with date_format => "rfc"';
385f92c @theory Update `log` formats for new metadata.
authored
441 is $log->formatter->format( '%{date}c', { committed_at => $cdt } ),
442 $cdt->as_string( format => 'rfc' ),
443 '%{date}c should respect the date_format attribute';
444 is $log->formatter->format( '%{d:iso}c', { committed_at => $cdt } ),
445 $cdt->as_string( format => 'iso' ),
446 '%{iso}c should override the date_format attribute';
192f813 @theory Test individual log format codes.
authored
447
448 delete $ENV{ANSI_COLORS_DISABLED};
449 for my $color (qw(yellow red blue cyan magenta)) {
450 is $formatter->format( "%{$color}C", {} ), color($color),
451 qq{Format "%{$color}C" should output }
452 . color($color) . $color . color('reset');
52f68fc @theory Test named log formats.
authored
453 }
192f813 @theory Test individual log format codes.
authored
454
4ff5fc9 @theory Integrate new formats into the default formats.
authored
455 for my $spec (
f7ced1f @theory Add `:event` arg to `%C` format.
authored
456 [ ':event', { event => 'deploy' }, 'green', 'deploy' ],
457 [ ':event', { event => 'revert' }, 'blue', 'revert' ],
458 [ ':event', { event => 'fail' }, 'red', 'fail' ],
4ff5fc9 @theory Integrate new formats into the default formats.
authored
459 ) {
f7ced1f @theory Add `:event` arg to `%C` format.
authored
460 is $formatter->format( "%{$spec->[0]}C", $spec->[1] ), color($spec->[2]),
461 qq{Format "%{$spec->[0]}C" on "$spec->[3]" should output }
462 . color($spec->[2]) . $spec->[2] . color('reset');
4ff5fc9 @theory Integrate new formats into the default formats.
authored
463 }
464
465 # Make sure other colors work.
466 my $yellow = color('yellow') . '%s' . color('reset');
467 my $green = color('green') . '%s' . color('reset');
001e728 @theory Add required and conflicting changes to "full" format.
authored
468 $event->{conflicts} = [qw(dr_evil)];
4ff5fc9 @theory Integrate new formats into the default formats.
authored
469 for my $spec (
470 [ full => sprintf($yellow, __ 'Change:' . ' 000011112222333444')
471 . " (\@beta, \@gamma)\n"
472 . __ 'Event:' . " " . sprintf($green, 'deploy'). "\n"
473 . __ 'Name:' . " lolz\n"
001e728 @theory Add required and conflicting changes to "full" format.
authored
474 . __ 'Requires: ' . " foo, bar\n"
475 . __ 'Conflicts: ' . "dr_evil\n"
4ff5fc9 @theory Integrate new formats into the default formats.
authored
476 . __ 'Planner:' . " damian <damian\@example.com>\n"
477 . __ 'Planned:' . " __PDATE__\n"
478 . __ 'Committer:' . " larry <larry\@example.com>\n"
479 . __ 'Committed:' . " __CDATE__\n\n"
480 . " For the LOLZ.\n \n You know, funny stuff and cute kittens, right?\n"
481 ],
482 [ long => sprintf($green, __ 'Deploy') . ' ' . sprintf($yellow, '000011112222333444')
483 . " (\@beta, \@gamma)\n"
484 . __ 'Name:' . " lolz\n"
485 . __ 'Planner:' . " damian <damian\@example.com>\n"
486 . __ 'Committer:' . " larry <larry\@example.com>\n\n"
487 . " For the LOLZ.\n \n You know, funny stuff and cute kittens, right?\n"
488 ],
489 [ medium => sprintf($green, __ 'Deploy') . ' ' . sprintf($yellow, '000011112222333444') . "\n"
490 . __ 'Name:' . " lolz\n"
491 . __ 'Committer:' . " larry <larry\@example.com>\n"
492 . __ 'Date:' . " __CDATE__\n\n"
493 . " For the LOLZ.\n \n You know, funny stuff and cute kittens, right?\n"
494 ],
495 [ short => sprintf($green, __ 'Deploy') . ' ' . sprintf($yellow, '000011112222333444') . "\n"
496 . __ 'Name:' . " lolz\n"
497 . __ 'Committer:' . " larry <larry\@example.com>\n\n"
498 . " For the LOLZ.\n",
499 ],
500 [ oneline => sprintf "$yellow $green %s %s", '000011112222333444', __('deploy'), 'lolz', 'For the LOLZ.' ],
501 ) {
502 my $format = $CLASS->configure( $config, { format => $spec->[0] } )->{format};
503 ok my $log = $CLASS->new( sqitch => $sqitch, format => $format ),
504 qq{Instantiate with format "$spec->[0]" again};
505 (my $exp = $spec->[1]) =~ s/__CDATE__/$ciso/;
506 $exp =~ s/__PDATE__/$piso/;
507 is $log->formatter->format( $log->format, $event ), $exp,
508 qq{Format "$spec->[0]" should output correctly with color};
509 }
510
192f813 @theory Test individual log format codes.
authored
511 throws_ok { $formatter->format( '%{BLUELOLZ}C', {} ) } 'App::Sqitch::X',
512 'Should get an error for an invalid color';
513 is $@->ident, 'log', 'Invalid color error ident should be "log"';
514 is $@->message, __x(
515 '{color} is not a valid ANSI color', color => 'BLUELOLZ'
516 ), 'Invalid color error message should be correct';
c510535 @theory Complete testing of `log`.
authored
517
518 ##############################################################################
519 # Test execute().
520 my $emock = Test::MockModule->new('App::Sqitch::Engine::sqlite');
521 $emock->mock(destination => 'flipr');
522
523 # First test for uninitialized DB.
524 my $init = 0;
525 $emock->mock(initialized => sub { $init });
526 throws_ok { $log->execute } 'App::Sqitch::X',
527 'Should get exception for unititialied db';
528 is $@->ident, 'log', 'Uninit db error ident should be "log"';
529 is $@->exitval, 1, 'Uninit db exit val should be 1';
530 is $@->message, __x(
531 'Database {db} has not been initilized for Sqitch',
532 db => 'flipr',
533 ), 'Uninit db error message should be correct';
534
535 # Next, test for no events.
536 $init = 1;
537 my @events;
538 my $iter = sub { shift @events };
539 my $search_args;
540 $emock->mock(search_events => sub {
541 shift;
542 $search_args = [@_];
543 return $iter;
544 });
545 throws_ok { $log->execute } 'App::Sqitch::X',
546 'Should get error for empty event table';
547 is $@->ident, 'log', 'no events error ident should be "log"';
548 is $@->exitval, 1, 'no events exit val should be 1';
549 is $@->message, __x(
550 'No events logged to {db}',
551 db => 'flipr',
552 ), 'no events error message should be correct';
553 is_deeply $search_args, [limit => 1],
554 'Search should have been limited to one row';
555
556 # Okay, let's add some events.
557 push @events => {}, $event;
558 ok $log->execute, 'Execute log';
559 is_deeply $search_args, [
560 event => undef,
561 change => undef,
58a9272 @theory Switch term from "actor" to "committer".
authored
562 committer => undef,
c510535 @theory Complete testing of `log`.
authored
563 limit => undef,
564 offset => undef,
565 direction => 'DESC'
566 ], 'The proper args should have been passed to search_events';
567
568 is_deeply +MockOutput->get_page, [
4143086 @theory Show database from which log output comes.
authored
569 [__x 'On database {db}', db => 'flipr'],
c510535 @theory Complete testing of `log`.
authored
570 [ $log->formatter->format( $log->format, $event ) ],
571 ], 'The change should have been paged';
572
573 # Set attributes and add more events.
574 my $event2 = {
4ff5fc9 @theory Integrate new formats into the default formats.
authored
575 event => 'revert',
576 change_id => '84584584359345',
577 change => 'barf',
578 tags => [],
579 committer_name => 'theory',
580 committer_email => 'theory@example.com',
581 committed_at => $cdt,
582 note => 'Oh man this was a bad idea',
c510535 @theory Complete testing of `log`.
authored
583 };
584 push @events => {}, $event, $event2;
585 isa_ok $log = $CLASS->new(
58a9272 @theory Switch term from "actor" to "committer".
authored
586 sqitch => $sqitch,
587 event => [qw(revert fail)],
588 change_pattern => '.+',
589 committer_pattern => '.+',
590 max_count => 10,
591 skip => 5,
592 reverse => 1,
c510535 @theory Complete testing of `log`.
authored
593 ), $CLASS, 'log with attributes';
594
595 ok $log->execute, 'Execute log with attributes';
596 is_deeply $search_args, [
597 event => [qw(revert fail)],
598 change => '.+',
58a9272 @theory Switch term from "actor" to "committer".
authored
599 committer => '.+',
c510535 @theory Complete testing of `log`.
authored
600 limit => 10,
601 offset => 5,
602 direction => 'ASC'
603 ], 'All params should have been passed to search_events';
604
605 is_deeply +MockOutput->get_page, [
4143086 @theory Show database from which log output comes.
authored
606 [__x 'On database {db}', db => 'flipr'],
c510535 @theory Complete testing of `log`.
authored
607 [ $log->formatter->format( $log->format, $event ) ],
608 [ $log->formatter->format( $log->format, $event2 ) ],
609 ], 'Both changes should have been paged';
610
611 # Make sure we catch bad format codes.
612 isa_ok $log = $CLASS->new(
613 sqitch => $sqitch,
614 format => '%Z',
615 ), $CLASS, 'log with bad format';
616
617 push @events, {}, $event;
618 throws_ok { $log->execute } 'App::Sqitch::X',
619 'Should get an exception for a bad format code';
620 is $@->ident, 'log',
621 'bad format code format error ident should be "log"';
622 is $@->message, __x(
623 'Unknown log format code "{code}"', code => 'Z',
624 ), 'bad format code format error message should be correct';
Something went wrong with that request. Please try again.