on fa72f86 help sign in
bat/tests/integration_tests.rs
1059 lines 26 kB history raw
1use assert_cmd::assert::OutputAssertExt;
2use assert_cmd::cargo::CommandCargoExt;
3use predicates::{prelude::predicate, str::PredicateStrExt};
4use serial_test::serial;
5use std::fs::File;
6use std::path::Path;
7use std::process::{Command, Stdio};
8use std::str::from_utf8;
10#[cfg(unix)]
11use std::time::Duration;
13mod utils;
14use utils::mocked_pagers;
16const EXAMPLES_DIR: &str = "tests/examples";
18#[cfg(unix)]
19const SAFE_CHILD_PROCESS_CREATION_TIME: Duration = Duration::from_millis(100);
21#[cfg(unix)]
22const CHILD_WAIT_TIMEOUT: Duration = Duration::from_secs(15);
24fn bat_raw_command() -> Command {
25 let mut cmd = Command::cargo_bin("bat").unwrap();
26 cmd.current_dir("tests/examples");
27 cmd.env_remove("PAGER");
28 cmd.env_remove("BAT_PAGER");
29 cmd.env_remove("BAT_CONFIG_PATH");
30 cmd.env_remove("BAT_STYLE");
31 cmd.env_remove("BAT_THEME");
32 cmd.env_remove("BAT_TABS");
33 cmd
36fn bat_with_config() -> assert_cmd::Command {
37 assert_cmd::Command::from_std(bat_raw_command())
40fn bat() -> assert_cmd::Command {
41 let mut cmd = bat_with_config();
42 cmd.arg("--no-config");
43 cmd
46#[test]
47fn basic() {
48 bat()
49 .arg("test.txt")
50 .assert()
51 .success()
52 .stdout("hello world\n")
53 .stderr("");
56#[test]
57fn stdin() {
58 bat()
59 .write_stdin("foo\nbar\n")
60 .assert()
61 .success()
62 .stdout("foo\nbar\n");
65#[test]
66fn concatenate() {
67 bat()
68 .arg("test.txt")
69 .arg("test.txt")
70 .assert()
71 .success()
72 .stdout("hello world\nhello world\n");
75#[test]
76fn concatenate_stdin() {
77 bat()
78 .arg("test.txt")
79 .arg("-")
80 .arg("test.txt")
81 .write_stdin("stdin\n")
82 .assert()
83 .success()
84 .stdout("hello world\nstdin\nhello world\n");
87#[test]
88fn concatenate_empty_first() {
89 bat()
90 .arg("empty.txt")
91 .arg("test.txt")
92 .assert()
93 .success()
94 .stdout("hello world\n");
97#[test]
98fn concatenate_empty_last() {
99 bat()
100 .arg("test.txt")
101 .arg("empty.txt")
102 .assert()
103 .success()
104 .stdout("hello world\n");
107#[test]
108fn concatenate_empty_both() {
109 bat()
110 .arg("empty.txt")
111 .arg("empty.txt")
112 .assert()
113 .success()
114 .stdout("");
117#[test]
118fn concatenate_empty_between() {
119 bat()
120 .arg("test.txt")
121 .arg("empty.txt")
122 .arg("test.txt")
123 .assert()
124 .success()
125 .stdout("hello world\nhello world\n");
128#[test]
129fn concatenate_empty_first_and_last() {
130 bat()
131 .arg("empty.txt")
132 .arg("test.txt")
133 .arg("empty.txt")
134 .assert()
135 .success()
136 .stdout("hello world\n");
139#[test]
140fn concatenate_single_line() {
141 bat()
142 .arg("single-line.txt")
143 .arg("single-line.txt")
144 .assert()
145 .success()
146 .stdout("Single LineSingle Line");
149#[test]
150fn concatenate_single_line_empty() {
151 bat()
152 .arg("single-line.txt")
153 .arg("empty.txt")
154 .arg("single-line.txt")
155 .assert()
156 .success()
157 .stdout("Single LineSingle Line");
160#[test]
161fn line_numbers() {
162 bat()
163 .arg("multiline.txt")
164 .arg("--style=numbers")
165 .arg("--decorations=always")
166 .assert()
167 .success()
168 .stdout(" 1 line 1\n 2 line 2\n 3 line 3\n 4 line 4\n");
171#[test]
172fn line_range_2_3() {
173 bat()
174 .arg("multiline.txt")
175 .arg("--line-range=2:3")
176 .assert()
177 .success()
178 .stdout("line 2\nline 3\n");
181#[test]
182fn line_range_first_two() {
183 bat()
184 .arg("multiline.txt")
185 .arg("--line-range=:2")
186 .assert()
187 .success()
188 .stdout("line 1\nline 2\n");
191#[test]
192fn line_range_last_3() {
193 bat()
194 .arg("multiline.txt")
195 .arg("--line-range=2:")
196 .assert()
197 .success()
198 .stdout("line 2\nline 3\nline 4\n");
201#[test]
202fn line_range_multiple() {
203 bat()
204 .arg("multiline.txt")
205 .arg("--line-range=1:2")
206 .arg("--line-range=4:4")
207 .assert()
208 .success()
209 .stdout("line 1\nline 2\nline 4\n");
212#[test]
213fn basic_io_cycle() {
214 let file_out = Stdio::from(File::open("tests/examples/cycle.txt").unwrap());
215 bat_raw_command()
216 .arg("test.txt")
217 .arg("cycle.txt")
218 .stdout(file_out)
219 .assert()
220 .failure();
223#[test]
224fn stdin_to_stdout_cycle() {
225 let file_out = Stdio::from(File::open("tests/examples/cycle.txt").unwrap());
226 let file_in = Stdio::from(File::open("tests/examples/cycle.txt").unwrap());
227 bat_raw_command()
228 .stdin(file_in)
229 .arg("test.txt")
230 .arg("-")
231 .stdout(file_out)
232 .assert()
233 .failure();
236#[cfg(unix)]
237#[test]
238fn no_args_doesnt_break() {
239 use std::io::Write;
240 use std::os::unix::io::FromRawFd;
241 use std::thread;
243 use clircle::nix::pty::{openpty, OpenptyResult};
244 use wait_timeout::ChildExt;
246 // To simulate bat getting started from the shell, a process is created with stdin and stdout
247 // as the slave end of a pseudo terminal. Although both point to the same "file", bat should
248 // not exit, because in this case it is safe to read and write to the same fd, which is why
249 // this test exists.
250 let OpenptyResult { master, slave } = openpty(None, None).expect("Couldn't open pty.");
251 let mut master = unsafe { File::from_raw_fd(master) };
252 let stdin = unsafe { Stdio::from_raw_fd(slave) };
253 let stdout = unsafe { Stdio::from_raw_fd(slave) };
255 let mut child = bat_raw_command()
256 .stdin(stdin)
257 .stdout(stdout)
258 .spawn()
259 .expect("Failed to start.");
261 // Some time for the child process to start and to make sure, that we can poll the exit status.
262 // Although this waiting period is not necessary, it is best to keep it in and be absolutely
263 // sure, that the try_wait does not error later.
264 thread::sleep(SAFE_CHILD_PROCESS_CREATION_TIME);
266 // The child process should be running and waiting for input,
267 // therefore no exit status should be available.
268 let exit_status = child
269 .try_wait()
270 .expect("Error polling exit status, this should never happen.");
271 assert!(exit_status.is_none());
273 // Write Ctrl-D (end of transmission) to the pty.
274 master
275 .write_all(&[0x04])
276 .expect("Couldn't write EOT character to master end.");
278 let exit_status = child
279 .wait_timeout(CHILD_WAIT_TIMEOUT)
280 .expect("Error polling exit status, this should never happen.")
281 .expect("Exit status not set, but the child should have exited already.");
283 assert!(exit_status.success());
286#[test]
287fn tabs_numbers() {
288 bat()
289 .arg("tabs.txt")
290 .arg("--tabs=4")
291 .arg("--style=numbers")
292 .arg("--decorations=always")
293 .assert()
294 .success()
295 .stdout(
296 " 1 1 2 3 4
297 2 1 ?
298 3 22 ?
299 4 333 ?
300 5 4444 ?
301 6 55555 ?
302 7 666666 ?
303 8 7777777 ?
304 9 88888888 ?
305",
306 );
309#[test]
310fn tabs_passthrough_wrapped() {
311 bat()
312 .arg("tabs.txt")
313 .arg("--tabs=0")
314 .arg("--style=plain")
315 .arg("--decorations=always")
316 .assert()
317 .success()
318 .stdout(
319 " 1 2 3 4
3201 ?
32122 ?
322333 ?
3234444 ?
32455555 ?
325666666 ?
3267777777 ?
32788888888 ?
328",
329 );
332#[test]
333fn tabs_4_wrapped() {
334 bat()
335 .arg("tabs.txt")
336 .arg("--tabs=4")
337 .arg("--style=plain")
338 .arg("--decorations=always")
339 .assert()
340 .success()
341 .stdout(
342 " 1 2 3 4
3431 ?
34422 ?
345333 ?
3464444 ?
34755555 ?
348666666 ?
3497777777 ?
35088888888 ?
351",
352 );
355#[test]
356fn tabs_8_wrapped() {
357 bat()
358 .arg("tabs.txt")
359 .arg("--tabs=8")
360 .arg("--style=plain")
361 .arg("--decorations=always")
362 .assert()
363 .success()
364 .stdout(
365 " 1 2 3 4
3661 ?
36722 ?
368333 ?
3694444 ?
37055555 ?
371666666 ?
3727777777 ?
37388888888 ?
374",
375 );
378#[test]
379fn tabs_passthrough() {
380 bat()
381 .arg("tabs.txt")
382 .arg("--tabs=0")
383 .arg("--style=plain")
384 .arg("--decorations=always")
385 .assert()
386 .success()
387 .stdout(
388 " 1 2 3 4
3891 ?
39022 ?
391333 ?
3924444 ?
39355555 ?
394666666 ?
3957777777 ?
39688888888 ?
397",
398 );
401#[test]
402fn tabs_4() {
403 bat()
404 .arg("tabs.txt")
405 .arg("--tabs=4")
406 .arg("--style=plain")
407 .arg("--decorations=always")
408 .assert()
409 .success()
410 .stdout(
411 " 1 2 3 4
4121 ?
41322 ?
414333 ?
4154444 ?
41655555 ?
417666666 ?
4187777777 ?
41988888888 ?
420",
421 );
424#[test]
425fn tabs_8() {
426 bat()
427 .arg("tabs.txt")
428 .arg("--tabs=8")
429 .arg("--style=plain")
430 .arg("--decorations=always")
431 .assert()
432 .success()
433 .stdout(
434 " 1 2 3 4
4351 ?
43622 ?
437333 ?
4384444 ?
43955555 ?
440666666 ?
4417777777 ?
44288888888 ?
443",
444 );
447#[test]
448fn fail_non_existing() {
449 bat().arg("non-existing-file").assert().failure();
452#[test]
453fn fail_directory() {
454 bat().arg("sub_directory").assert().failure();
457#[test]
458fn do_not_exit_directory() {
459 bat()
460 .arg("sub_directory")
461 .arg("test.txt")
462 .assert()
463 .stdout("hello world\n")
464 .failure();
467#[test]
468fn pager_basic() {
469 bat()
470 .env("PAGER", "echo pager-output")
471 .arg("--paging=always")
472 .arg("test.txt")
473 .assert()
474 .success()
475 .stdout(predicate::eq("pager-output\n").normalize());
478#[test]
479fn pager_overwrite() {
480 bat()
481 .env("PAGER", "echo other-pager")
482 .env("BAT_PAGER", "echo pager-output")
483 .arg("--paging=always")
484 .arg("test.txt")
485 .assert()
486 .success()
487 .stdout(predicate::eq("pager-output\n").normalize());
490#[test]
491fn pager_disable() {
492 bat()
493 .env("PAGER", "echo other-pager")
494 .env("BAT_PAGER", "")
495 .arg("--paging=always")
496 .arg("test.txt")
497 .assert()
498 .success()
499 .stdout(predicate::eq("hello world\n").normalize());
502#[test]
503fn env_var_pager_value_bat() {
504 bat()
505 .env("PAGER", "bat")
506 .arg("--paging=always")
507 .arg("test.txt")
508 .assert()
509 .success()
510 .stdout(predicate::eq("hello world\n").normalize());
513#[test]
514fn env_var_bat_pager_value_bat() {
515 bat()
516 .env("BAT_PAGER", "bat")
517 .arg("--paging=always")
518 .arg("test.txt")
519 .assert()
520 .failure()
521 .stderr(predicate::str::contains("bat as a pager is disallowed"));
524#[test]
525fn pager_value_bat() {
526 bat()
527 .arg("--pager=bat")
528 .arg("--paging=always")
529 .arg("test.txt")
530 .assert()
531 .failure()
532 .stderr(predicate::str::contains("bat as a pager is disallowed"));
535/// We shall use less instead of most if PAGER is used since PAGER
536/// is a generic env var
537#[test]
538#[serial] // Because of PATH
539fn pager_most_from_pager_env_var() {
540 mocked_pagers::with_mocked_versions_of_more_and_most_in_path(|| {
541 // If the output is not "I am most" then we know 'most' is not used
542 bat()
543 .env("PAGER", mocked_pagers::from("most"))
544 .arg("--paging=always")
545 .arg("test.txt")
546 .assert()
547 .success()
548 .stdout(predicate::eq("hello world\n").normalize());
549 });
552/// If the bat-specific BAT_PAGER is used, obey the wish of the user
553/// and allow 'most'
554#[test]
555#[serial] // Because of PATH
556fn pager_most_from_bat_pager_env_var() {
557 mocked_pagers::with_mocked_versions_of_more_and_most_in_path(|| {
558 bat()
559 .env("BAT_PAGER", mocked_pagers::from("most"))
560 .arg("--paging=always")
561 .arg("test.txt")
562 .assert()
563 .success()
564 .stdout(predicate::str::contains("I am most"));
565 });
568/// Same reasoning with --pager as with BAT_PAGER
569#[test]
570#[serial] // Because of PATH
571fn pager_most_from_pager_arg() {
572 mocked_pagers::with_mocked_versions_of_more_and_most_in_path(|| {
573 bat()
574 .arg("--paging=always")
575 .arg(format!("--pager={}", mocked_pagers::from("most")))
576 .arg("test.txt")
577 .assert()
578 .success()
579 .stdout(predicate::str::contains("I am most"));
580 });
583/// Make sure the logic for 'most' applies even if an argument is passed
584#[test]
585#[serial] // Because of PATH
586fn pager_most_with_arg() {
587 mocked_pagers::with_mocked_versions_of_more_and_most_in_path(|| {
588 bat()
589 .env("PAGER", format!("{} -w", mocked_pagers::from("most")))
590 .arg("--paging=always")
591 .arg("test.txt")
592 .assert()
593 .success()
594 .stdout(predicate::eq("hello world\n").normalize());
595 });
598/// Sanity check that 'more' is treated like 'most'
599#[test]
600#[serial] // Because of PATH
601fn pager_more() {
602 mocked_pagers::with_mocked_versions_of_more_and_most_in_path(|| {
603 bat()
604 .env("PAGER", mocked_pagers::from("more"))
605 .arg("--paging=always")
606 .arg("test.txt")
607 .assert()
608 .success()
609 .stdout(predicate::eq("hello world\n").normalize());
610 });
613#[test]
614fn alias_pager_disable() {
615 bat()
616 .env("PAGER", "echo other-pager")
617 .arg("-P")
618 .arg("test.txt")
619 .assert()
620 .success()
621 .stdout(predicate::eq("hello world\n").normalize());
624#[test]
625fn alias_pager_disable_long_overrides_short() {
626 bat()
627 .env("PAGER", "echo pager-output")
628 .arg("-P")
629 .arg("--paging=always")
630 .arg("test.txt")
631 .assert()
632 .success()
633 .stdout(predicate::eq("pager-output\n").normalize());
636#[test]
637fn pager_failed_to_parse() {
638 bat()
639 .env("BAT_PAGER", "mismatched-quotes 'a")
640 .arg("--paging=always")
641 .arg("test.txt")
642 .assert()
643 .failure()
644 .stderr(predicate::str::contains("Could not parse pager command"));
647#[test]
648fn config_location_test() {
649 bat_with_config()
650 .env("BAT_CONFIG_PATH", "bat.conf")
651 .arg("--config-file")
652 .assert()
653 .success()
654 .stdout("bat.conf\n");
657#[test]
658fn config_read_arguments_from_file() {
659 bat_with_config()
660 .env("BAT_CONFIG_PATH", "bat.conf")
661 .arg("test.txt")
662 .assert()
663 .success()
664 .stdout(predicate::eq("dummy-pager-from-config\n").normalize());
667#[test]
668fn utf16() {
669 // The output will be converted to UTF-8 with a leading UTF-8 BOM
670 bat()
671 .arg("--plain")
672 .arg("--decorations=always")
673 .arg("test_UTF-16LE.txt")
674 .assert()
675 .success()
676 .stdout(std::str::from_utf8(b"\xEF\xBB\xBFhello world\n").unwrap());
679#[test]
680fn can_print_file_named_cache() {
681 bat_with_config()
682 .arg("cache")
683 .assert()
684 .success()
685 .stdout("test\n")
686 .stderr("");
689#[test]
690fn can_print_file_named_cache_with_additional_argument() {
691 bat_with_config()
692 .arg("cache")
693 .arg("test.txt")
694 .assert()
695 .success()
696 .stdout("test\nhello world\n")
697 .stderr("");
700#[test]
701fn can_print_file_starting_with_cache() {
702 bat_with_config()
703 .arg("cache.c")
704 .assert()
705 .success()
706 .stdout("test\n")
707 .stderr("");
710#[test]
711fn does_not_print_unwanted_file_named_cache() {
712 bat_with_config().arg("cach").assert().failure();
715#[test]
716fn unicode_wrap() {
717 bat_with_config()
718 .arg("unicode-wrap.txt")
719 .arg("--style=numbers,snip")
720 .arg("--decorations=always")
721 .arg("--terminal-width=40")
722 .assert()
723 .success()
724 .stdout(
725 " 1 ビタミンA ビタミンD ビタミンE ビ
726 タミンK ビタミンB1 ビタミンB2 ナ
727 イアシン パントテン酸 ビタミンB6
728 ビタミンB12 葉酸 ビオチン ビタ
729 ミンC
730 2
731 3 고양이 고양이 고양이 고양이 고양이
732 고양이 고양이 고양이 고양이 고양이
733 고양이 고양이 고양이 고양이 고양이
734 고양이 고양이 고양이 고양이 고양이
735 고양이 고양이 고양이 고양이 고양이
736 고양이 고양이 고양이 고양이 고양이
737 고양이 고양이 고양이 고양이 고양이
738 고양이 고양이 고양이 고양이 고양이
739 고양이
740 4
741 5 1 บวก 2 บวก 3 บวก 4 บวก 5 บวก 6 บวก
742 7 บวก 8 บวก 9 บวก 10 บวก 11 บวก 12
743 บวก 13 บวก 14 บวก 15 บวก 16 บวก 17
744 บวก 18 บวก 19 บวก 20
745 6
746 7 Бельгия Болгария Чехия Дания Герман
747 ия Эстония Ирландия Греция Испания
748 Франция Хорватия Италия Кипр Латвия
749 Литва Люксембург Венгрия Мальта Ни
750 дерланды Австрия Польша Португалия
751 Румыния Словения Словакия Финляндия
752 Швеция Великобритания
753",
754 );
757#[test]
758fn snip() {
759 bat()
760 .arg("multiline.txt")
761 .arg("--style=numbers,snip")
762 .arg("--decorations=always")
763 .arg("--line-range=1:2")
764 .arg("--line-range=4:")
765 .arg("--terminal-width=80")
766 .assert()
767 .success()
768 .stdout(
769 " 1 line 1
770 2 line 2
771 ...─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ 8< ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
772 4 line 4
773",
774 );
777#[test]
778fn empty_file_leads_to_empty_output_with_grid_enabled() {
779 bat()
780 .arg("empty.txt")
781 .arg("--style=grid")
782 .arg("--decorations=always")
783 .arg("--terminal-width=80")
784 .assert()
785 .success()
786 .stdout("");
789#[test]
790fn empty_file_leads_to_empty_output_with_rule_enabled() {
791 bat()
792 .arg("empty.txt")
793 .arg("--style=rule")
794 .arg("--decorations=always")
795 .arg("--terminal-width=80")
796 .assert()
797 .success()
798 .stdout("");
801#[test]
802fn filename_basic() {
803 bat()
804 .arg("test.txt")
805 .arg("--decorations=always")
806 .arg("--style=header")
807 .arg("-r=0:0")
808 .arg("--file-name=foo")
809 .assert()
810 .success()
811 .stdout("File: foo\n")
812 .stderr("");
815#[test]
816fn filename_binary() {
817 bat()
818 .arg("test.binary")
819 .arg("--decorations=always")
820 .arg("--style=header")
821 .arg("-r=0:0")
822 .arg("--file-name=foo")
823 .assert()
824 .success()
825 .stdout("File: foo <BINARY>\n")
826 .stderr("");
829#[test]
830fn filename_stdin() {
831 bat()
832 .arg("--decorations=always")
833 .arg("--style=header")
834 .arg("-r=0:0")
835 .arg("-")
836 .write_stdin("stdin\n")
837 .arg("--file-name=foo")
838 .assert()
839 .success()
840 .stdout("File: foo\n")
841 .stderr("");
844#[test]
845fn filename_stdin_binary() {
846 let vec = vec![0; 1];
847 bat_with_config()
848 .arg("--decorations=always")
849 .arg("--style=header")
850 .write_stdin(vec)
851 .arg("--file-name=foo")
852 .assert()
853 .success()
854 .stdout("File: foo <BINARY>\n")
855 .stderr("");
858#[test]
859fn filename_multiple_ok() {
860 bat()
861 .arg("--decorations=always")
862 .arg("--style=header")
863 .arg("-r=0:0")
864 .arg("test.txt")
865 .arg("--file-name=foo")
866 .arg("single-line.txt")
867 .arg("--file-name=bar")
868 .assert()
869 .success()
870 .stdout("File: foo\n\nFile: bar\n")
871 .stderr("");
874#[test]
875fn filename_multiple_err() {
876 bat()
877 .arg("--decorations=always")
878 .arg("--style=header")
879 .arg("-r=0:0")
880 .arg("test.txt")
881 .arg("--file-name=foo")
882 .arg("single-line.txt")
883 .assert()
884 .failure();
887#[test]
888fn header_padding() {
889 bat()
890 .arg("--decorations=always")
891 .arg("--style=header")
892 .arg("test.txt")
893 .arg("single-line.txt")
894 .assert()
895 .stdout("File: test.txt\nhello world\n\nFile: single-line.txt\nSingle Line\n")
896 .stderr("");
899#[test]
900fn header_padding_rule() {
901 bat()
902 .arg("--decorations=always")
903 .arg("--style=header,rule")
904 .arg("--terminal-width=80")
905 .arg("test.txt")
906 .arg("single-line.txt")
907 .assert()
908 .stdout(
909 "File: test.txt
910hello world
911────────────────────────────────────────────────────────────────────────────────
912File: single-line.txt
913Single Line
914",
915 )
916 .stderr("");
919#[test]
920fn grid_overrides_rule() {
921 bat()
922 .arg("--decorations=always")
923 .arg("--style=grid,rule")
924 .arg("--terminal-width=80")
925 .arg("test.txt")
926 .arg("single-line.txt")
927 .assert()
928 .stdout(
929 "\
930────────────────────────────────────────────────────────────────────────────────
931hello world
932────────────────────────────────────────────────────────────────────────────────
933────────────────────────────────────────────────────────────────────────────────
934Single Line
935────────────────────────────────────────────────────────────────────────────────
936",
937 )
938 .stderr("\x1b[33m[bat warning]\x1b[0m: Style 'rule' is a subset of style 'grid', 'rule' will not be visible.\n");
941#[cfg(target_os = "linux")]
942#[test]
943fn file_with_invalid_utf8_filename() {
944 use std::ffi::OsStr;
945 use std::fs::File;
946 use std::io::Write;
947 use std::os::unix::ffi::OsStrExt;
949 use tempdir::TempDir;
951 let tmp_dir = TempDir::new("bat_test").expect("can create temporary directory");
952 let file_path = tmp_dir
953 .path()
954 .join(OsStr::from_bytes(b"test-invalid-utf8-\xC3(.rs"));
955 {
956 let mut file = File::create(&file_path).expect("can create temporary file");
957 writeln!(file, "dummy content").expect("can write to file");
958 }
960 bat()
961 .arg(file_path.as_os_str())
962 .assert()
963 .success()
964 .stdout("dummy content\n");
967#[test]
968fn do_not_panic_regression_tests() {
969 for filename in &[
970 "issue_28.md",
971 "issue_190.md",
972 "issue_314.hs",
973 "issue_914.rb",
974 "issue_915.vue",
975 ] {
976 bat()
977 .arg("--color=always")
978 .arg(&format!("regression_tests/{}", filename))
979 .assert()
980 .success();
981 }
984#[test]
985fn do_not_detect_different_syntax_for_stdin_and_files() {
986 let file = "regression_tests/issue_985.js";
988 let cmd_for_file = bat()
989 .arg("--color=always")
990 .arg("--map-syntax=*.js:Markdown")
991 .arg(&format!("--file-name={}", file))
992 .arg("--style=plain")
993 .arg(file)
994 .assert()
995 .success();
997 let cmd_for_stdin = bat()
998 .arg("--color=always")
999 .arg("--map-syntax=*.js:Markdown")
1000 .arg("--style=plain")
1001 .arg(&format!("--file-name={}", file))
1002 .pipe_stdin(Path::new(EXAMPLES_DIR).join(file))
1003 .unwrap()
1004 .assert()
1005 .success();
1007 assert_eq!(
1008 from_utf8(&cmd_for_file.get_output().stdout).expect("output is valid utf-8"),
1009 from_utf8(&cmd_for_stdin.get_output().stdout).expect("output is valid utf-8")
1010 );
1013#[test]
1014fn show_all_mode() {
1015 bat()
1016 .arg("--show-all")
1017 .arg("nonprintable.txt")
1018 .assert()
1019 .stdout("hello·world␊\n├──┤␍␀␇␈␛")
1020 .stderr("");
1023#[test]
1024fn plain_mode_does_not_add_nonexisting_newline() {
1025 bat()
1026 .arg("--paging=never")
1027 .arg("--color=never")
1028 .arg("--decorations=always")
1029 .arg("--style=plain")
1030 .arg("single-line.txt")
1031 .assert()
1032 .success()
1033 .stdout("Single Line");
1036// Regression test for https://github.com/sharkdp/bat/issues/299
1037#[test]
1038fn grid_for_file_without_newline() {
1039 bat()
1040 .arg("--paging=never")
1041 .arg("--color=never")
1042 .arg("--terminal-width=80")
1043 .arg("--wrap=never")
1044 .arg("--decorations=always")
1045 .arg("--style=full")
1046 .arg("single-line.txt")
1047 .assert()
1048 .success()
1049 .stdout(
1050 "\
1051───────┬────────────────────────────────────────────────────────────────────────
1052 │ File: single-line.txt
1053───────┼────────────────────────────────────────────────────────────────────────
1054 1 │ Single Line
1055───────┴────────────────────────────────────────────────────────────────────────
1058 .stderr("");