r3bl_tui 0.3.6

TUI library inspired by Redux, Redux, Flexbox, CSS, editor components, etc
/*
 *   Copyright (c) 2022 R3BL LLC
 *   All rights reserved.
 *
 *   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.
 */

//! The reason the tests are in this separate file and not inside of `style.rs` is because the
//! [r3bl_rs_utils_macro::style!] macro is in a different crate than the [r3bl_rs_utils_core::Style]
//! struct.
//!
//! In order to use this macro, the test has to be in a different crate (aka `r3bl_tui` craete) than
//! both:
//!
//! 1. the [r3bl_rs_utils_core::Style] struct (`r3bl_rs_utils_core` crate)
//! 2. the [r3bl_rs_utils_macro::style!] macro (`r3bl_rs_utils_macro` crate).

#[cfg(test)]
mod tests {
    use r3bl_rs_utils_core::*;
    use r3bl_rs_utils_macro::style;

    #[test]
    fn syntect_style_conversion() {
        let st_style: syntect::highlighting::Style = syntect::highlighting::Style {
            foreground: syntect::highlighting::Color::WHITE,
            background: syntect::highlighting::Color::BLACK,
            font_style: syntect::highlighting::FontStyle::BOLD
                | syntect::highlighting::FontStyle::ITALIC
                | syntect::highlighting::FontStyle::UNDERLINE,
        };
        let style = Style::from(st_style);
        assert_eq2!(
            style.color_fg.unwrap(),
            TuiColor::Rgb(RgbValue {
                red: 255,
                green: 255,
                blue: 255
            })
        );
        assert_eq2!(
            style.color_bg.unwrap(),
            TuiColor::Rgb(RgbValue {
                red: 0,
                green: 0,
                blue: 0
            })
        );
        assert_eq2!(style.bold, true);
        assert_eq2!(style.underline, true);
    }

    #[test]
    fn test_cascade_style() {
        let style_bold_green_fg = style! {
          id: 1 // "bold_green_fg"
          attrib: [bold]
          color_fg: TuiColor::Basic(ANSIBasicColor::Green)
        };

        let style_dim = style! {
          id: 2 // "dim"
          attrib: [dim]
        };

        let style_yellow_bg = style! {
          id: 3 // "yellow_bg"
          color_bg: TuiColor::Basic(ANSIBasicColor::Yellow)
        };

        let style_padding = style! {
          id: 4 // "padding"
          padding: 2
        };

        let style_red_fg = style! {
          id: 5 // "red_fg"
          color_fg: TuiColor::Basic(ANSIBasicColor::Red)
        };

        let style_padding_another = style! {
          id: 6 // "padding"
          padding: 1
        };

        let my_style = style_bold_green_fg
            + style_dim
            + style_yellow_bg
            + style_padding
            + style_red_fg
            + style_padding_another;

        debug!(my_style);

        assert_eq2!(my_style.padding.unwrap(), ch!(3));
        assert_eq2!(
            my_style.color_bg.unwrap(),
            TuiColor::Basic(ANSIBasicColor::Yellow)
        );
        assert_eq2!(
            my_style.color_fg.unwrap(),
            TuiColor::Basic(ANSIBasicColor::Red)
        );
        assert!(my_style.bold);
        assert!(my_style.dim);
        assert!(my_style.computed);
        assert!(!my_style.underline);
    }

    #[test]
    fn test_stylesheet() {
        let mut stylesheet = Stylesheet::new();

        let style1 = make_a_style(1);
        let result = stylesheet.add_style(style1);
        result.unwrap();
        assert_eq2!(stylesheet.styles.len(), 1);

        let style2 = make_a_style(2);
        let result = stylesheet.add_style(style2);
        result.unwrap();
        assert_eq2!(stylesheet.styles.len(), 2);

        // Test find_style_by_id.
        {
            // No macro.
            assert_eq2!(stylesheet.find_style_by_id(1).unwrap().id, 1);
            assert_eq2!(stylesheet.find_style_by_id(2).unwrap().id, 2);
            assert!(stylesheet.find_style_by_id(3).is_none());
            // Macro.
            assert_eq2!(get_style!(@from: stylesheet, 1).unwrap().id, 1);
            assert_eq2!(get_style!(@from: stylesheet, 2).unwrap().id, 2);
            assert!(get_style!(@from: stylesheet, 3).is_none());
        }

        // Test find_styles_by_ids.
        {
            // Contains.
            assertions_for_find_styles_by_ids(&stylesheet.find_styles_by_ids(vec![1, 2]));
            assertions_for_find_styles_by_ids(&get_styles!(
                @from: &stylesheet,
                [1, 2]
            ));
            fn assertions_for_find_styles_by_ids(result: &Option<Vec<Style>>) {
                assert_eq2!(result.as_ref().unwrap().len(), 2);
                assert_eq2!(result.as_ref().unwrap()[0].id, 1);
                assert_eq2!(result.as_ref().unwrap()[1].id, 2);
            }
            // Does not contain.
            assert_eq2!(stylesheet.find_styles_by_ids(vec![3, 4]), None);
            assert_eq2!(get_styles!(@from: stylesheet, [3, 4]), None);
        }
    }

    #[test]
    fn test_stylesheet_builder() -> CommonResult<()> {
        let id_2 = 2;
        let style1 = make_a_style(1);
        let mut stylesheet = stylesheet! {
          style1,
          style! {
                id: id_2 /* using a variable instead of string literal */
                padding: 1
                color_bg: TuiColor::Rgb (RgbValue{ red: 55, green: 55, blue: 248 })
          },
          make_a_style(3),
          vec![
            style! {
              id: 4
              padding: 1
              color_bg: TuiColor::Rgb (RgbValue{ red: 55, green: 55, blue: 248 })
            },
            style! {
              id: 5
              padding: 1
              color_bg: TuiColor::Rgb (RgbValue{ red: 85, green: 85, blue: 255 })
            },
          ],
          make_a_style(6)
        };

        assert_eq2!(stylesheet.styles.len(), 6);
        assert_eq2!(stylesheet.find_style_by_id(1).unwrap().id, 1);
        assert_eq2!(stylesheet.find_style_by_id(2).unwrap().id, 2);
        assert_eq2!(stylesheet.find_style_by_id(3).unwrap().id, 3);
        assert_eq2!(stylesheet.find_style_by_id(4).unwrap().id, 4);
        assert_eq2!(stylesheet.find_style_by_id(5).unwrap().id, 5);
        assert_eq2!(stylesheet.find_style_by_id(6).unwrap().id, 6);
        assert!(stylesheet.find_style_by_id(7).is_none());

        let result = stylesheet.find_styles_by_ids(vec![1, 2]);
        assert_eq2!(result.as_ref().unwrap().len(), 2);
        assert_eq2!(result.as_ref().unwrap()[0].id, 1);
        assert_eq2!(result.as_ref().unwrap()[1].id, 2);
        assert_eq2!(stylesheet.find_styles_by_ids(vec![13, 41]), None);
        let style7 = make_a_style(7);
        let result = stylesheet.add_style(style7);
        result.unwrap();
        assert_eq2!(stylesheet.styles.len(), 7);
        assert_eq2!(stylesheet.find_style_by_id(7).unwrap().id, 7);
        Ok(())
    }

    /// Helper function.
    fn make_a_style(id: u8) -> Style {
        Style {
            id,
            dim: true,
            bold: true,
            color_fg: color!(0, 0, 0).into(),
            color_bg: color!(0, 0, 0).into(),
            ..Style::default()
        }
    }
}