summaryrefslogtreecommitdiffstats
path: root/tests/formatting.rs
blob: 84f9dd2cb01f33eca9554c446776f3eda5f10be3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// Copyright 2018-2019 Sebastian Wiesner <sebastian@swsnr.de>

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

// 	http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![deny(warnings, missing_docs, clippy::all)]
// Currently we only run formatting tests on Unix, because we rely on a Python
// tool here, and I failed to setup Python properly on Travis CI' Windows
// workers.
#![cfg(unix)]

use mdcat;

use pretty_assertions::assert_eq;
use pulldown_cmark::{Options, Parser};
use std::fs::File;
use std::io::prelude::*;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
use syntect::parsing::SyntaxSet;

fn format_ansi_to_html(markdown: &str) -> String {
    let child = Command::new("ansi2html")
        .arg("--input-encoding")
        .arg("utf8")
        .arg("--output-encoding")
        .arg("utf8")
        .arg("--markup-lines")
        .stdout(Stdio::piped())
        .stdin(Stdio::piped())
        .spawn()
        .expect("Failed to start ansi2html");
    {
        let size = mdcat::TerminalSize::default();
        let syntax_set = SyntaxSet::load_defaults_newlines();
        let wd = std::env::current_dir().expect("No working directory");
        let mut options = Options::empty();
        options.insert(Options::ENABLE_TASKLISTS);
        options.insert(Options::ENABLE_STRIKETHROUGH);
        let parser = Parser::new_ext(markdown, options);
        mdcat::push_tty(
            &mut child.stdin.unwrap(),
            mdcat::TerminalCapabilities::ansi(),
            size,
            parser,
            &wd,
            mdcat::ResourceAccess::LocalOnly,
            syntax_set,
        )
        .expect("Formatting failed")
    }
    let mut buffer = Vec::new();
    child
        .stdout
        .unwrap()
        .read_to_end(&mut buffer)
        .expect("Failed to read");

    String::from_utf8(buffer)
        .expect("Failed to convert from bytes")
        // Normalize line endings
        .replace("\r\n", "\n")
}

fn test_directory() -> PathBuf {
    Path::new(file!())
        .parent()
        .expect("Failed to get parent directory")
        .join("formatting")
}

fn read_file(basename: &str, extension: &str) -> String {
    let mut contents = String::new();
    let path = test_directory().join(basename).with_extension(extension);
    File::open(path)
        .and_then(|mut source| source.read_to_string(&mut contents))
        .expect("Failed to read test file");
    contents
}

fn assert_formats_to_expected_html(basename: &str) {
    let markdown = read_file(basename, "md");
    let actual_html = format_ansi_to_html(&markdown);

    let target = test_directory()
        .join(basename)
        .with_extension("actual.html");
    File::create(target)
        .and_then(|mut f| f.write_all(actual_html.as_bytes()))
        .expect("Failed to write actual HTML");

    let expected_html = read_file(basename, "expected.html");
    assert_eq!(actual_html, expected_html, "Different format produced");
}

macro_rules! test_compare_html(
    ($testname:ident) => (
        #[test]
        fn $testname() {
            crate::assert_formats_to_expected_html(stringify!($testname));
        }
    )
);

mod formatting {
    mod html {
        test_compare_html!(block_quote_and_ruler);
        test_compare_html!(code_blocks);
        test_compare_html!(headers_and_paragraphs);
        test_compare_html!(inline_formatting);
        test_compare_html!(just_a_line);
        test_compare_html!(links);
        test_compare_html!(lists);
        test_compare_html!(tasklist);
    }
}