Repository: zhiburt/tabled
Pull request #516 (2025-03-21 23:09:23)

Improve standart wrap algorithm
ref #513


Patch:
diff --git a/tabled/src/settings/width/wrap.rs b/tabled/src/settings/width/wrap.rs
index b4920ba..e876997 100644
--- a/tabled/src/settings/width/wrap.rs
+++ b/tabled/src/settings/width/wrap.rs
@@ -23,7 +23,6 @@ use crate::{
 use crate::grid::util::string::get_string_width;
 
 use super::util::{get_table_widths, get_table_widths_with_total};
-use crate::util::string::split_at_width;
 
 /// Wrap wraps a string to a new line in case it exceeds the provided max boundary.
 /// Otherwise keeps the content of a cell untouched.
@@ -195,34 +194,32 @@ where
     widths
 }
 
-#[cfg(not(feature = "ansi"))]
 pub(crate) fn wrap_text(text: &str, width: usize, keep_words: bool) -> String {
     if width == 0 {
         return String::new();
     }
 
-    if keep_words {
-        split_keeping_words(text, width, "\n")
-    } else {
-        chunks(text, width).join("\n")
+    #[cfg(not(feature = "ansi"))]
+    {
+        if keep_words {
+            wrap_text_keeping_words(text, width)
+        } else {
+            wrap_text_basic(text, width)
+        }
     }
-}
 
-#[cfg(feature = "ansi")]
-pub(crate) fn wrap_text(text: &str, width: usize, keep_words: bool) -> String {
-    use crate::util::string::strip_osc;
-
-    if width == 0 {
-        return String::new();
-    }
+    #[cfg(feature = "ansi")]
+    {
+        use crate::util::string::strip_osc;
 
-    let (text, url): (String, Option<String>) = strip_osc(text);
-    let (prefix, suffix) = build_link_prefix_suffix(url);
+        let (text, url): (String, Option<String>) = strip_osc(text);
+        let (prefix, suffix) = build_link_prefix_suffix(url);
 
-    if keep_words {
-        split_keeping_words(&text, width, &prefix, &suffix)
-    } else {
-        chunks(&text, width, &prefix, &suffix).join("\n")
+        if keep_words {
+            wrap_text_keeping_words(&text, width, &prefix, &suffix)
+        } else {
+            wrap_text_basic(&text, width, &prefix, &suffix)
+        }
     }
 }
 
@@ -241,223 +238,228 @@ fn build_link_prefix_suffix(url: Option<String>) -> (String, String) {
 }
 
 #[cfg(not(feature = "ansi"))]
-fn chunks(s: &str, width: usize) -> Vec<String> {
+fn wrap_text_basic(s: &str, width: usize) -> String {
     const REPLACEMENT: char = '\u{FFFD}';
 
     if width == 0 {
-        return Vec::new();
+        return String::new();
     }
 
-    let mut prev_newline = false;
-    let mut buf = String::with_capacity(width);
-    let mut list = Vec::new();
-    let mut i = 0;
+    let mut buf = String::new();
+    let mut current_width = 0;
     for c in s.chars() {
         if c == '\n' {
-            if buf.is_empty() {
-                list.push(String::new());
-            } else {
-                list.push(buf);
-            }
-
-            buf = String::with_capacity(width);
-            i = 0;
-            prev_newline = true;
+            buf.push('\n');
+            current_width = 0;
             continue;
         }
 
-        let c_width = get_char_width(c);
-        if i + c_width > width {
-            let count_unknowns = width - i;
-            buf.extend(std::iter::repeat(REPLACEMENT).take(count_unknowns));
-            i += count_unknowns;
-        } else {
-            buf.push(c);
-            i += c_width;
+        if current_width == width {
+            buf.push('\n');
+            current_width = 0;
         }
 
-        if i == width {
-            list.push(buf);
-            buf = String::with_capacity(width);
-            i = 0;
-            prev_newline = false;
+        let char_width = get_char_width(c);
+        let has_line_space = current_width + char_width <= width;
+        if !has_line_space {
+            let is_char_small = char_width <= width;
+            if !is_char_small {
+                let count_unknowns = width - current_width;
+                buf.extend(std::iter::repeat(REPLACEMENT).take(count_unknowns));
+                current_width += count_unknowns;
+            } else {
+                buf.push('\n');
+                buf.push(c);
+                current_width = char_width;
+            }
+        } else {
+            buf.push(c);
+            current_width += char_width;
         }
     }
 
-    if !buf.is_empty() || prev_newline {
-        list.push(buf);
-    }
-
-    list
+    buf
 }
 
 #[cfg(feature = "ansi")]
-fn chunks(s: &str, width: usize, prefix: &str, suffix: &str) -> Vec<String> {
+fn wrap_text_basic(text: &str, width: usize, line_prefix: &str, line_suffix: &str) -> String {
     use std::fmt::Write;
 
-    if width == 0 {
-        return Vec::new();
+    const REPLACEMENT: char = '\u{FFFD}';
+
+    if width == 0 || text.is_empty() {
+        return String::new();
     }
 
-    let mut list = Vec::new();
-    let mut line = String::with_capacity(width);
+    let mut buf = String::with_capacity(width);
     let mut line_width = 0;
 
-    for b in ansi_str::get_blocks(s) {
-        let text_style = b.style();
-        let mut text_slice = b.text();
-        if text_slice.is_empty() {
+    buf.push_str(line_prefix);
+
+    for block in ansi_str::get_blocks(text) {
+        let style = block.style();
+        let text = block.text();
+        if text.is_empty() {
             continue;
         }
 
-        let available_space = width - line_width;
-        if available_space == 0 {
-            list.push(line);
-            line = String::with_capacity(width);
+        let available = width - line_width;
+        if available == 0 {
+            buf.push('\n');
             line_width = 0;
         }
 
-        line.push_str(prefix);
-        let _ = write!(&mut line, "{}", text_style.start());
-
-        while !text_slice.is_empty() {
-            let available_space = width - line_width;
-
-            let part_width = get_text_width(text_slice);
-
-            if part_width <= available_space {
-                line.push_str(text_slice);
-                line_width += part_width;
-
-                if available_space == 0 {
-                    let _ = write!(&mut line, "{}", text_style.end());
-                    line.push_str(suffix);
-                    list.push(line);
-                    line = String::with_capacity(width);
-                    line.push_str(prefix);
-                    line_width = 0;
-                    let _ = write!(&mut line, "{}", text_style.start());
-                }
-
-                break;
+        let _ = write!(&mut buf, "{}", style.start());
+
+        // let text_width = get_text_width(text);
+        // if text_width + line_width <= width {
+        //     buf.push_str(text);
+        //     let _ = write!(&mut buf, "{}", style.end());
+        //     buf.push_str(line_suffix);
+        //     continue;
+        // }
+
+        for c in text.chars() {
+            if c == '\n' {
+                let _ = write!(&mut buf, "{}", style.end());
+                buf.push_str(line_suffix);
+                buf.push('\n');
+                line_width = 0;
+                buf.push_str(line_prefix);
+                let _ = write!(&mut buf, "{}", style.start());
+                continue;
             }
 
-            let (lhs, rhs, (unknowns, split_char)) = split_string_at(text_slice, available_space);
-
-            text_slice = &rhs[split_char..];
+            let char_width = get_char_width(c);
+            let line_has_space = line_width + char_width <= width;
+            if line_has_space {
+                buf.push(c);
+                line_width += char_width;
+                continue;
+            }
 
-            line.push_str(lhs);
-            line_width += get_text_width(lhs);
+            let is_char_small = char_width <= width;
+            if is_char_small {
+                let _ = write!(&mut buf, "{}", style.end());
+                buf.push_str(line_suffix);
+                buf.push('\n');
+                line_width = 0;
+                buf.push_str(line_prefix);
+                let _ = write!(&mut buf, "{}", style.start());
 
-            const REPLACEMENT: char = '\u{FFFD}';
-            line.extend(std::iter::repeat(REPLACEMENT).take(unknowns));
-            line_width += unknowns;
+                buf.push(c);
+                line_width += char_width;
+                continue;
+            }
 
             if line_width == width {
-                let _ = write!(&mut line, "{}", text_style.end());
-                line.push_str(suffix);
-                list.push(line);
-                line = String::with_capacity(width);
-                line.push_str(prefix);
+                let _ = write!(&mut buf, "{}", style.end());
+                buf.push_str(line_suffix);
+                buf.push('\n');
                 line_width = 0;
-                let _ = write!(&mut line, "{}", text_style.start());
+                buf.push_str(line_prefix);
+                let _ = write!(&mut buf, "{}", style.start());
             }
+
+            let count_unknowns = width - line_width;
+            buf.extend(std::iter::repeat(REPLACEMENT).take(count_unknowns));
+            line_width += count_unknowns;
         }
 
         if line_width > 0 {
-            let _ = write!(&mut line, "{}", text_style.end());
+            let _ = write!(&mut buf, "{}", style.end());
         }
     }
 
     if line_width > 0 {
-        line.push_str(suffix);
-        list.push(line);
+        buf.push_str(line_suffix);
     }
 
-    list
+    buf
 }
 
 #[cfg(not(feature = "ansi"))]
-fn split_keeping_words(s: &str, width: usize, sep: &str) -> String {
+fn wrap_text_keeping_words(text: &str, width: usize) -> String {
     const REPLACEMENT: char = '\u{FFFD}';
 
-    let mut lines = Vec::new();
-    let mut line = String::with_capacity(width);
-    let mut line_width = 0;
+    if width == 0 || text.is_empty() {
+        return String::new();
+    }
 
-    let mut is_first_word = true;
+    let mut buf = String::with_capacity(width);
+    let mut line_width = 0;
 
-    for word in s.split(' ') {
-        if !is_first_word {
+    for word in text.split(' ') {
+        // restore space char
+        if line_width > 0 {
             let line_has_space = line_width < width;
             if line_has_space {
-                line.push(' ');
+                buf.push(' ');
                 line_width += 1;
-                is_first_word = false;
             }
         }
 
-        if is_first_word {
-            is_first_word = false;
-        }
-
         let word_width = get_string_width(word);
 
         let line_has_space = line_width + word_width <= width;
         if line_has_space {
-            line.push_str(word);
+            buf.push_str(word);
             line_width += word_width;
             continue;
         }
 
-        if word_width <= width {
-            // the word can be fit to 'width' so we put it on new line
-
-            line.extend(std::iter::repeat(' ').take(width - line_width));
-            lines.push(line);
-
-            line = String::with_capacity(width);
+        let is_small_word = word_width <= width;
+        if is_small_word {
+            buf.push('\n');
             line_width = 0;
 
-            line.push_str(word);
+            buf.push_str(word);
             line_width += word_width;
-            is_first_word = false;
-        } else {
-            // the word is too long any way so we split it
-
-            let mut word_part = word;
-            while !word_part.is_empty() {
-                let available_space = width - line_width;
-                let (lhs, rhs, (unknowns, split_char)) =
-                    split_string_at(word_part, available_space);
-
-                word_part = &rhs[split_char..];
-                line_width += get_string_width(lhs) + unknowns;
-                is_first_word = false;
-
-                line.push_str(lhs);
-                line.extend(std::iter::repeat(REPLACEMENT).take(unknowns));
-
-                if line_width == width {
-                    lines.push(line);
-                    line = String::with_capacity(width);
-                    line_width = 0;
-                    is_first_word = true;
+            continue;
+        }
+
+        for c in word.chars() {
+            // take 1 char by 1 and just push it
+
+            let char_width = get_char_width(c);
+            let line_has_space = line_width + char_width <= width;
+            if !line_has_space {
+                let is_char_small = char_width <= width;
+                if !is_char_small {
+                    if line_width == width {
+                        buf.push('\n');
+                        line_width = 0;
+                    }
+
+                    // NOTE:
+                    // Practically it only can happen if we wrap some late UTF8 symbol.
+                    // For example:
+                    // Emojie with width 2 but and wrap width 1
+                    let available = width - line_width;
+                    buf.extend(std::iter::repeat(REPLACEMENT).take(available));
+                    line_width = width;
+                    continue;
                 }
+
+                buf.push('\n');
+                line_width = 0;
             }
-        }
-    }
 
-    if line_width > 0 {
-        line.extend(std::iter::repeat(' ').take(width - line_width));
-        lines.push(line);
+            buf.push(c);
+            line_width += char_width;
+        }
     }
 
-    lines.join(sep)
+    buf
 }
 
 #[cfg(feature = "ansi")]
-fn split_keeping_words(text: &str, width: usize, prefix: &str, suffix: &str) -> String {
+fn wrap_text_keeping_words(
+    text: &str,
+    width: usize,
+    line_prefix: &str,
+    line_suffix: &str,
+) -> String {
     if text.is_empty() || width == 0 {
         return String::new();
     }
@@ -467,8 +469,8 @@ fn split_keeping_words(text: &str, width: usize, prefix: &str, suffix: &str) ->
     let mut word_chars = 0;
     let mut blocks = parsing::Blocks::new(ansi_str::get_blocks(text));
     let mut buf = parsing::MultilineBuffer::new(width);
-    buf.set_prefix(prefix);
-    buf.set_suffix(suffix);
+    buf.set_prefix(line_prefix);
+    buf.set_suffix(line_suffix);
 
     for c in stripped_text.chars() {
         match c {
@@ -605,7 +607,6 @@ mod parsing {
 
             self.buf.push_str(self.suffix);
 
-            let _ = self.fill(' ');
             self.buf.push('\n');
             self.width_last = 0;
 
@@ -626,8 +627,6 @@ mod parsing {
             }
 
             self.buf.push_str(self.suffix);
-
-            let _ = self.fill(' ');
             self.width_last = 0;
         }
 
@@ -800,14 +799,6 @@ mod parsing {
     }
 }
 
-fn split_string_at(text: &str, at: usize) -> (&str, &str, (usize, usize)) {
-    let (length, width, split_char_size) = split_at_width(text, at);
-    let count_unknowns = if split_char_size > 0 { at - width } else { 0 };
-    let (lhs, rhs) = text.split_at(length);
-
-    (lhs, rhs, (count_unknowns, split_char_size))
-}
-
 fn decrease_widths<F>(
     widths: &mut [usize],
     min_widths: &[usize],
@@ -895,10 +886,10 @@ mod tests {
     #[test]
     fn split_test() {
         #[cfg(not(feature = "ansi"))]
-        let split = |text, width| chunks(text, width).join("\n");
+        let split = |text, width| wrap_text_basic(text, width);
 
         #[cfg(feature = "ansi")]
-        let split = |text, width| chunks(text, width, "", "").join("\n");
+        let split = |text, width| wrap_text_basic(text, width, "", "");
 
         assert_eq!(split("123456", 0), "");
 
@@ -910,7 +901,7 @@ mod tests {
 
         assert_eq!(split("😳😳😳😳😳", 1), "�\n�\n�\n�\n�");
         assert_eq!(split("😳😳😳😳😳", 2), "😳\n😳\n😳\n😳\n😳");
-        assert_eq!(split("😳😳😳😳😳", 3), "😳�\n😳�\n😳");
+        assert_eq!(split("😳😳😳😳😳", 3), "😳\n😳\n😳\n😳\n😳");
         assert_eq!(split("😳😳😳😳😳", 6), "😳😳😳\n😳😳");
         assert_eq!(split("😳😳😳😳😳", 20), "😳😳😳😳😳");
 
@@ -922,63 +913,75 @@ mod tests {
     fn chunks_test() {
         #[allow(clippy::redundant_closure)]
         #[cfg(not(feature = "ansi"))]
-        let chunks = |text, width| chunks(text, width);
+        let chunks = |text, width| wrap_text_basic(text, width);
 
         #[cfg(feature = "ansi")]
-        let chunks = |text, width| chunks(text, width, "", "");
+        let chunks = |text, width| wrap_text_basic(text, width, "", "");
 
-        assert_eq!(chunks("123456", 0), [""; 0]);
+        assert_eq!(chunks("123456", 0), "");
 
-        assert_eq!(chunks("123456", 1), ["1", "2", "3", "4", "5", "6"]);
-        assert_eq!(chunks("123456", 2), ["12", "34", "56"]);
-        assert_eq!(chunks("12345", 2), ["12", "34", "5"]);
+        assert_eq!(
+            chunks("123456", 1),
+            ["1", "2", "3", "4", "5", "6"].join("\n")
+        );
+        assert_eq!(chunks("123456", 2), ["12", "34", "56"].join("\n"));
+        assert_eq!(chunks("12345", 2), ["12", "34", "5"].join("\n"));
 
-        assert_eq!(chunks("😳😳😳😳😳", 1), ["�", "�", "�", "�", "�"]);
-        assert_eq!(chunks("😳😳😳😳😳", 2), ["😳", "😳", "😳", "😳", "😳"]);
-        assert_eq!(chunks("😳😳😳😳😳", 3), ["😳�", "😳�", "😳"]);
+        assert_eq!(
+            chunks("😳😳😳😳😳", 1),
+            ["�", "�", "�", "�", "�"].join("\n")
+        );
+        assert_eq!(
+            chunks("😳😳😳😳😳", 2),
+            ["😳", "😳", "😳", "😳", "😳"].join("\n")
+        );
+        assert_eq!(
+            chunks("😳😳😳😳😳", 3),
+            ["😳", "😳", "😳", "😳", "😳"].join("\n")
+        );
     }
 
     #[cfg(not(feature = "ansi"))]
     #[test]
     fn split_by_line_keeping_words_test() {
-        let split_keeping_words = |text, width| split_keeping_words(text, width, "\n");
+        let split_keeping_words = |text, width| wrap_text_keeping_words(text, width);
 
         assert_eq!(split_keeping_words("123456", 1), "1\n2\n3\n4\n5\n6");
         assert_eq!(split_keeping_words("123456", 2), "12\n34\n56");
-        assert_eq!(split_keeping_words("12345", 2), "12\n34\n5 ");
+        assert_eq!(split_keeping_words("12345", 2), "12\n34\n5");
 
         assert_eq!(split_keeping_words("😳😳😳😳😳", 1), "�\n�\n�\n�\n�");
 
-        assert_eq!(split_keeping_words("111 234 1", 4), "111 \n234 \n1   ");
+        assert_eq!(split_keeping_words("111 234 1", 4), "111 \n234 \n1");
     }
 
     #[cfg(feature = "ansi")]
     #[test]
     fn split_by_line_keeping_words_test() {
         #[cfg(feature = "ansi")]
-        let split_keeping_words = |text, width| split_keeping_words(text, width, "", "");
+        let split_keeping_words = |text, width| wrap_text_keeping_words(text, width, "", "");
 
         assert_eq!(split_keeping_words("123456", 1), "1\n2\n3\n4\n5\n6");
         assert_eq!(split_keeping_words("123456", 2), "12\n34\n56");
-        assert_eq!(split_keeping_words("12345", 2), "12\n34\n5 ");
+        assert_eq!(split_keeping_words("12345", 2), "12\n34\n5");
 
         assert_eq!(split_keeping_words("😳😳😳😳😳", 1), "�\n�\n�\n�\n�");
 
-        assert_eq!(split_keeping_words("111 234 1", 4), "111 \n234 \n1   ");
+        assert_eq!(split_keeping_words("111 234 1", 4), "111 \n234 \n1");
     }
 
     #[cfg(feature = "ansi")]
     #[test]
     fn split_by_line_keeping_words_color_test() {
         #[cfg(feature = "ansi")]
-        let split_keeping_words = |text, width| split_keeping_words(text, width, "", "");
+        let split_keeping_words = |text, width| wrap_text_keeping_words(text, width, "", "");
 
         #[cfg(not(feature = "ansi"))]
         let split_keeping_words = |text, width| split_keeping_words(text, width, "\n");
 
         let text = "\u{1b}[36mJapanese “vacancy” button\u{1b}[0m";
 
-        assert_eq!(split_keeping_words(text, 2), "\u{1b}[36mJa\u{1b}[39m\n\u{1b}[36mpa\u{1b}[39m\n\u{1b}[36mne\u{1b}[39m\n\u{1b}[36mse\u{1b}[39m\n\u{1b}[36m “\u{1b}[39m\n\u{1b}[36mva\u{1b}[39m\n\u{1b}[36mca\u{1b}[39m\n\u{1b}[36mnc\u{1b}[39m\n\u{1b}[36my”\u{1b}[39m\n\u{1b}[36m b\u{1b}[39m\n\u{1b}[36mut\u{1b}[39m\n\u{1b}[36mto\u{1b}[39m\n\u{1b}[36mn\u{1b}[39m ");
+        assert_eq!(split_keeping_words(text, 2), "\u{1b}[36mJa\u{1b}[39m\n\u{1b}[36mpa\u{1b}[39m\n\u{1b}[36mne\u{1b}[39m\n\u{1b}[36mse\u{1b}[39m\n\u{1b}[36m “\u{1b}[39m\n\u{1b}[36mva\u{1b}[39m\n\u{1b}[36mca\u{1b}[39m\n\u{1b}[36mnc\u{1b}[39m\n\u{1b}[36my”\u{1b}[39m\n\u{1b}[36m b\u{1b}[39m\n\u{1b}[36mut\u{1b}[39m\n\u{1b}[36mto\u{1b}[39m\n\u{1b}[36mn\u{1b}[39m");
         assert_eq!(split_keeping_words(text, 1), "\u{1b}[36mJ\u{1b}[39m\n\u{1b}[36ma\u{1b}[39m\n\u{1b}[36mp\u{1b}[39m\n\u{1b}[36ma\u{1b}[39m\n\u{1b}[36mn\u{1b}[39m\n\u{1b}[36me\u{1b}[39m\n\u{1b}[36ms\u{1b}[39m\n\u{1b}[36me\u{1b}[39m\n\u{1b}[36m \u{1b}[39m\n\u{1b}[36m“\u{1b}[39m\n\u{1b}[36mv\u{1b}[39m\n\u{1b}[36ma\u{1b}[39m\n\u{1b}[36mc\u{1b}[39m\n\u{1b}[36ma\u{1b}[39m\n\u{1b}[36mn\u{1b}[39m\n\u{1b}[36mc\u{1b}[39m\n\u{1b}[36my\u{1b}[39m\n\u{1b}[36m”\u{1b}[39m\n\u{1b}[36m \u{1b}[39m\n\u{1b}[36mb\u{1b}[39m\n\u{1b}[36mu\u{1b}[39m\n\u{1b}[36mt\u{1b}[39m\n\u{1b}[36mt\u{1b}[39m\n\u{1b}[36mo\u{1b}[39m\n\u{1b}[36mn\u{1b}[39m");
     }
 
@@ -988,7 +991,7 @@ mod tests {
         use ansi_str::AnsiStr;
 
         #[cfg(feature = "ansi")]
-        let split_keeping_words = |text, width| split_keeping_words(text, width, "", "");
+        let split_keeping_words = |text, width| wrap_text_keeping_words(text, width, "", "");
 
         #[cfg(not(feature = "ansi"))]
         let split_keeping_words = |text, width| split_keeping_words(text, width, "\n");
@@ -1135,7 +1138,7 @@ mod tests {
     #[cfg(feature = "ansi")]
     #[test]
     fn split_by_line_keeping_words_color_3_test() {
-        let split = |text, width| split_keeping_words(text, width, "", "");
+        let split = |text, width| wrap_text_keeping_words(text, width, "", "");
         assert_eq!(
             split(
                 "\u{1b}[37m🚵🏻🚵🏻🚵🏻🚵🏻🚵🏻🚵🏻🚵🏻🚵🏻🚵🏻🚵🏻\u{1b}[0m",
@@ -1145,66 +1148,72 @@ mod tests {
         );
         assert_eq!(
             split("\u{1b}[37mthis is a long sentence\u{1b}[0m", 7),
-            "\u{1b}[37mthis is\u{1b}[39m\n\u{1b}[37m a long\u{1b}[39m\n\u{1b}[37m senten\u{1b}[39m\n\u{1b}[37mce\u{1b}[39m     "
+            "\u{1b}[37mthis is\u{1b}[39m\n\u{1b}[37m a long\u{1b}[39m\n\u{1b}[37m senten\u{1b}[39m\n\u{1b}[37mce\u{1b}[39m"
         );
         assert_eq!(
             split("\u{1b}[37mHello World\u{1b}[0m", 7),
-            "\u{1b}[37mHello \u{1b}[39m \n\u{1b}[37mWorld\u{1b}[39m  "
+            "\u{1b}[37mHello \u{1b}[39m\n\u{1b}[37mWorld\u{1b}[39m"
         );
         assert_eq!(
             split("\u{1b}[37mHello Wo\u{1b}[37mrld\u{1b}[0m", 7),
-            "\u{1b}[37mHello \u{1b}[39m \n\u{1b}[37mWo\u{1b}[39m\u{1b}[37mrld\u{1b}[39m  "
+            "\u{1b}[37mHello \u{1b}[39m\n\u{1b}[37mWo\u{1b}[39m\u{1b}[37mrld\u{1b}[39m"
         );
         assert_eq!(
             split("\u{1b}[37mHello Wo\u{1b}[37mrld\u{1b}[0m", 8),
-            "\u{1b}[37mHello \u{1b}[39m  \n\u{1b}[37mWo\u{1b}[39m\u{1b}[37mrld\u{1b}[39m   "
+            "\u{1b}[37mHello \u{1b}[39m\n\u{1b}[37mWo\u{1b}[39m\u{1b}[37mrld\u{1b}[39m"
         );
     }
 
     #[cfg(not(feature = "ansi"))]
     #[test]
     fn split_keeping_words_4_test() {
-        let split_keeping_words = |text, width| split_keeping_words(text, width, "\n");
+        let split_keeping_words = |text, width| wrap_text_keeping_words(text, width);
 
-        assert_eq!(split_keeping_words("12345678", 3,), "123\n456\n78 ");
+        assert_eq!(split_keeping_words("12345678", 3,), "123\n456\n78");
         assert_eq!(split_keeping_words("12345678", 2,), "12\n34\n56\n78");
     }
 
     #[cfg(feature = "ansi")]
     #[test]
     fn split_keeping_words_4_test() {
-        let split_keeping_words = |text, width| split_keeping_words(text, width, "", "");
+        let split_keeping_words = |text, width| wrap_text_keeping_words(text, width, "", "");
 
         #[cfg(not(feature = "ansi"))]
         let split_keeping_words = |text, width| split_keeping_words(text, width, "\n");
 
-        assert_eq!(split_keeping_words("12345678", 3,), "123\n456\n78 ");
+        assert_eq!(split_keeping_words("12345678", 3,), "123\n456\n78");
         assert_eq!(split_keeping_words("12345678", 2,), "12\n34\n56\n78");
     }
 
     #[cfg(feature = "ansi")]
     #[test]
     fn chunks_test_with_prefix_and_suffix() {
-        assert_eq!(chunks("123456", 0, "^", "$"), ["^$"; 0]);
+        assert_eq!(wrap_text_basic("123456", 0, "^", "$"), ["^$"; 0].join("\n"));
 
         assert_eq!(
-            chunks("123456", 1, "^", "$"),
-            ["^1$", "^2$", "^3$", "^4$", "^5$", "^6$"]
+            wrap_text_basic("123456", 1, "^", "$"),
+            ["^1$", "^2$", "^3$", "^4$", "^5$", "^6$"].join("\n")
+        );
+        assert_eq!(
+            wrap_text_basic("123456", 2, "^", "$"),
+            ["^12$", "^34$", "^56$"].join("\n")
+        );
+        assert_eq!(
+            wrap_text_basic("12345", 2, "^", "$"),
+            ["^12$", "^34$", "^5$"].join("\n")
         );
-        assert_eq!(chunks("123456", 2, "^", "$"), ["^12$", "^34$", "^56$"]);
-        assert_eq!(chunks("12345", 2, "^", "$"), ["^12$", "^34$", "^5$"]);
 
         assert_eq!(
-            chunks("😳😳😳😳😳", 1, "^", "$"),
-            ["^�$", "^�$", "^�$", "^�$", "^�$"]
+            wrap_text_basic("😳😳😳😳😳", 1, "^", "$"),
+            ["^�$", "^�$", "^�$", "^�$", "^�$"].join("\n")
         );
         assert_eq!(
-            chunks("😳😳😳😳😳", 2, "^", "$"),
-            ["^😳$", "^😳$", "^😳$", "^😳$", "^😳$"]
+            wrap_text_basic("😳😳😳😳😳", 2, "^", "$"),
+            ["^😳$", "^😳$", "^😳$", "^😳$", "^😳$"].join("\n")
         );
         assert_eq!(
-            chunks("😳😳😳😳😳", 3, "^", "$"),
-            ["^😳�$", "^😳�$", "^😳$"]
+            wrap_text_basic("😳😳😳😳😳", 3, "^", "$"),
+            "^😳$\n^😳$\n^😳$\n^😳$\n^😳$"
         );
     }
 
@@ -1212,20 +1221,20 @@ mod tests {
     #[test]
     fn split_by_line_keeping_words_test_with_prefix_and_suffix() {
         assert_eq!(
-            split_keeping_words("123456", 1, "^", "$"),
+            wrap_text_keeping_words("123456", 1, "^", "$"),
             "^1$\n^2$\n^3$\n^4$\n^5$\n^6$"
         );
         assert_eq!(
-            split_keeping_words("123456", 2, "^", "$"),
+            wrap_text_keeping_words("123456", 2, "^", "$"),
             "^12$\n^34$\n^56$"
         );
         assert_eq!(
-            split_keeping_words("12345", 2, "^", "$"),
-            "^12$\n^34$\n^5$ "
+            wrap_text_keeping_words("12345", 2, "^", "$"),
+            "^12$\n^34$\n^5$"
         );
 
         assert_eq!(
-            split_keeping_words("😳😳😳😳😳", 1, "^", "$"),
+            wrap_text_keeping_words("😳😳😳😳😳", 1, "^", "$"),
             "^�$\n^�$\n^�$\n^�$\n^�$"
         );
     }
@@ -1238,7 +1247,7 @@ mod tests {
         let text = "\u{1b}[37mTigre Ecuador   OMYA Andina     3824909999      Calcium carbonate       Colombia\u{1b}[0m";
 
         assert_eq!(
-            split_keeping_words(text, 2, "^", "$")
+            wrap_text_keeping_words(text, 2, "^", "$")
                 .ansi_split("\n")
                 .collect::<Vec<_>>(),
             [
@@ -1286,7 +1295,7 @@ mod tests {
         );
 
         assert_eq!(
-            split_keeping_words(text, 1, "^", "$")
+            wrap_text_keeping_words(text, 1, "^", "$")
                 .ansi_split("\n")
                 .collect::<Vec<_>>(),
             [
@@ -1379,12 +1388,12 @@ mod tests {
     fn chunks_wrap_2() {
         let text = "\u{1b}[30mDebian\u{1b}[0m\u{1b}[31mDebian\u{1b}[0m\u{1b}[32mDebian\u{1b}[0m\u{1b}[33mDebian\u{1b}[0m\u{1b}[34mDebian\u{1b}[0m\u{1b}[35mDebian\u{1b}[0m\u{1b}[36mDebian\u{1b}[0m\u{1b}[37mDebian\u{1b}[0m\u{1b}[40mDebian\u{1b}[0m\u{1b}[41mDebian\u{1b}[0m\u{1b}[42mDebian\u{1b}[0m\u{1b}[43mDebian\u{1b}[0m\u{1b}[44mDebian\u{1b}[0m";
         assert_eq!(
-            chunks(text, 30, "", ""),
+            wrap_text_basic(text, 30, "", ""),
             [
                 "\u{1b}[30mDebian\u{1b}[39m\u{1b}[31mDebian\u{1b}[39m\u{1b}[32mDebian\u{1b}[39m\u{1b}[33mDebian\u{1b}[39m\u{1b}[34mDebian\u{1b}[39m",
                 "\u{1b}[35mDebian\u{1b}[39m\u{1b}[36mDebian\u{1b}[39m\u{1b}[37mDebian\u{1b}[39m\u{1b}[40mDebian\u{1b}[49m\u{1b}[41mDebian\u{1b}[49m",
                 "\u{1b}[42mDebian\u{1b}[49m\u{1b}[43mDebian\u{1b}[49m\u{1b}[44mDebian\u{1b}[49m",
-            ]
+            ].join("\n")
         );
     }
 
@@ -1394,11 +1403,12 @@ mod tests {
         let text = "\u{1b}[37mCreate bytes from the \u{1b}[0m\u{1b}[7;34marg\u{1b}[0m\u{1b}[37muments.\u{1b}[0m";
 
         assert_eq!(
-            chunks(text, 22, "", ""),
+            wrap_text_basic(text, 22, "", ""),
             [
                 "\u{1b}[37mCreate bytes from the \u{1b}[39m",
                 "\u{1b}[7m\u{1b}[34marg\u{1b}[27m\u{1b}[39m\u{1b}[37muments.\u{1b}[39m"
             ]
+            .join("\n")
         );
     }
 
@@ -1408,8 +1418,8 @@ mod tests {
         let text = "\u{1b}[37mCreate bytes from the \u{1b}[0m\u{1b}[7;34marg\u{1b}[0m\u{1b}[37muments.\u{1b}[0m";
 
         assert_eq!(
-            split_keeping_words(text, 22, "", ""),
-            "\u{1b}[37mCreate bytes from the \u{1b}[39m\n\u{1b}[7m\u{1b}[34marg\u{1b}[27m\u{1b}[39m\u{1b}[37muments.\u{1b}[39m            "
+            wrap_text_keeping_words(text, 22, "", ""),
+            "\u{1b}[37mCreate bytes from the \u{1b}[39m\n\u{1b}[7m\u{1b}[34marg\u{1b}[27m\u{1b}[39m\u{1b}[37muments.\u{1b}[39m"
         );
     }
 
@@ -1419,7 +1429,7 @@ mod tests {
         let text = "\u{1b}[37mReturns the floor of a number (l\u{1b}[0m\u{1b}[41;37marg\u{1b}[0m\u{1b}[37mest integer less than or equal to that number).\u{1b}[0m";
 
         assert_eq!(
-            chunks(text, 10, "", ""),
+            wrap_text_basic(text, 10, "", ""),
             [
                 "\u{1b}[37mReturns th\u{1b}[39m",
                 "\u{1b}[37me floor of\u{1b}[39m",
@@ -1430,7 +1440,7 @@ mod tests {
                 "\u{1b}[37mequal to t\u{1b}[39m",
                 "\u{1b}[37mhat number\u{1b}[39m",
                 "\u{1b}[37m).\u{1b}[39m",
-            ]
+            ].join("\n")
         );
     }
 
@@ -1439,19 +1449,47 @@ mod tests {
     fn chunks_wrap_4_keeping_words() {
         let text = "\u{1b}[37mReturns the floor of a number (l\u{1b}[0m\u{1b}[41;37marg\u{1b}[0m\u{1b}[37mest integer less than or equal to that number).\u{1b}[0m";
         assert_eq!(
-            split_keeping_words(text, 10, "", ""),
+            wrap_text_keeping_words(text, 10, "", ""),
             concat!(
-                "\u{1b}[37mReturns \u{1b}[39m  \n",
+                "\u{1b}[37mReturns \u{1b}[39m\n",
                 "\u{1b}[37mthe floor \u{1b}[39m\n",
-                "\u{1b}[37mof a \u{1b}[39m     \n",
-                "\u{1b}[37mnumber \u{1b}[39m   \n",
-                "\u{1b}[37m(l\u{1b}[39m\u{1b}[37m\u{1b}[41marg\u{1b}[39m\u{1b}[49m\u{1b}[37mest \u{1b}[39m \n",
-                "\u{1b}[37minteger \u{1b}[39m  \n",
+                "\u{1b}[37mof a \u{1b}[39m\n",
+                "\u{1b}[37mnumber \u{1b}[39m\n",
+                "\u{1b}[37m(l\u{1b}[39m\u{1b}[37m\u{1b}[41marg\u{1b}[39m\u{1b}[49m\u{1b}[37mest \u{1b}[39m\n",
+                "\u{1b}[37minteger \u{1b}[39m\n",
                 "\u{1b}[37mless than \u{1b}[39m\n",
-                "\u{1b}[37mor equal \u{1b}[39m \n",
-                "\u{1b}[37mto that \u{1b}[39m  \n",
-                "\u{1b}[37mnumber).\u{1b}[39m  ",
+                "\u{1b}[37mor equal \u{1b}[39m\n",
+                "\u{1b}[37mto that \u{1b}[39m\n",
+                "\u{1b}[37mnumber).\u{1b}[39m",
             )
         );
     }
+
+    #[cfg(not(feature = "ansi"))]
+    #[test]
+    fn chunks_chinese_0() {
+        let text = "(公司{ 名称:\"腾讯科技（深圳）有限公司\",成立时间:\"1998年11月\"}";
+
+        assert_eq!(
+            wrap_text_basic(text, 40),
+            concat!(
+                "(公司{ 名称:\"腾讯科技（深圳）有限公司\",\n",
+                "成立时间:\"1998年11月\"}",
+            ),
+        );
+    }
+
+    #[cfg(not(feature = "ansi"))]
+    #[test]
+    fn chunks_keeping_chinese_0() {
+        let text = "(公司{ 名称:\"腾讯科技（深圳）有限公司\",成立时间:\"1998年11月\"}";
+
+        assert_eq!(
+            wrap_text_keeping_words(text, 40),
+            concat!(
+                "(公司{ 名称:\"腾讯科技（深圳）有限公司\",\n",
+                "成立时间:\"1998年11月\"}",
+            ),
+        );
+    }
 }


Test patch:
diff --git a/tabled/tests/core/table_test.rs b/tabled/tests/core/table_test.rs
index f47e2a2..e438985 100644
--- a/tabled/tests/core/table_test.rs
+++ b/tabled/tests/core/table_test.rs
@@ -750,46 +750,67 @@ mod derived {
 }
 
 #[cfg(feature = "ansi")]
-#[test]
-fn multiline_table_test2() {
-    use testing_table::assert_table;
-
-    let data = &[
-        ["\u{1b}[37mThis is the 0.19 release of Nushell. If you'd like to read more about it, please check out: https://www.nushell.sh/blog/2020/09/01/nushell_0_19.html\n\nFor convenience, we are providing full builds for Windows, Linux, and macOS. These are the \"all extra features\" builds, so be sure you have the requirements to enable all capabilities: https://github.com/nushell/book/blob/master/en/installation.md#dependencies\n\u{1b}[0m"],
-    ];
-
-    let mut table = Table::new(data);
-    table.with(Style::modern());
-
-    assert_table!(
-        ansi_str::AnsiStr::ansi_strip(&table.to_string()),
-        r#"┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐"#
-        r#"│ 0                                                                                                                                                                                                                                                                    │"#
-        r#"├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤"#
-        r#"│ This is the 0.19 release of Nushell. If you'd like to read more about it, please check out: https://www.nushell.sh/blog/2020/09/01/nushell_0_19.html                                                                                                                 │"#
-        r#"│                                                                                                                                                                                                                                                                      │"#
-        r#"│ For convenience, we are providing full builds for Windows, Linux, and macOS. These are the "all extra features" builds, so be sure you have the requirements to enable all capabilities: https://github.com/nushell/book/blob/master/en/installation.md#dependencies │"#
-        r#"│                                                                                                                                                                                                                                                                      │"#
-        r#"└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘"#
-    );
+test_table!(
+    test_wrap_multiline_0,
+    Table::new([
+        [
+            concat!(
+                "\u{1b}[37m",
+                "This is the 0.19 release of Nushell. If you'd like to read more about it, please check out: https://www.nushell.sh/blog/2020/09/01/nushell_0_19.html",
+                "\n",
+                "\n",
+                "For convenience, we are providing full builds for Windows, Linux, and macOS. These are the \"all extra features\" builds, so be sure you have the requirements to enable all capabilities: https://github.com/nushell/book/blob/master/en/installation.md#dependencies",
+                "\n",
+                "\u{1b}[0m",
+            )
+        ],
+    ])
+    .with(Style::modern())
+    .with(Width::wrap(100)),
+    "┌──────────────────────────────────────────────────────────────────────────────────────────────────┐"
+    "│ 0                                                                                                │"
+    "├──────────────────────────────────────────────────────────────────────────────────────────────────┤"
+    "│ \u{1b}[37mThis is the 0.19 release of Nushell. If you'd like to read more about it, please check out: http\u{1b}[39m │"
+    "│ \u{1b}[37ms://www.nushell.sh/blog/2020/09/01/nushell_0_19.html\u{1b}[39m                                             │"
+    "│ \u{1b}[37m\u{1b}[39m                                                                                                 │"
+    "│ \u{1b}[37mFor convenience, we are providing full builds for Windows, Linux, and macOS. These are the \"all \u{1b}[39m │"
+    "│ \u{1b}[37mextra features\" builds, so be sure you have the requirements to enable all capabilities: https:/\u{1b}[39m │"
+    "│ \u{1b}[37m/github.com/nushell/book/blob/master/en/installation.md#dependencies\u{1b}[39m                             │"
+    "│ \u{1b}[37m\u{1b}[39m                                                                                                 │"
+    "└──────────────────────────────────────────────────────────────────────────────────────────────────┘"
+);
 
-    table.with(Width::wrap(100));
-
-    assert_table!(
-        ansi_str::AnsiStr::ansi_strip(&table.to_string()),
-        "┌──────────────────────────────────────────────────────────────────────────────────────────────────┐"
-        "│ 0                                                                                                │"
-        "├──────────────────────────────────────────────────────────────────────────────────────────────────┤"
-        "│ This is the 0.19 release of Nushell. If you'd like to read more about it, please check out: http │"
-        "│ s://www.nushell.sh/blog/2020/09/01/nushell_0_19.html                                             │"
-        "│                                                                                                  │"
-        "│ For convenience, we are providing full builds for Windows, Linux, and macOS. These are the \"all  │"
-        "│ extra features\" builds, so be sure you have the requirements to enable all capabilities: https:/ │"
-        "│ /github.com/nushell/book/blob/master/en/installation.md#dependencies                             │"
-        "│                                                                                                  │"
-        "└──────────────────────────────────────────────────────────────────────────────────────────────────┘"
-    );
-}
+test_table!(
+    test_wrap_multiline_1,
+    {
+        let data = &[
+            [
+                concat!(
+                    "This is the 0.19 release of Nushell. If you'd like to read more about it, please check out: https://www.nushell.sh/blog/2020/09/01/nushell_0_19.html",
+                    "\n",
+                    "\n",
+                    "For convenience, we are providing full builds for Windows, Linux, and macOS. These are the \"all extra features\" builds, so be sure you have the requirements to enable all capabilities: https://github.com/nushell/book/blob/master/en/installation.md#dependencies",
+                    "\n",
+                )
+            ],
+        ];
+
+        Table::new(data)
+            .with(Style::modern())
+            .with(Width::wrap(100))
+    },
+    "┌──────────────────────────────────────────────────────────────────────────────────────────────────┐"
+    "│ 0                                                                                                │"
+    "├──────────────────────────────────────────────────────────────────────────────────────────────────┤"
+    "│ This is the 0.19 release of Nushell. If you'd like to read more about it, please check out: http │"
+    "│ s://www.nushell.sh/blog/2020/09/01/nushell_0_19.html                                             │"
+    "│                                                                                                  │"
+    "│ For convenience, we are providing full builds for Windows, Linux, and macOS. These are the \"all  │"
+    "│ extra features\" builds, so be sure you have the requirements to enable all capabilities: https:/ │"
+    "│ /github.com/nushell/book/blob/master/en/installation.md#dependencies                             │"
+    "│                                                                                                  │"
+    "└──────────────────────────────────────────────────────────────────────────────────────────────────┘"
+);
 
 test_table!(
     table_1x1_empty,
diff --git a/tabled/tests/settings/width_test.rs b/tabled/tests/settings/width_test.rs
index 3b6e3b4..8d98343 100644
--- a/tabled/tests/settings/width_test.rs
+++ b/tabled/tests/settings/width_test.rs
@@ -1,7 +1,6 @@
 #![cfg(feature = "std")]
 
 use tabled::{
-    grid::util::string::get_text_width,
     settings::{
         formatting::{TabSize, TrimStrategy},
         object::{Columns, Object, Rows, Segment},
@@ -9,10 +8,11 @@ use tabled::{
         width::{Justify, MinWidth, SuffixLimit, Width},
         Alignment, Margin, Modify, Padding, Panel, Settings, Span, Style,
     },
+    Table,
 };
 
 use crate::matrix::Matrix;
-use testing_table::{assert_width, static_table, test_table};
+use testing_table::{assert_width, test_table};
 
 #[cfg(feature = "ansi")]
 use ::{
@@ -88,40 +88,28 @@ test_table!(
 
 test_table!(
     max_width_wrapped_keep_words_0,
-    {
-        let table = Matrix::iter(vec!["this is a long sentence"])
-            .with(Style::markdown())
-            .with(Modify::new(Segment::all()).with(Alignment::left()))
-            .with(Modify::new(Segment::all()).with(Width::wrap(17).keep_words(true)))
-            .to_string();
-
-        assert_width!(table, 17 + 2 + 2);
-
-        table
-    },
-    "| &str              |"
-    "|-------------------|"
-    "| this is a long    |"
-    "| sentence          |"
+    Matrix::iter(vec!["this is a long sentence"])
+        .with(Style::markdown())
+        .with(Modify::new(Segment::all()).with(Alignment::left()))
+        .with(Modify::new(Segment::all()).with(Width::wrap(17).keep_words(true)))
+        .to_string(),
+    "| &str            |"
+    "|-----------------|"
+    "| this is a long  |"
+    "| sentence        |"
 );
 
 test_table!(
     max_width_wrapped_keep_words_1,
-    {
-        let table = Matrix::iter(vec!["this is a long  sentence"])
-            .with(Style::markdown())
-            .with(Modify::new(Segment::all()).with(Alignment::left()))
-            .with(Modify::new(Segment::all()).with(Width::wrap(17).keep_words(true)))
-            .to_string();
-
-        assert_width!(&table, 17 + 2 + 2);
-
-        table
-    },
-    "| &str              |"
-    "|-------------------|"
-    "| this is a long    |"
-    "| sentence          |"
+    Matrix::iter(vec!["this is a long  sentence"])
+        .with(Style::markdown())
+        .with(Modify::new(Segment::all()).with(Alignment::left()))
+        .with(Modify::new(Segment::all()).with(Width::wrap(17).keep_words(true)))
+        .to_string(),
+    "| &str             |"
+    "|------------------|"
+    "| this is a long   |"
+    "| sentence         |"
 );
 
 test_table!(
@@ -214,10 +202,10 @@ test_table!(
 
         AnsiStr::ansi_strip(&table).to_string()
     },
-    "| String            |"
-    "|-------------------|"
-    "| this is a long    |"
-    "| sentence          |"
+    "| String          |"
+    "|-----------------|"
+    "| this is a long  |"
+    "| sentence        |"
 );
 
 #[cfg(feature = "ansi")]
@@ -227,10 +215,10 @@ test_table!(
         .with(Style::markdown())
         .with(Modify::new(Segment::all()).with(Alignment::left()))
         .with(Modify::new(Segment::all()).with(Width::wrap(17).keep_words(true))),
-        "| String            |"
-        "|-------------------|"
-        "| \u{1b}[32m\u{1b}[40mthis is a long \u{1b}[39m\u{1b}[49m   |"
-        "| \u{1b}[32m\u{1b}[40msentence\u{1b}[39m\u{1b}[49m          |"
+        "| String          |"
+        "|-----------------|"
+        "| \u{1b}[32m\u{1b}[40mthis is a long \u{1b}[39m\u{1b}[49m |"
+        "| \u{1b}[32m\u{1b}[40msentence\u{1b}[39m\u{1b}[49m        |"
 );
 
 #[cfg(feature = "ansi")]
@@ -245,10 +233,10 @@ test_table!(
 
         AnsiStr::ansi_strip(&table).to_string()
     },
-    "| String            |"
-    "|-------------------|"
-    "| this is a long    |"
-    "| sentence          |"
+    "| String           |"
+    "|------------------|"
+    "| this is a long   |"
+    "| sentence         |"
 );
 
 #[cfg(feature = "ansi")]
@@ -258,10 +246,10 @@ test_table!(
         .with(Style::markdown())
         .with(Modify::new(Segment::all()).with(Alignment::left()))
         .with(Modify::new(Segment::all()).with(Width::wrap(17).keep_words(true))),
-    "| String            |"
-    "|-------------------|"
-    "| \u{1b}[32m\u{1b}[40mthis is a long  \u{1b}[39m\u{1b}[49m  |"
-    "| \u{1b}[32m\u{1b}[40msentence\u{1b}[39m\u{1b}[49m          |"
+    "| String           |"
+    "|------------------|"
+    "| \u{1b}[32m\u{1b}[40mthis is a long  \u{1b}[39m\u{1b}[49m |"
+    "| \u{1b}[32m\u{1b}[40msentence\u{1b}[39m\u{1b}[49m         |"
 );
 
 #[cfg(feature = "ansi")]
@@ -367,662 +355,508 @@ test_table!(
 );
 
 #[cfg(feature = "ansi")]
-#[test]
-fn max_width_wrapped_keep_words_long_word_color() {
-    let data = vec![
-        (Color::BG_BLACK | Color::FG_GREEN).colorize("this is a long sentencesentencesentence")
-    ];
-    let table = Matrix::iter(data)
-        .with(Style::markdown())
-        .with(Modify::new(Segment::all()).with(Alignment::left()))
-        .with(Modify::new(Segment::all()).with(Width::wrap(17).keep_words(true)))
-        .to_string();
-
-    assert_eq!(
-        ansi_str::AnsiStr::ansi_strip(&table),
-        static_table!(
-            "| String            |"
-            "|-------------------|"
-            "| this is a long se |"
-            "| ntencesentencesen |"
-            "| tence             |"
-        )
-    );
-
-    assert_eq!(
-        table,
-        static_table!(
-            "| String            |"
-            "|-------------------|"
-            "| \u{1b}[32m\u{1b}[40mthis is a long se\u{1b}[39m\u{1b}[49m |"
-            "| \u{1b}[32m\u{1b}[40mntencesentencesen\u{1b}[39m\u{1b}[49m |"
-            "| \u{1b}[32m\u{1b}[40mtence\u{1b}[39m\u{1b}[49m             |"
-        )
-    );
-}
+test_table!(
+    max_width_wrapped_keep_words_long_word_color,
+    {
+        let color = Color::BG_BLACK | Color::FG_GREEN;
+        let data = vec![color.colorize("this is a long sentencesentencesentence")];
+        Table::new(data)
+            .with(Style::markdown())
+            .with(Alignment::left())
+            .with(Width::wrap(21).keep_words(true))
+            .to_string()
+    },
+    "| String            |"
+    "|-------------------|"
+    "| \u{1b}[32m\u{1b}[40mthis is a long se\u{1b}[39m\u{1b}[49m |"
+    "| \u{1b}[32m\u{1b}[40mntencesentencesen\u{1b}[39m\u{1b}[49m |"
+    "| \u{1b}[32m\u{1b}[40mtence\u{1b}[39m\u{1b}[49m             |"
+);
 
 #[cfg(feature = "ansi")]
-#[test]
-fn max_width_keep_words_1() {
-    let table = Matrix::iter(["asdf"])
-        .with(Width::wrap(7).keep_words(true))
-        .to_string();
-
-    assert_eq!(
-        table,
-        static_table!(
-            "+-----+"
-            "| &st |"
-            "| r   |"
-            "+-----+"
-            "| asd |"
-            "| f   |"
-            "+-----+"
-        )
-    );
-
-    let table = Matrix::iter(["qweqw eqwe"])
-        .with(Width::wrap(8).keep_words(true))
-        .to_string();
-
-    assert_eq!(
-        table,
-        static_table!(
-            "+------+"
-            "| &str |"
-            "+------+"
-            "| qweq |"
-            "| w    |"
-            "| eqwe |"
-            "+------+"
-        )
-    );
+test_table!(
+    max_width_keep_words_1,
+    Matrix::iter(["asdf"])
+        .with(Width::wrap(7).keep_words(true)),
+    "+-----+"
+    "| &st |"
+    "| r   |"
+    "+-----+"
+    "| asd |"
+    "| f   |"
+    "+-----+"
+);
 
-    let table = Matrix::iter([
-        ["123 45678", "qweqw eqwe", "..."],
-        ["0", "1", "..."],
-        ["0", "1", "..."],
-    ])
-    .with(
-        Style::modern()
-            .remove_horizontal()
-            .horizontals([(1, HorizontalLine::inherit(Style::modern()))]),
-    )
-    .with(
-        Width::wrap(21)
-            .keep_words(true)
-            .priority(PriorityMax::right()),
-    )
-    .with(Alignment::center())
-    .to_string();
-
-    assert_eq!(
-        table,
-        static_table!(
-            "┌──────┬──────┬─────┐"
-            "│  0   │  1   │  2  │"
-            "├──────┼──────┼─────┤"
-            "│ 123  │ qweq │ ... │"
-            "│ 4567 │ w    │     │"
-            "│ 8    │ eqwe │     │"
-            "│  0   │  1   │ ... │"
-            "│  0   │  1   │ ... │"
-            "└──────┴──────┴─────┘"
-        )
-    );
-}
+#[cfg(feature = "ansi")]
+test_table!(
+    max_width_keep_words_2,
+    Matrix::iter(["qweqw eqwe"])
+        .with(Width::wrap(8).keep_words(true)),
+    "+------+"
+    "| &str |"
+    "+------+"
+    "| qweq |"
+    "| w    |"
+    "| eqwe |"
+    "+------+"
+);
 
 #[cfg(feature = "ansi")]
-#[test]
-fn max_width_wrapped_collored() {
-    let data = &[
-        Color::FG_RED.colorize("asd"),
-        Color::FG_BLUE.colorize("zxc2"),
-        (Color::FG_GREEN | Color::BG_BLACK).colorize("asdasd"),
-    ];
+test_table!(
+    max_width_keep_words_3,
+    {
+        let mut m = Matrix::iter([
+            ["123 45678", "qweqw eqwe", "..."],
+            ["0", "1", "..."],
+            ["0", "1", "..."],
+        ]);
+
+        m.with(Alignment::center())
+            .with(
+                Style::modern()
+                    .remove_horizontal()
+                    .horizontals([(1, HorizontalLine::inherit(Style::modern()))]),
+            )
+            .with(
+                Width::wrap(21)
+                    .keep_words(true)
+                    .priority(PriorityMax::right()),
+            )
+            .to_string()
+    },
+    "┌──────┬──────┬─────┐"
+    "│  0   │  1   │  2  │"
+    "├──────┼──────┼─────┤"
+    "│ 123  │ qweq │ ... │"
+    "│ 4567 │ w    │     │"
+    "│ 8    │ eqwe │     │"
+    "│  0   │  1   │ ... │"
+    "│  0   │  1   │ ... │"
+    "└──────┴──────┴─────┘"
+);
 
-    let table = Matrix::iter(data)
-        .with(Style::markdown())
-        .with(Modify::new(Segment::all()).with(Width::wrap(2)))
-        .to_string();
+#[cfg(feature = "ansi")]
+test_table!(
+    max_width_wrapped_collored,
+    {
+        let data = &[
+            Color::FG_RED.colorize("asd"),
+            Color::FG_BLUE.colorize("zxc2"),
+            (Color::FG_GREEN | Color::BG_BLACK).colorize("asdasd"),
+        ];
 
-    assert_eq!(
-        table,
-        "| St |\n| ri |\n| ng |\n|----|\n| \u{1b}[31mas\u{1b}[39m |\n| \u{1b}[31md\u{1b}[39m  |\n| \u{1b}[34mzx\u{1b}[39m |\n| \u{1b}[34mc2\u{1b}[39m |\n| \u{1b}[32m\u{1b}[40mas\u{1b}[39m\u{1b}[49m |\n| \u{1b}[32m\u{1b}[40mda\u{1b}[39m\u{1b}[49m |\n| \u{1b}[32m\u{1b}[40msd\u{1b}[39m\u{1b}[49m |"
-    );
-}
+        Matrix::iter(data)
+            .with(Style::markdown())
+            .modify(Segment::all(), Width::wrap(2))
+            .to_string()
+    },
+    "| St |"
+    "| ri |"
+    "| ng |"
+    "|----|"
+    "| \u{1b}[31mas\u{1b}[39m |"
+    "| \u{1b}[31md\u{1b}[39m  |"
+    "| \u{1b}[34mzx\u{1b}[39m |"
+    "| \u{1b}[34mc2\u{1b}[39m |"
+    "| \u{1b}[32m\u{1b}[40mas\u{1b}[39m\u{1b}[49m |"
+    "| \u{1b}[32m\u{1b}[40mda\u{1b}[39m\u{1b}[49m |"
+    "| \u{1b}[32m\u{1b}[40msd\u{1b}[39m\u{1b}[49m |"
+);
 
-#[test]
-fn dont_change_content_if_width_is_less_then_max_width() {
-    let table = Matrix::new(3, 3)
+test_table!(
+    dont_change_content_if_width_is_less_then_max_width,
+    Matrix::new(3, 3)
         .with(Style::markdown())
         .with(Modify::new(Segment::all()).with(Width::truncate(1000).suffix("...")))
-        .to_string();
-
-    assert_eq!(
-        table,
-        static_table!(
-            "| N | column 0 | column 1 | column 2 |"
-            "|---|----------|----------|----------|"
-            "| 0 |   0-0    |   0-1    |   0-2    |"
-            "| 1 |   1-0    |   1-1    |   1-2    |"
-            "| 2 |   2-0    |   2-1    |   2-2    |"
-        )
-    );
-}
-
-#[test]
-fn max_width_with_emoji() {
-    let data = &["🤠", "😳🥵🥶😱😨", "🚴🏻‍♀️🚴🏻🚴🏻‍♂️🚵🏻‍♀️🚵🏻🚵🏻‍♂️"];
+        .to_string(),
+    "| N | column 0 | column 1 | column 2 |"
+    "|---|----------|----------|----------|"
+    "| 0 |   0-0    |   0-1    |   0-2    |"
+    "| 1 |   1-0    |   1-1    |   1-2    |"
+    "| 2 |   2-0    |   2-1    |   2-2    |"
+);
 
-    let table = Matrix::iter(data)
+test_table!(
+    max_width_with_emoji,
+    Matrix::iter(["🤠", "😳🥵🥶😱😨", "🚴🏻‍♀️🚴🏻🚴🏻‍♂️🚵🏻‍♀️🚵🏻🚵🏻‍♂️"])
         .with(Style::markdown())
-        .with(Modify::new(Segment::all()).with(Width::truncate(6).suffix("...")))
-        .to_string();
-
-    assert_eq!(
-        table,
-        static_table!(
-            "|  &str  |"
-            "|--------|"
-            "|   🤠   |"
-            "| 😳�... |"
-            "| 🚴�... |"
-        )
-    );
-}
+        .modify(Segment::all(), Width::truncate(6).suffix("..."))
+        .to_string(),
+    "|  &str  |"
+    "|--------|"
+    "|   🤠   |"
+    "| 😳�... |"
+    "| 🚴�... |"
+);
 
 #[cfg(feature = "ansi")]
-#[test]
-fn color_chars_are_stripped() {
-    let data = &[
+test_table!(
+    color_chars_are_stripped,
+    Matrix::iter(&[
         Color::FG_RED.colorize("asd"),
         Color::FG_BLUE.colorize("zxc"),
         (Color::FG_GREEN | Color::BG_BLACK).colorize("asdasd"),
-    ];
-
-    let table = Matrix::iter(data)
-        .with(Style::markdown())
-        .with(Modify::new(Segment::all()).with(Width::truncate(4).suffix("...")))
-        .to_string();
+    ])
+    .with(Style::markdown())
+    .modify(Segment::all(), Width::truncate(4).suffix("..."))
+    .to_string(),
+    "| S... |"
+    "|------|"
+    "| \u{1b}[31masd\u{1b}[39m  |"
+    "| \u{1b}[34mzxc\u{1b}[39m  |"
+    "| \u{1b}[32m\u{1b}[40ma\u{1b}[39m\u{1b}[49m... |"
+);
 
-    assert_eq!(
-        ansi_str::AnsiStr::ansi_strip(&table),
-        static_table!(
-            "| S... |"
-            "|------|"
-            "| asd  |"
-            "| zxc  |"
-            "| a... |"
-        )
-    );
+test_table!(
+    min_width_0,
+    Matrix::table(3, 3)
+        .with(Style::markdown())
+        .modify(Rows::single(0), MinWidth::new(12)),
+    "| N            | column 0     | column 1     | column 2     |"
+    "|--------------|--------------|--------------|--------------|"
+    "|      0       |     0-0      |     0-1      |     0-2      |"
+    "|      1       |     1-0      |     1-1      |     1-2      |"
+    "|      2       |     2-0      |     2-1      |     2-2      |"
+);
 
-    assert_eq!(
-        table,
-        "| S... |\n|------|\n| \u{1b}[31masd\u{1b}[39m  |\n| \u{1b}[34mzxc\u{1b}[39m  |\n| \u{1b}[32m\u{1b}[40ma\u{1b}[39m\u{1b}[49m... |",
-    );
-}
+test_table!(
+    min_width_1,
+    Matrix::table(3, 3)
+        .with(Style::markdown())
+        .modify(Rows::single(0), MinWidth::new(12))
+        .modify(Segment::all(), TrimStrategy::None),
+    "| N            | column 0     | column 1     | column 2     |"
+    "|--------------|--------------|--------------|--------------|"
+    "|      0       |     0-0      |     0-1      |     0-2      |"
+    "|      1       |     1-0      |     1-1      |     1-2      |"
+    "|      2       |     2-0      |     2-1      |     2-2      |"
+);
 
-#[test]
-fn min_width() {
-    let mut table = Matrix::table(3, 3);
-    table
-        .with(Style::markdown())
-        .with(Modify::new(Rows::single(0)).with(MinWidth::new(12)));
-
-    assert_eq!(
-        table.to_string(),
-        static_table!(
-            "| N            | column 0     | column 1     | column 2     |"
-            "|--------------|--------------|--------------|--------------|"
-            "|      0       |     0-0      |     0-1      |     0-2      |"
-            "|      1       |     1-0      |     1-1      |     1-2      |"
-            "|      2       |     2-0      |     2-1      |     2-2      |"
-        ),
-    );
-
-    table.with(Modify::new(Segment::all()).with(TrimStrategy::None));
-
-    assert_eq!(
-        table.to_string(),
-        static_table!(
-            "| N            | column 0     | column 1     | column 2     |"
-            "|--------------|--------------|--------------|--------------|"
-            "|      0       |     0-0      |     0-1      |     0-2      |"
-            "|      1       |     1-0      |     1-1      |     1-2      |"
-            "|      2       |     2-0      |     2-1      |     2-2      |"
-        ),
-    );
-}
+test_table!(
+    min_width_with_filler,
+    Matrix::new(3, 3)
+        .with(Style::markdown())
+        .modify(Rows::single(0), MinWidth::new(12).fill_with('.'))
+        .to_string(),
+    "| N........... | column 0.... | column 1.... | column 2.... |"
+    "|--------------|--------------|--------------|--------------|"
+    "|      0       |     0-0      |     0-1      |     0-2      |"
+    "|      1       |     1-0      |     1-1      |     1-2      |"
+    "|      2       |     2-0      |     2-1      |     2-2      |"
+);
 
-#[test]
-fn min_width_with_filler() {
-    let table = Matrix::new(3, 3)
-        .with(Style::markdown())
-        .with(Modify::new(Rows::single(0)).with(MinWidth::new(12).fill_with('.')))
-        .to_string();
-
-    assert_eq!(
-        table,
-        static_table!(
-            "| N........... | column 0.... | column 1.... | column 2.... |"
-            "|--------------|--------------|--------------|--------------|"
-            "|      0       |     0-0      |     0-1      |     0-2      |"
-            "|      1       |     1-0      |     1-1      |     1-2      |"
-            "|      2       |     2-0      |     2-1      |     2-2      |"
-        )
-    );
-}
+test_table!(
+    min_width_one_column_0,
+    Matrix::table(3, 3)
+        .with(Style::markdown())
+        .modify((0, 0), MinWidth::new(5)),
+    "| N     | column 0 | column 1 | column 2 |"
+    "|-------|----------|----------|----------|"
+    "|   0   |   0-0    |   0-1    |   0-2    |"
+    "|   1   |   1-0    |   1-1    |   1-2    |"
+    "|   2   |   2-0    |   2-1    |   2-2    |"
+);
 
-#[test]
-fn min_width_one_column() {
-    let mut table = Matrix::table(3, 3);
-    table
-        .with(Style::markdown())
-        .with(Modify::new((0, 0)).with(MinWidth::new(5)));
-
-    assert_eq!(
-        table.to_string(),
-        static_table!(
-            "| N     | column 0 | column 1 | column 2 |"
-            "|-------|----------|----------|----------|"
-            "|   0   |   0-0    |   0-1    |   0-2    |"
-            "|   1   |   1-0    |   1-1    |   1-2    |"
-            "|   2   |   2-0    |   2-1    |   2-2    |"
-        )
-    );
-
-    table.with(Modify::new(Segment::all()).with(TrimStrategy::None));
-
-    assert_eq!(
-        table.to_string(),
-        static_table!(
-            "| N     | column 0 | column 1 | column 2 |"
-            "|-------|----------|----------|----------|"
-            "|   0   |   0-0    |   0-1    |   0-2    |"
-            "|   1   |   1-0    |   1-1    |   1-2    |"
-            "|   2   |   2-0    |   2-1    |   2-2    |"
-        )
-    );
-}
+test_table!(
+    min_width_one_column_1,
+    Matrix::table(3, 3)
+        .with(Style::markdown())
+        .modify((0, 0), MinWidth::new(5))
+        .modify(Segment::all(), TrimStrategy::None),
+    "| N     | column 0 | column 1 | column 2 |"
+    "|-------|----------|----------|----------|"
+    "|   0   |   0-0    |   0-1    |   0-2    |"
+    "|   1   |   1-0    |   1-1    |   1-2    |"
+    "|   2   |   2-0    |   2-1    |   2-2    |"
+);
 
-#[test]
-fn min_width_on_smaller_content() {
-    assert_eq!(
-        Matrix::new(3, 3)
-            .with(Style::markdown())
-            .with(Modify::new(Rows::single(0)).with(MinWidth::new(1)))
-            .to_string(),
-        Matrix::new(3, 3).with(Style::markdown()).to_string()
-    );
-}
+test_table!(
+    min_width_on_smaller_content,
+    Matrix::new(3, 3)
+        .with(Style::markdown())
+        .modify(Rows::single(0), MinWidth::new(1))
+        .to_string(),
+    "| N | column 0 | column 1 | column 2 |"
+    "|---|----------|----------|----------|"
+    "| 0 |   0-0    |   0-1    |   0-2    |"
+    "| 1 |   1-0    |   1-1    |   1-2    |"
+    "| 2 |   2-0    |   2-1    |   2-2    |"
+);
 
-#[test]
-fn min_with_max_width() {
-    let mut table = Matrix::table(3, 3);
-    table
+test_table!(
+    min_with_max_width_0,
+    Matrix::table(3, 3)
         .with(Style::markdown())
         .with(Modify::new(Rows::single(0)).with(MinWidth::new(3)))
-        .with(Modify::new(Rows::single(0)).with(Width::truncate(3)));
-
-    assert_eq!(
-        table.to_string(),
-        static_table!(
-            "| N   | col | col | col |"
-            "|-----|-----|-----|-----|"
-            "|  0  | 0-0 | 0-1 | 0-2 |"
-            "|  1  | 1-0 | 1-1 | 1-2 |"
-            "|  2  | 2-0 | 2-1 | 2-2 |"
-        )
-    );
-
-    table.with(Modify::new(Segment::all()).with(TrimStrategy::None));
-
-    assert_eq!(
-        table.to_string(),
-        static_table!(
-            "| N   | col | col | col |"
-            "|-----|-----|-----|-----|"
-            "|  0  | 0-0 | 0-1 | 0-2 |"
-            "|  1  | 1-0 | 1-1 | 1-2 |"
-            "|  2  | 2-0 | 2-1 | 2-2 |"
-        )
-    );
-}
+        .with(Modify::new(Rows::single(0)).with(Width::truncate(3))),
+    "| N   | col | col | col |"
+    "|-----|-----|-----|-----|"
+    "|  0  | 0-0 | 0-1 | 0-2 |"
+    "|  1  | 1-0 | 1-1 | 1-2 |"
+    "|  2  | 2-0 | 2-1 | 2-2 |"
+);
 
-#[test]
-fn min_with_max_width_truncate_suffix() {
-    let mut table = Matrix::table(3, 3);
-    table
+test_table!(
+    min_with_max_width_1,
+    Matrix::table(3, 3)
         .with(Style::markdown())
         .with(Modify::new(Rows::single(0)).with(MinWidth::new(3)))
-        .with(Modify::new(Rows::single(0)).with(Width::truncate(3).suffix("...")));
-
-    assert_eq!(
-        table.to_string(),
-        static_table!(
-            "| N   | ... | ... | ... |"
-            "|-----|-----|-----|-----|"
-            "|  0  | 0-0 | 0-1 | 0-2 |"
-            "|  1  | 1-0 | 1-1 | 1-2 |"
-            "|  2  | 2-0 | 2-1 | 2-2 |"
-        )
-    );
-
-    table.with(Modify::new(Segment::all()).with(TrimStrategy::None));
-
-    assert_eq!(
-        table.to_string(),
-        static_table!(
-            "| N   | ... | ... | ... |"
-            "|-----|-----|-----|-----|"
-            "|  0  | 0-0 | 0-1 | 0-2 |"
-            "|  1  | 1-0 | 1-1 | 1-2 |"
-            "|  2  | 2-0 | 2-1 | 2-2 |"
-        )
-    );
-}
+        .with(Modify::new(Rows::single(0)).with(Width::truncate(3)))
+        .with(Modify::new(Segment::all()).with(TrimStrategy::None)),
+    "| N   | col | col | col |"
+    "|-----|-----|-----|-----|"
+    "|  0  | 0-0 | 0-1 | 0-2 |"
+    "|  1  | 1-0 | 1-1 | 1-2 |"
+    "|  2  | 2-0 | 2-1 | 2-2 |"
+);
 
-#[test]
-fn min_with_max_width_truncate_suffix_limit_replace() {
-    let table = Matrix::new(3, 3)
+test_table!(
+    min_with_max_width_truncate_suffix_0,
+    Matrix::table(3, 3)
         .with(Style::markdown())
-        .with(
-            Modify::new(Rows::single(0)).with(
-                Width::truncate(3)
-                    .suffix("...")
-                    .suffix_limit(SuffixLimit::Replace('x')),
-            ),
-        )
-        .to_string();
-
-    assert_eq!(
-        table,
-        static_table!(
-            "| N | xxx | xxx | xxx |"
-            "|---|-----|-----|-----|"
-            "| 0 | 0-0 | 0-1 | 0-2 |"
-            "| 1 | 1-0 | 1-1 | 1-2 |"
-            "| 2 | 2-0 | 2-1 | 2-2 |"
-        )
-    );
-}
+        .with(Modify::new(Rows::single(0)).with(MinWidth::new(3)))
+        .with(Modify::new(Rows::single(0)).with(Width::truncate(3).suffix("..."))),
+    "| N   | ... | ... | ... |"
+    "|-----|-----|-----|-----|"
+    "|  0  | 0-0 | 0-1 | 0-2 |"
+    "|  1  | 1-0 | 1-1 | 1-2 |"
+    "|  2  | 2-0 | 2-1 | 2-2 |"
+);
 
-#[test]
-fn min_with_max_width_truncate_suffix_limit_cut() {
-    let table = Matrix::new(3, 3)
+test_table!(
+    min_with_max_width_truncate_suffix_1,
+    Matrix::table(3, 3)
         .with(Style::markdown())
-        .with(
-            Modify::new(Rows::single(0)).with(
-                Width::truncate(3)
-                    .suffix("qwert")
-                    .suffix_limit(SuffixLimit::Cut),
-            ),
-        )
-        .to_string();
-
-    assert_eq!(
-        table,
-        static_table!(
-            "| N | qwe | qwe | qwe |"
-            "|---|-----|-----|-----|"
-            "| 0 | 0-0 | 0-1 | 0-2 |"
-            "| 1 | 1-0 | 1-1 | 1-2 |"
-            "| 2 | 2-0 | 2-1 | 2-2 |"
-        )
-    );
-}
+        .with(Modify::new(Rows::single(0)).with(MinWidth::new(3)))
+        .with(Modify::new(Rows::single(0)).with(Width::truncate(3).suffix("...")))
+        .with(Modify::new(Segment::all()).with(TrimStrategy::None)),
+    "| N   | ... | ... | ... |"
+    "|-----|-----|-----|-----|"
+    "|  0  | 0-0 | 0-1 | 0-2 |"
+    "|  1  | 1-0 | 1-1 | 1-2 |"
+    "|  2  | 2-0 | 2-1 | 2-2 |"
+);
 
-#[test]
-fn min_with_max_width_truncate_suffix_limit_ignore() {
-    let table = Matrix::new(3, 3)
+test_table!(
+    min_with_max_width_truncate_suffix_limit_replace,
+    Matrix::new(3, 3)
         .with(Style::markdown())
-        .with(
-            Modify::new(Rows::single(0)).with(
-                Width::truncate(3)
-                    .suffix("qwert")
-                    .suffix_limit(SuffixLimit::Ignore),
-            ),
-        )
-        .to_string();
-
-    assert_eq!(
-        table,
-        static_table!(
-            "| N | col | col | col |"
-            "|---|-----|-----|-----|"
-            "| 0 | 0-0 | 0-1 | 0-2 |"
-            "| 1 | 1-0 | 1-1 | 1-2 |"
-            "| 2 | 2-0 | 2-1 | 2-2 |"
-        )
-    );
-}
-
-#[cfg(feature = "ansi")]
-#[test]
-fn min_with_max_width_truncate_suffix_try_color() {
-    let data = &[
-        Color::FG_RED.colorize("asd"),
-        Color::FG_BLUE.colorize("zxc2"),
-        (Color::FG_GREEN | Color::BG_BLACK).colorize("asdasd"),
-    ];
+        .modify(
+            Rows::single(0),
+            Width::truncate(3)
+                .suffix("...")
+                .suffix_limit(SuffixLimit::Replace('x'))
+        )
+        .to_string(),
+    "| N | xxx | xxx | xxx |"
+    "|---|-----|-----|-----|"
+    "| 0 | 0-0 | 0-1 | 0-2 |"
+    "| 1 | 1-0 | 1-1 | 1-2 |"
+    "| 2 | 2-0 | 2-1 | 2-2 |"
+);
 
-    let table = Matrix::iter(data)
+test_table!(
+    min_with_max_width_truncate_suffix_limit_cut,
+    Matrix::new(3, 3)
         .with(Style::markdown())
-        .with(Width::truncate(7).suffix("..").suffix_try_color(true))
-        .to_string();
+        .modify(
+            Rows::single(0),
+            Width::truncate(3)
+                .suffix("qwert")
+                .suffix_limit(SuffixLimit::Cut)
+        ),
+    "| N | qwe | qwe | qwe |"
+    "|---|-----|-----|-----|"
+    "| 0 | 0-0 | 0-1 | 0-2 |"
+    "| 1 | 1-0 | 1-1 | 1-2 |"
+    "| 2 | 2-0 | 2-1 | 2-2 |"
+);
 
-    assert_eq!(
-        table,
-        static_table!(
-            "| S.. |"
-            "|-----|"
-            "| \u{1b}[31masd\u{1b}[39m |"
-            "| \u{1b}[34mz\u{1b}[39m\u{1b}[34m..\u{1b}[39m |"
-            "| \u{1b}[32m\u{1b}[40ma\u{1b}[39m\u{1b}[49m\u{1b}[32m\u{1b}[40m..\u{1b}[39m\u{1b}[49m |"
-        )
-    );
-}
+test_table!(
+    min_with_max_width_truncate_suffix_limit_ignore,
+    Matrix::new(3, 3)
+        .with(Style::markdown())
+        .modify(
+            Rows::single(0),
+            Width::truncate(3)
+                .suffix("qwert")
+                .suffix_limit(SuffixLimit::Ignore),
+        ),
+    "| N | col | col | col |"
+    "|---|-----|-----|-----|"
+    "| 0 | 0-0 | 0-1 | 0-2 |"
+    "| 1 | 1-0 | 1-1 | 1-2 |"
+    "| 2 | 2-0 | 2-1 | 2-2 |"
+);
 
 #[cfg(feature = "ansi")]
-#[test]
-fn min_width_color() {
-    let data = &[
-        Color::FG_RED.colorize("asd"),
-        Color::FG_BLUE.colorize("zxc"),
-        (Color::FG_GREEN | Color::BG_BLACK).colorize("asdasd"),
-    ];
+test_table!(
+    min_with_max_width_truncate_suffix_try_color,
+    {
+        let data = &[
+            Color::FG_RED.colorize("asd"),
+            Color::FG_BLUE.colorize("zxc2"),
+            (Color::FG_GREEN | Color::BG_BLACK).colorize("asdasd"),
+        ];
 
-    let table = Matrix::iter(data)
-        .with(Style::markdown())
-        .with(Modify::new(Segment::all()).with(MinWidth::new(10)))
-        .to_string();
+        Matrix::iter(data)
+            .with(Style::markdown())
+            .with(Width::truncate(7).suffix("..").suffix_try_color(true))
+    },
+    "| S.. |"
+    "|-----|"
+    "| \u{1b}[31masd\u{1b}[39m |"
+    "| \u{1b}[34mz\u{1b}[39m\u{1b}[34m..\u{1b}[39m |"
+    "| \u{1b}[32m\u{1b}[40ma\u{1b}[39m\u{1b}[49m\u{1b}[32m\u{1b}[40m..\u{1b}[39m\u{1b}[49m |"
+);
 
-    assert_eq!(
-        ansi_str::AnsiStr::ansi_strip(&table),
-        static_table!(
-            "| String     |"
-            "|------------|"
-            "| asd        |"
-            "| zxc        |"
-            "| asdasd     |"
-        )
-    );
+#[cfg(feature = "ansi")]
+test_table!(
+    min_width_color,
+    {
+        let data = &[
+            Color::FG_RED.colorize("asd"),
+            Color::FG_BLUE.colorize("zxc"),
+            (Color::FG_GREEN | Color::BG_BLACK).colorize("asdasd"),
+        ];
 
-    assert_eq!(
-        table,
-        "| String     |\n|------------|\n| \u{1b}[31masd\u{1b}[39m        |\n| \u{1b}[34mzxc\u{1b}[39m        |\n| \u{1b}[32m\u{1b}[40masdasd\u{1b}[39m\u{1b}[49m     |",
-    );
-}
+        Matrix::iter(data)
+            .with(Style::markdown())
+            .with(Modify::new(Segment::all()).with(MinWidth::new(10)))
+    },
+    "| String     |"
+    "|------------|"
+    "| \u{1b}[31masd\u{1b}[39m        |"
+    "| \u{1b}[34mzxc\u{1b}[39m        |"
+    "| \u{1b}[32m\u{1b}[40masdasd\u{1b}[39m\u{1b}[49m     |"
+);
 
 #[cfg(feature = "ansi")]
-#[test]
-fn min_width_color_with_smaller_then_width() {
-    let data = &[
-        Color::FG_RED.colorize("asd"),
-        Color::FG_BLUE.colorize("zxc2"),
-        (Color::FG_GREEN | Color::BG_BLACK).colorize("asdasd"),
-    ];
+test_table!(
+    min_width_color_with_smaller_then_width,
+    {
+        let data = &[
+            Color::FG_RED.colorize("asd"),
+            Color::FG_BLUE.colorize("zxc2"),
+            (Color::FG_GREEN | Color::BG_BLACK).colorize("asdasd"),
+        ];
 
-    assert_eq!(
         Matrix::iter(data)
-            .with(Modify::new(Segment::all()).with(MinWidth::new(1)))
-            .to_string(),
-        Matrix::iter(data).to_string()
-    );
-}
+            .modify(Segment::all(), MinWidth::new(1))
+    },
+    "+--------+"
+    "| String |"
+    "+--------+"
+    "|  \u{1b}[31masd\u{1b}[39m   |"
+    "+--------+"
+    "|  \u{1b}[34mzxc2\u{1b}[39m  |"
+    "+--------+"
+    "| \u{1b}[32m\u{1b}[40masdasd\u{1b}[39m\u{1b}[49m |"
+    "+--------+"
+);
 
-#[test]
-fn total_width_big() {
-    let table = Matrix::new(3, 3)
+test_table!(
+    total_width_big_0,
+    Matrix::new(3, 3)
         .with(Style::markdown())
         .with(Width::truncate(80))
-        .with(MinWidth::new(80))
-        .to_string();
-
-    assert_eq!(get_text_width(&table), 80);
-    assert_eq!(
-        table,
-        static_table!(
-            "|      N       |      column 0       |      column 1      |      column 2      |"
-            "|--------------|---------------------|--------------------|--------------------|"
-            "|      0       |         0-0         |        0-1         |        0-2         |"
-            "|      1       |         1-0         |        1-1         |        1-2         |"
-            "|      2       |         2-0         |        2-1         |        2-2         |"
-        )
-    );
+        .with(MinWidth::new(80)),
+    "|      N       |      column 0       |      column 1      |      column 2      |"
+    "|--------------|---------------------|--------------------|--------------------|"
+    "|      0       |         0-0         |        0-1         |        0-2         |"
+    "|      1       |         1-0         |        1-1         |        1-2         |"
+    "|      2       |         2-0         |        2-1         |        2-2         |"
+);
 
-    let table = Matrix::new(3, 3)
+test_table!(
+    total_width_big_1,
+    Matrix::new(3, 3)
         .with(Style::markdown())
         .with(Modify::new(Segment::all()).with(TrimStrategy::None))
-        .with(Settings::new(Width::truncate(80), Width::increase(80)))
-        .to_string();
-
-    assert_eq!(get_text_width(&table), 80);
-    assert_eq!(
-        table,
-        static_table!(
-            "|      N       |      column 0       |      column 1      |      column 2      |"
-            "|--------------|---------------------|--------------------|--------------------|"
-            "|      0       |         0-0         |        0-1         |        0-2         |"
-            "|      1       |         1-0         |        1-1         |        1-2         |"
-            "|      2       |         2-0         |        2-1         |        2-2         |"
-        )
-    );
-}
+        .with(Settings::new(Width::truncate(80), Width::increase(80))),
+    "|      N       |      column 0       |      column 1      |      column 2      |"
+    "|--------------|---------------------|--------------------|--------------------|"
+    "|      0       |         0-0         |        0-1         |        0-2         |"
+    "|      1       |         1-0         |        1-1         |        1-2         |"
+    "|      2       |         2-0         |        2-1         |        2-2         |"
+);
 
-#[test]
-fn total_width_big_with_panel() {
-    let table = Matrix::new(3, 3)
+test_table!(
+    total_width_big_with_panel,
+    Matrix::new(3, 3)
         .with(Panel::horizontal(0, "Hello World"))
-        .with(
-            Modify::new(Segment::all())
-                .with(Alignment::center())
-                .with(Padding::zero()),
-        )
+        .with(Alignment::center())
+        .with(Padding::zero())
         .with(Style::markdown())
         .with(Width::truncate(80))
-        .with(MinWidth::new(80))
-        .to_string();
-
-    assert_width!(&table, 80);
-    assert_eq!(
-        table,
-        static_table!(
-            "|                                 Hello World                                  |"
-            "|--------------|---------------------|--------------------|--------------------|"
-            "|      N       |      column 0       |      column 1      |      column 2      |"
-            "|      0       |         0-0         |        0-1         |        0-2         |"
-            "|      1       |         1-0         |        1-1         |        1-2         |"
-            "|      2       |         2-0         |        2-1         |        2-2         |"
-        )
-    );
-}
+        .with(MinWidth::new(80)),
+    "|                                 Hello World                                  |"
+    "|--------------|---------------------|--------------------|--------------------|"
+    "|      N       |      column 0       |      column 1      |      column 2      |"
+    "|      0       |         0-0         |        0-1         |        0-2         |"
+    "|      1       |         1-0         |        1-1         |        1-2         |"
+    "|      2       |         2-0         |        2-1         |        2-2         |"
+);
 
-#[test]
-fn total_width_big_with_panel_with_wrapping_doesnt_affect_increase() {
-    let table1 = Matrix::new(3, 3)
+test_table!(
+    total_width_big_with_panel_with_wrapping_doesnt_affect_increase,
+    Matrix::new(3, 3)
         .with(Panel::horizontal(0, "Hello World"))
         .with(Modify::new(Segment::all()).with(Alignment::center()))
         .with(Style::markdown())
         .with(Width::wrap(80))
-        .with(MinWidth::new(80))
-        .to_string();
-
-    let table2 = Matrix::new(3, 3)
-        .with(Panel::horizontal(0, "Hello World"))
-        .with(Modify::new(Segment::all()).with(Alignment::center()))
-        .with(Style::markdown())
-        .with(Width::truncate(80))
-        .with(MinWidth::new(80))
-        .to_string();
-
-    assert_eq!(table1, table2);
-}
+        .with(MinWidth::new(80)),
+    "|                                 Hello World                                  |"
+    "|--------------|---------------------|--------------------|--------------------|"
+    "|      N       |      column 0       |      column 1      |      column 2      |"
+    "|      0       |         0-0         |        0-1         |        0-2         |"
+    "|      1       |         1-0         |        1-1         |        1-2         |"
+    "|      2       |         2-0         |        2-1         |        2-2         |"
+);
 
-#[test]
-fn total_width_small() {
-    let table = Matrix::new(3, 3)
+test_table!(
+    total_width_small,
+    Matrix::new(3, 3)
         .with(Style::markdown())
         .with(Width::truncate(14))
-        .with(MinWidth::new(14))
-        .to_string();
-
-    assert_eq!(
-        table,
-        static_table!(
-            "|  |  |  | c |"
-            "|--|--|--|---|"
-            "|  |  |  | 0 |"
-            "|  |  |  | 1 |"
-            "|  |  |  | 2 |"
-        )
-    );
-    assert_width!(table, 14);
-}
+        .with(MinWidth::new(14)),
+    "|  |  |  | c |"
+    "|--|--|--|---|"
+    "|  |  |  | 0 |"
+    "|  |  |  | 1 |"
+    "|  |  |  | 2 |"
+);
 
-#[test]
-fn total_width_smaller_then_content() {
-    let table = Matrix::new(3, 3)
+test_table!(
+    total_width_smaller_then_content,
+    Matrix::new(3, 3)
         .with(Style::markdown())
         .with(Width::truncate(8))
-        .with(MinWidth::new(8))
-        .to_string();
-
-    assert_eq!(
-        table,
-        static_table!(
-            "|  |  |  |  |"
-            "|--|--|--|--|"
-            "|  |  |  |  |"
-            "|  |  |  |  |"
-            "|  |  |  |  |"
-        )
-    );
-}
+        .with(MinWidth::new(8)),
+    "|  |  |  |  |"
+    "|--|--|--|--|"
+    "|  |  |  |  |"
+    "|  |  |  |  |"
+    "|  |  |  |  |"
+);
 
-#[test]
-fn total_width_small_with_panel() {
-    let table = Matrix::new(3, 3)
+test_table!(
+    total_width_small_with_panel_0,
+    Matrix::new(3, 3)
         .with(Modify::new(Segment::all()).with(Alignment::center()))
         .with(Style::markdown())
         .with(Width::truncate(20))
-        .with(MinWidth::new(20))
-        .to_string();
-
-    assert_eq!(
-        table,
-        static_table!(
-            "|  | co | co | col |"
-            "|--|----|----|-----|"
-            "|  | 0- | 0- | 0-2 |"
-            "|  | 1- | 1- | 1-2 |"
-            "|  | 2- | 2- | 2-2 |"
-        )
-    );
-    assert_width!(table, 20);
+        .with(MinWidth::new(20)),
+    "|  | co | co | col |"
+    "|--|----|----|-----|"
+    "|  | 0- | 0- | 0-2 |"
+    "|  | 1- | 1- | 1-2 |"
+    "|  | 2- | 2- | 2-2 |"
+);
 
-    let table = Matrix::iter(Vec::<usize>::new())
+test_table!(
+    total_width_small_with_panel_1,
+    Matrix::iter(Vec::<usize>::new())
         .with(Panel::horizontal(0, "Hello World"))
         .with(
             Modify::new(Segment::all())
@@ -1030,1418 +864,1105 @@ fn total_width_small_with_panel() {
                 .with(Padding::zero()),
         )
         .with(Width::truncate(5))
-        .with(MinWidth::new(5))
-        .to_string();
-
-    assert_eq!(
-        table,
-        static_table!("+---+" "|Hel|" "+---+" "|usi|" "+---+")
-    );
-    assert_width!(table, 5);
+        .with(MinWidth::new(5)),
+    "+---+"
+    "|Hel|"
+    "+---+"
+    "|usi|"
+    "+---+"
+);
 
-    let table = Matrix::table(1, 2)
+test_table!(
+    total_width_small_with_panel_2,
+    Matrix::table(1, 2)
         .with(Panel::horizontal(0, "Hello World"))
         .with(Modify::new(Segment::all()).with(Alignment::center()))
         .with(Style::markdown())
         .with(Width::truncate(20))
-        .with(MinWidth::new(20))
-        .to_string();
-
-    assert_eq!(
-        table,
-        static_table!(
-            "|   Hello World    |"
-            "|--|-------|-------|"
-            "|  | colum | colum |"
-            "|  |  0-0  |  0-1  |"
-        )
-    );
-    assert_width!(table, 20);
+        .with(MinWidth::new(20)),
+    "|   Hello World    |"
+    "|--|-------|-------|"
+    "|  | colum | colum |"
+    "|  |  0-0  |  0-1  |"
+);
 
-    let table = Matrix::new(3, 3)
+test_table!(
+    total_width_small_with_panel_3,
+    Matrix::new(3, 3)
         .with(Panel::horizontal(0, "Hello World"))
         .with(Modify::new(Segment::all()).with(Alignment::center()))
         .with(Style::markdown())
         .with(Width::truncate(20))
-        .with(MinWidth::new(20))
-        .to_string();
-
-    assert_eq!(
-        table,
-        static_table!(
-            "|   Hello World    |"
-            "|--|----|----|-----|"
-            "|  | co | co | col |"
-            "|  | 0- | 0- | 0-2 |"
-            "|  | 1- | 1- | 1-2 |"
-            "|  | 2- | 2- | 2-2 |"
-        )
-    );
-    assert_width!(table, 20);
+        .with(MinWidth::new(20)),
+    "|   Hello World    |"
+    "|--|----|----|-----|"
+    "|  | co | co | col |"
+    "|  | 0- | 0- | 0-2 |"
+    "|  | 1- | 1- | 1-2 |"
+    "|  | 2- | 2- | 2-2 |"
+);
 
-    let table = Matrix::new(3, 3)
+test_table!(
+    total_width_small_with_panel_4,
+    Matrix::new(3, 3)
         .with(Panel::horizontal(0, "Hello World"))
         .with(Modify::new(Segment::all()).with(Alignment::center()))
         .with(Style::markdown())
         .with(Width::truncate(6))
-        .with(MinWidth::new(6))
-        .to_string();
-
-    assert_eq!(
-        table,
-        static_table!(
-            "| Hello Wor |"
-            "|--|--|--|--|"
-            "|  |  |  |  |"
-            "|  |  |  |  |"
-            "|  |  |  |  |"
-            "|  |  |  |  |"
-        )
-    );
-    assert_width!(table, 13);
+        .with(MinWidth::new(6)),
+    "| Hello Wor |"
+    "|--|--|--|--|"
+    "|  |  |  |  |"
+    "|  |  |  |  |"
+    "|  |  |  |  |"
+    "|  |  |  |  |"
+);
 
-    let table = Matrix::new(3, 3)
+test_table!(
+    total_width_small_with_panel_5,
+    Matrix::new(3, 3)
         .with(Panel::horizontal(0, "Hello World"))
         .with(Modify::new(Segment::all()).with(Alignment::center()))
         .with(Style::markdown())
         .with(Width::truncate(14))
-        .with(MinWidth::new(14))
-        .to_string();
-
-    assert_eq!(
-        table,
-        static_table!(
-            "| Hello Worl |"
-            "|--|--|--|---|"
-            "|  |  |  | c |"
-            "|  |  |  | 0 |"
-            "|  |  |  | 1 |"
-            "|  |  |  | 2 |"
-        )
-    );
-    assert_width!(table, 14);
+        .with(MinWidth::new(14)),
+    "| Hello Worl |"
+    "|--|--|--|---|"
+    "|  |  |  | c |"
+    "|  |  |  | 0 |"
+    "|  |  |  | 1 |"
+    "|  |  |  | 2 |"
+);
 
-    let table = Matrix::new(3, 3)
+test_table!(
+    total_width_small_with_panel_6,
+    Matrix::new(3, 3)
         .with(Panel::horizontal(0, "Hello World 123"))
         .with(Modify::new(Segment::all()).with(Alignment::center()))
         .with(Style::markdown())
         .with(Width::truncate(14))
-        .with(MinWidth::new(14))
-        .to_string();
-
-    assert_eq!(
-        table,
-        static_table!(
-            "| Hello Worl |"
-            "|--|--|--|---|"
-            "|  |  |  | c |"
-            "|  |  |  | 0 |"
-            "|  |  |  | 1 |"
-            "|  |  |  | 2 |"
-        )
-    );
-    assert_width!(table, 14);
-}
+        .with(MinWidth::new(14)),
+    "| Hello Worl |"
+    "|--|--|--|---|"
+    "|  |  |  | c |"
+    "|  |  |  | 0 |"
+    "|  |  |  | 1 |"
+    "|  |  |  | 2 |"
+);
 
 #[cfg(feature = "ansi")]
-#[test]
-fn total_width_wrapping() {
-    let table = Matrix::new(3, 3)
+test_table!(
+    total_width_wrapping_0,
+    Matrix::new(3, 3)
         .with(Modify::new(Segment::all()).with(Alignment::center()))
         .with(Style::markdown())
         .with(Width::wrap(20))
-        .with(MinWidth::new(20))
-        .to_string();
-
-    assert_eq!(
-        table,
-        static_table!(
-            "|  | co | co | col |"
-            "|  | lu | lu | umn |"
-            "|  | mn | mn |  2  |"
-            "|  |  0 |  1 |     |"
-            "|--|----|----|-----|"
-            "|  | 0- | 0- | 0-2 |"
-            "|  | 0  | 1  |     |"
-            "|  | 1- | 1- | 1-2 |"
-            "|  | 0  | 1  |     |"
-            "|  | 2- | 2- | 2-2 |"
-            "|  | 0  | 1  |     |"
-        )
-    );
-    assert_width!(table, 20);
+        .with(MinWidth::new(20)),
+    "|  | co | co | col |"
+    "|  | lu | lu | umn |"
+    "|  | mn | mn |  2  |"
+    "|  |  0 |  1 |     |"
+    "|--|----|----|-----|"
+    "|  | 0- | 0- | 0-2 |"
+    "|  | 0  | 1  |     |"
+    "|  | 1- | 1- | 1-2 |"
+    "|  | 0  | 1  |     |"
+    "|  | 2- | 2- | 2-2 |"
+    "|  | 0  | 1  |     |"
+);
 
-    let table = Matrix::new(3, 3)
+#[cfg(feature = "ansi")]
+test_table!(
+    total_width_wrapping_1,
+    Matrix::new(3, 3)
         .insert((3, 2).into(), "some loong string")
         .with(Modify::new(Segment::all()).with(Alignment::center()))
         .with(Style::markdown())
         .with(Width::wrap(20).keep_words(true))
-        .with(MinWidth::new(20))
-        .to_string();
-
-    assert_eq!(
-        table,
-        static_table!(
-            "|  |  | column  |  |"
-            "|  |  | 1       |  |"
-            "|--|--|---------|--|"
-            "|  |  |   0-1   |  |"
-            "|  |  |   1-1   |  |"
-            "|  |  | some    |  |"
-            "|  |  | loong   |  |"
-            "|  |  | string  |  |"
-        )
-    );
-    assert_width!(table, 20);
-}
+        .with(MinWidth::new(20)),
+    "|  |  | column  |  |"
+    "|  |  | 1       |  |"
+    "|--|--|---------|--|"
+    "|  |  |   0-1   |  |"
+    "|  |  |   1-1   |  |"
+    "|  |  | some    |  |"
+    "|  |  | loong   |  |"
+    "|  |  | string  |  |"
+);
 
-#[test]
-fn total_width_small_with_panel_using_wrapping() {
-    let table = Matrix::new(3, 3)
+test_table!(
+    total_width_small_with_panel_using_wrapping_0,
+    Matrix::new(3, 3)
         .with(Panel::horizontal(0, "Hello World"))
         .with(Modify::new(Segment::all()).with(Alignment::center()))
         .with(Style::markdown())
         .with(Width::wrap(20))
-        .with(MinWidth::new(20))
-        .to_string();
-
-    assert_eq!(
-        table,
-        static_table!(
-            "|   Hello World    |"
-            "|--|----|----|-----|"
-            "|  | co | co | col |"
-            "|  | lu | lu | umn |"
-            "|  | mn | mn |  2  |"
-            "|  |  0 |  1 |     |"
-            "|  | 0- | 0- | 0-2 |"
-            "|  | 0  | 1  |     |"
-            "|  | 1- | 1- | 1-2 |"
-            "|  | 0  | 1  |     |"
-            "|  | 2- | 2- | 2-2 |"
-            "|  | 0  | 1  |     |"
-        )
-    );
-    assert_width!(table, 20);
+        .with(MinWidth::new(20)),
+    "|   Hello World    |"
+    "|--|----|----|-----|"
+    "|  | co | co | col |"
+    "|  | lu | lu | umn |"
+    "|  | mn | mn |  2  |"
+    "|  |  0 |  1 |     |"
+    "|  | 0- | 0- | 0-2 |"
+    "|  | 0  | 1  |     |"
+    "|  | 1- | 1- | 1-2 |"
+    "|  | 0  | 1  |     |"
+    "|  | 2- | 2- | 2-2 |"
+    "|  | 0  | 1  |     |"
+);
 
-    let table = Matrix::new(3, 3)
+test_table!(
+    total_width_small_with_panel_using_wrapping_1,
+    Matrix::new(3, 3)
         .with(Panel::horizontal(0, "Hello World"))
         .with(Modify::new(Segment::all()).with(Alignment::center()))
         .with(Style::markdown())
         .with(Width::wrap(14))
-        .with(MinWidth::new(14))
-        .to_string();
-
-    assert_eq!(
-        table,
-        static_table!(
-            "| Hello Worl |"
-            "| d          |"
-            "|--|--|--|---|"
-            "|  |  |  | c |"
-            "|  |  |  | o |"
-            "|  |  |  | l |"
-            "|  |  |  | u |"
-            "|  |  |  | m |"
-            "|  |  |  | n |"
-            "|  |  |  |   |"
-            "|  |  |  | 2 |"
-            "|  |  |  | 0 |"
-            "|  |  |  | - |"
-            "|  |  |  | 2 |"
-            "|  |  |  | 1 |"
-            "|  |  |  | - |"
-            "|  |  |  | 2 |"
-            "|  |  |  | 2 |"
-            "|  |  |  | - |"
-            "|  |  |  | 2 |"
-        )
-    );
-    assert_width!(table, 14);
+        .with(MinWidth::new(14)),
+    "| Hello Worl |"
+    "| d          |"
+    "|--|--|--|---|"
+    "|  |  |  | c |"
+    "|  |  |  | o |"
+    "|  |  |  | l |"
+    "|  |  |  | u |"
+    "|  |  |  | m |"
+    "|  |  |  | n |"
+    "|  |  |  |   |"
+    "|  |  |  | 2 |"
+    "|  |  |  | 0 |"
+    "|  |  |  | - |"
+    "|  |  |  | 2 |"
+    "|  |  |  | 1 |"
+    "|  |  |  | - |"
+    "|  |  |  | 2 |"
+    "|  |  |  | 2 |"
+    "|  |  |  | - |"
+    "|  |  |  | 2 |"
+);
 
-    let table = Matrix::new(3, 3)
+test_table!(
+    total_width_small_with_panel_using_wrapping_2,
+    Matrix::new(3, 3)
         .with(Panel::horizontal(0, "Hello World 123"))
         .with(Modify::new(Segment::all()).with(Alignment::center()))
         .with(Style::markdown())
         .with(Width::wrap(14))
-        .with(MinWidth::new(14))
-        .to_string();
-
-    assert_eq!(
-        table,
-        static_table!(
-            "| Hello Worl |"
-            "| d 123      |"
-            "|--|--|--|---|"
-            "|  |  |  | c |"
-            "|  |  |  | o |"
-            "|  |  |  | l |"
-            "|  |  |  | u |"
-            "|  |  |  | m |"
-            "|  |  |  | n |"
-            "|  |  |  |   |"
-            "|  |  |  | 2 |"
-            "|  |  |  | 0 |"
-            "|  |  |  | - |"
-            "|  |  |  | 2 |"
-            "|  |  |  | 1 |"
-            "|  |  |  | - |"
-            "|  |  |  | 2 |"
-            "|  |  |  | 2 |"
-            "|  |  |  | - |"
-            "|  |  |  | 2 |"
-        )
-    );
-    assert_width!(table, 14);
-}
+        .with(MinWidth::new(14)),
+    "| Hello Worl |"
+    "| d 123      |"
+    "|--|--|--|---|"
+    "|  |  |  | c |"
+    "|  |  |  | o |"
+    "|  |  |  | l |"
+    "|  |  |  | u |"
+    "|  |  |  | m |"
+    "|  |  |  | n |"
+    "|  |  |  |   |"
+    "|  |  |  | 2 |"
+    "|  |  |  | 0 |"
+    "|  |  |  | - |"
+    "|  |  |  | 2 |"
+    "|  |  |  | 1 |"
+    "|  |  |  | - |"
+    "|  |  |  | 2 |"
+    "|  |  |  | 2 |"
+    "|  |  |  | - |"
+    "|  |  |  | 2 |"
+);
 
-#[test]
-fn max_width_with_span() {
-    let mut table = Matrix::new(3, 3)
+test_table!(
+    max_width_with_span_0,
+    Matrix::new(3, 3)
         .insert((1, 1).into(), "a long string")
-        .to_table();
-    table
+        .to_table()
         .with(Style::psql())
         .with(Modify::new((1, 1)).with(Span::column(2)))
-        .with(Modify::new((2, 2)).with(Span::column(2)));
-
-    table.with(Width::truncate(40));
-
-    assert_eq!(
-        table.to_string(),
-        static_table!(
-            " N | column 0 | column 1 | column 2 "
-            "---+----------+----------+----------"
-            " 0 |    a long string    |   0-2    "
-            " 1 |   1-0    |         1-1         "
-            " 2 |   2-0    |   2-1    |   2-2    "
-        )
-    );
-    assert_width!(table, 36);
-
-    table.with(Width::truncate(20));
-
-    assert_eq!(
-        table.to_string(),
-        static_table!(
-            "  | col | col | col "
-            "--+-----+-----+-----"
-            "  | a long st | 0-2 "
-            "  | 1-0 |    1-1    "
-            "  | 2-0 | 2-1 | 2-2 "
-        )
-    );
-    assert_width!(table, 20);
-
-    table.with(Width::truncate(10));
-
-    assert_eq!(
-        table.to_string(),
-        static_table!(
-            "  |  |  |  "
-            "--+--+--+--"
-            "  | a l |  "
-            "  |  | 1-1 "
-            "  |  |  |  "
-        )
-    );
-    assert_width!(table, 11);
-}
+        .with(Modify::new((2, 2)).with(Span::column(2)))
+        .with(Width::truncate(40)),
+    " N | column 0 | column 1 | column 2 "
+    "---+----------+----------+----------"
+    " 0 |    a long string    |   0-2    "
+    " 1 |   1-0    |         1-1         "
+    " 2 |   2-0    |   2-1    |   2-2    "
+);
+
+test_table!(
+    max_width_with_span_1,
+    Matrix::new(3, 3)
+        .insert((1, 1).into(), "a long string")
+        .to_table()
+        .with(Style::psql())
+        .with(Modify::new((1, 1)).with(Span::column(2)))
+        .with(Modify::new((2, 2)).with(Span::column(2)))
+        .with(Width::truncate(40))
+        .with(Width::truncate(20)),
+    "  | col | col | col "
+    "--+-----+-----+-----"
+    "  | a long st | 0-2 "
+    "  | 1-0 |    1-1    "
+    "  | 2-0 | 2-1 | 2-2 "
+);
+
+test_table!(
+    max_width_with_span_2,
+    Matrix::new(3, 3)
+        .insert((1, 1).into(), "a long string")
+        .to_table()
+        .with(Style::psql())
+        .with(Modify::new((1, 1)).with(Span::column(2)))
+        .with(Modify::new((2, 2)).with(Span::column(2)))
+        .with(Width::truncate(40))
+        .with(Width::truncate(20))
+        .with(Width::truncate(10)),
+    "  |  |  |  "
+    "--+--+--+--"
+    "  | a l |  "
+    "  |  | 1-1 "
+    "  |  |  |  "
+);
 
-#[test]
-fn min_width_works_with_right_alignment() {
-    let json = r#"
+test_table!(
+    min_width_works_with_right_alignment_0,
     {
-        "some": "random",
-        "json": [
-            { "1": "2" },
-            { "1": "2" },
-            { "1": "2" }
-        ]
-    }
-    "#;
+        let json = r#"
+        {
+            "some": "random",
+            "json": [
+                { "1": "2" },
+                { "1": "2" },
+                { "1": "2" }
+            ]
+        }
+        "#;
 
-    let mut table = Matrix::iter([json]);
-    table
-        .with(Style::markdown())
-        .with(
-            Modify::new(Segment::all())
-                .with(Alignment::right())
-                .with(TrimStrategy::None),
-        )
-        .with(MinWidth::new(50));
-
-    assert_eq!(get_text_width(&table.to_string()), 50);
-    assert_eq!(
-        table.to_string(),
-        static_table!(
-            "|                                           &str |"
-            "|------------------------------------------------|"
-            "|                                                |"
-            "|                          {                     |"
-            "|                              \"some\": \"random\", |"
-            "|                              \"json\": [         |"
-            "|                                  { \"1\": \"2\" }, |"
-            "|                                  { \"1\": \"2\" }, |"
-            "|                                  { \"1\": \"2\" }  |"
-            "|                              ]                 |"
-            "|                          }                     |"
-            "|                                                |"
-        )
-    );
-
-    table
-        .with(Modify::new(Segment::all()).with(TrimStrategy::Horizontal))
-        .with(MinWidth::new(50));
-
-    assert_eq!(
-        table.to_string(),
-        static_table!(
-            r#"|                                           &str |"#
-            r#"|------------------------------------------------|"#
-            r#"|                                                |"#
-            r#"|                              {                 |"#
-            r#"|                              "some": "random", |"#
-            r#"|                              "json": [         |"#
-            r#"|                              { "1": "2" },     |"#
-            r#"|                              { "1": "2" },     |"#
-            r#"|                              { "1": "2" }      |"#
-            r#"|                              ]                 |"#
-            r#"|                              }                 |"#
-            r#"|                                                |"#
-        )
-    );
-    assert_width!(table, 50);
-
-    table
-        .with(Modify::new(Segment::all()).with(TrimStrategy::Both))
-        .with(MinWidth::new(50));
-
-    assert_eq!(
-        table.to_string(),
-        static_table!(
-            r#"|                                           &str |"#
-            r#"|------------------------------------------------|"#
-            r#"|                              {                 |"#
-            r#"|                              "some": "random", |"#
-            r#"|                              "json": [         |"#
-            r#"|                              { "1": "2" },     |"#
-            r#"|                              { "1": "2" },     |"#
-            r#"|                              { "1": "2" }      |"#
-            r#"|                              ]                 |"#
-            r#"|                              }                 |"#
-            r#"|                                                |"#
-            r#"|                                                |"#
-        )
-    );
-    assert_width!(table, 50);
+        Matrix::iter([json])
+            .with(Style::markdown())
+            .with(Alignment::right())
+            .with(TrimStrategy::None)
+            .with(MinWidth::new(50))
+    },
+    "|                                           &str |"
+    "|------------------------------------------------|"
+    "|                                                |"
+    "|                          {                     |"
+    "|                              \"some\": \"random\", |"
+    "|                              \"json\": [         |"
+    "|                                  { \"1\": \"2\" }, |"
+    "|                                  { \"1\": \"2\" }, |"
+    "|                                  { \"1\": \"2\" }  |"
+    "|                              ]                 |"
+    "|                          }                     |"
+    "|                                                |"
+);
 
-    let mut table = Matrix::iter([json]);
-    table
-        .with(Style::markdown())
-        .with(
-            Modify::new(Segment::all())
-                .with(Alignment::center())
-                .with(TrimStrategy::None),
-        )
-        .with(MinWidth::new(50));
-
-    assert_eq!(
-        table.to_string(),
-        static_table!(
-            "|                      &str                      |"
-            "|------------------------------------------------|"
-            "|                                                |"
-            "|               {                                |"
-            "|                   \"some\": \"random\",            |"
-            "|                   \"json\": [                    |"
-            "|                       { \"1\": \"2\" },            |"
-            "|                       { \"1\": \"2\" },            |"
-            "|                       { \"1\": \"2\" }             |"
-            "|                   ]                            |"
-            "|               }                                |"
-            "|                                                |"
-        )
-    );
-    assert_eq!(get_text_width(&table.to_string()), 50);
-
-    table
-        .with(Modify::new(Segment::all()).with(TrimStrategy::Horizontal))
-        .with(MinWidth::new(50));
-
-    assert_eq!(
-        table.to_string(),
-        static_table!(
-            r#"|                      &str                      |"#
-            r#"|------------------------------------------------|"#
-            r#"|                                                |"#
-            r#"|               {                                |"#
-            r#"|               "some": "random",                |"#
-            r#"|               "json": [                        |"#
-            r#"|               { "1": "2" },                    |"#
-            r#"|               { "1": "2" },                    |"#
-            r#"|               { "1": "2" }                     |"#
-            r#"|               ]                                |"#
-            r#"|               }                                |"#
-            r#"|                                                |"#
-        )
-    );
-    assert_width!(table, 50);
-
-    table
-        .with(Modify::new(Segment::all()).with(TrimStrategy::Both))
-        .with(MinWidth::new(50));
-
-    assert_eq!(
-        table.to_string(),
-        static_table!(
-            r#"|                      &str                      |"#
-            r#"|------------------------------------------------|"#
-            r#"|               {                                |"#
-            r#"|               "some": "random",                |"#
-            r#"|               "json": [                        |"#
-            r#"|               { "1": "2" },                    |"#
-            r#"|               { "1": "2" },                    |"#
-            r#"|               { "1": "2" }                     |"#
-            r#"|               ]                                |"#
-            r#"|               }                                |"#
-            r#"|                                                |"#
-            r#"|                                                |"#
-        )
-    );
-    assert_width!(table, 50);
-}
+test_table!(
+    min_width_works_with_right_alignment_1,
+    {
+        let json = r#"
+        {
+            "some": "random",
+            "json": [
+                { "1": "2" },
+                { "1": "2" },
+                { "1": "2" }
+            ]
+        }
+        "#;
+
+        Matrix::iter([json])
+            .with(Style::markdown())
+            .with(Alignment::right())
+            .with(TrimStrategy::None)
+            .with(MinWidth::new(50))
+            .with(TrimStrategy::Horizontal)
+            .with(MinWidth::new(50))
+    },
+    r#"|                          &str |"#
+    r#"|-------------------------------|"#
+    r#"|                               |"#
+    r#"|             {                 |"#
+    r#"|             "some": "random", |"#
+    r#"|             "json": [         |"#
+    r#"|             { "1": "2" },     |"#
+    r#"|             { "1": "2" },     |"#
+    r#"|             { "1": "2" }      |"#
+    r#"|             ]                 |"#
+    r#"|             }                 |"#
+    r#"|                               |"#
+);
+
+test_table!(
+    min_width_works_with_right_alignment_2,
+    {
+        let json = r#"
+        {
+            "some": "random",
+            "json": [
+                { "1": "2" },
+                { "1": "2" },
+                { "1": "2" }
+            ]
+        }
+        "#;
+
+        Matrix::iter([json])
+            .with(Style::markdown())
+            .with(Alignment::right())
+            .with(TrimStrategy::None)
+            .with(MinWidth::new(50))
+            .with(TrimStrategy::Both)
+            .with(MinWidth::new(50))
+    },
+    r#"|                          &str |"#
+    r#"|-------------------------------|"#
+    r#"|             {                 |"#
+    r#"|             "some": "random", |"#
+    r#"|             "json": [         |"#
+    r#"|             { "1": "2" },     |"#
+    r#"|             { "1": "2" },     |"#
+    r#"|             { "1": "2" }      |"#
+    r#"|             ]                 |"#
+    r#"|             }                 |"#
+    r#"|                               |"#
+    r#"|                               |"#
+);
+
+test_table!(
+    min_width_works_with_right_alignment_3,
+    {
+        let json = r#"
+        {
+            "some": "random",
+            "json": [
+                { "1": "2" },
+                { "1": "2" },
+                { "1": "2" }
+            ]
+        }
+        "#;
+
+        Matrix::iter([json])
+            .with(Style::markdown())
+            .with(Alignment::center())
+            .with(TrimStrategy::None)
+            .with(MinWidth::new(50))
+    },
+    r#"|                      &str                      |"#
+    r#"|------------------------------------------------|"#
+    r#"|                                                |"#
+    r#"|                 {                              |"#
+    r#"|                     "some": "random",          |"#
+    r#"|                     "json": [                  |"#
+    r#"|                         { "1": "2" },          |"#
+    r#"|                         { "1": "2" },          |"#
+    r#"|                         { "1": "2" }           |"#
+    r#"|                     ]                          |"#
+    r#"|                 }                              |"#
+    r#"|                                                |"#
+);
+
+test_table!(
+    min_width_works_with_right_alignment_4,
+    {
+        let json = r#"
+        {
+            "some": "random",
+            "json": [
+                { "1": "2" },
+                { "1": "2" },
+                { "1": "2" }
+            ]
+        }
+        "#;
+
+        Matrix::iter([json])
+            .with(Style::markdown())
+            .with(Alignment::center())
+            .with(TrimStrategy::Horizontal)
+            .with(MinWidth::new(50))
+    },
+    r#"|                      &str                      |"#
+    r#"|------------------------------------------------|"#
+    r#"|                                                |"#
+    r#"|               {                                |"#
+    r#"|               "some": "random",                |"#
+    r#"|               "json": [                        |"#
+    r#"|               { "1": "2" },                    |"#
+    r#"|               { "1": "2" },                    |"#
+    r#"|               { "1": "2" }                     |"#
+    r#"|               ]                                |"#
+    r#"|               }                                |"#
+    r#"|                                                |"#
+);
+
+test_table!(
+    min_width_works_with_right_alignment_5,
+    {
+        let json = r#"
+        {
+            "some": "random",
+            "json": [
+                { "1": "2" },
+                { "1": "2" },
+                { "1": "2" }
+            ]
+        }
+        "#;
 
-#[test]
-fn min_width_with_span_1() {
-    let data = [
+        Matrix::iter([json])
+            .with(Style::markdown())
+            .with(Alignment::center())
+            .with(TrimStrategy::Both)
+            .with(MinWidth::new(50))
+    },
+    r#"|                      &str                      |"#
+    r#"|------------------------------------------------|"#
+    r#"|               {                                |"#
+    r#"|               "some": "random",                |"#
+    r#"|               "json": [                        |"#
+    r#"|               { "1": "2" },                    |"#
+    r#"|               { "1": "2" },                    |"#
+    r#"|               { "1": "2" }                     |"#
+    r#"|               ]                                |"#
+    r#"|               }                                |"#
+    r#"|                                                |"#
+    r#"|                                                |"#
+);
+
+test_table!(
+    min_width_with_span_1,
+    Matrix::iter([
         ["0", "1"],
         ["a long string which will affect min width logic", ""],
         ["2", "3"],
-    ];
-
-    let table = Matrix::iter(data)
-        .with(Style::markdown())
-        .with(Modify::new((1, 0)).with(Span::column(2)))
-        .with(MinWidth::new(100))
-        .to_string();
-
-    assert_eq!(get_text_width(&table), 100);
-    assert_eq!(
-        table,
-        static_table!(
-            "|                                   0                                    |            1            |"
-            "|------------------------------------------------------------------------|-------------------------|"
-            "|                                                0                                                 |"
-            "|            a long string which will affect min width logic             |                         |"
-            "|                                   2                                    |            3            |"
-        )
-    );
-    assert_width!(table, 100);
-}
+    ])
+    .with(Style::markdown())
+    .with(Modify::new((1, 0)).with(Span::column(2)))
+    .with(MinWidth::new(100)),
+    "|                                   0                                    |            1            |"
+    "|------------------------------------------------------------------------|-------------------------|"
+    "|                                                0                                                 |"
+    "|            a long string which will affect min width logic             |                         |"
+    "|                                   2                                    |            3            |"
+);
 
-#[test]
-fn min_width_with_span_2() {
-    let data = [
+test_table!(
+    min_width_with_span_2,
+    Matrix::iter([
         ["0", "1"],
         ["a long string which will affect min width logic", ""],
         ["2", "3"],
-    ];
-
-    let table = Matrix::iter(data)
-        .with(Style::markdown())
-        .with(Modify::new((2, 0)).with(Span::column(2)))
-        .with(MinWidth::new(100))
-        .to_string();
-
-    assert_eq!(get_text_width(&table), 100);
-    assert_eq!(
-        table,
-        static_table!(
-            "|                        0                        |                       1                        |"
-            "|-------------------------------------------------|------------------------------------------------|"
-            "|                        0                        |                       1                        |"
-            "|                         a long string which will affect min width logic                          |"
-            "|                        2                        |                       3                        |"
-        )
-    );
-}
+    ])
+    .with(Style::markdown())
+    .with(Modify::new((2, 0)).with(Span::column(2)))
+    .with(MinWidth::new(100)),
+    "|                        0                        |                       1                        |"
+    "|-------------------------------------------------|------------------------------------------------|"
+    "|                        0                        |                       1                        |"
+    "|                         a long string which will affect min width logic                          |"
+    "|                        2                        |                       3                        |"
+);
 
-#[test]
-fn justify_width_constant_test() {
-    let table = Matrix::new(3, 3)
-        .with(Style::markdown())
-        .with(Justify::new(3))
-        .to_string();
-
-    assert_eq!(
-        table,
-        static_table!(
-            "| N   | col | col | col |"
-            "|-----|-----|-----|-----|"
-            "| 0   | 0-0 | 0-1 | 0-2 |"
-            "| 1   | 1-0 | 1-1 | 1-2 |"
-            "| 2   | 2-0 | 2-1 | 2-2 |"
-        )
-    );
-}
+test_table!(
+    justify_width_constant_test,
+    Matrix::new(3, 3)
+        .with(Style::markdown())
+        .with(Justify::new(3)),
+    "| N   | col | col | col |"
+    "|-----|-----|-----|-----|"
+    "| 0   | 0-0 | 0-1 | 0-2 |"
+    "| 1   | 1-0 | 1-1 | 1-2 |"
+    "| 2   | 2-0 | 2-1 | 2-2 |"
+);
 
-#[test]
-fn justify_width_constant_different_sizes_test() {
-    let table = Matrix::new(3, 3)
+test_table!(
+    justify_width_constant_different_sizes_test,
+    Matrix::new(3, 3)
         .insert((1, 1).into(), "Hello World")
         .insert((3, 2).into(), "multi\nline string\n")
         .with(Style::markdown())
-        .with(Justify::new(3))
-        .to_string();
-
-    assert_eq!(
-        table,
-        static_table!(
-            "| N   | col | col | col |"
-            "|-----|-----|-----|-----|"
-            "| 0   | Hel | 0-1 | 0-2 |"
-            "| 1   | 1-0 | 1-1 | 1-2 |"
-            "| 2   | 2-0 | mul | 2-2 |"
-        )
-    );
-}
-
-#[test]
-fn justify_width_constant_0_test() {
-    let table = Matrix::new(3, 3)
-        .with(Style::markdown())
-        .with(Justify::new(0))
-        .to_string();
-
-    assert_eq!(
-        table,
-        static_table!(
-            "|  |  |  |  |"
-            "|--|--|--|--|"
-            "|  |  |  |  |"
-            "|  |  |  |  |"
-            "|  |  |  |  |"
-        )
-    );
-}
+        .with(Justify::new(3)),
+    "| N   | col | col | col |"
+    "|-----|-----|-----|-----|"
+    "| 0   | Hel | 0-1 | 0-2 |"
+    "| 1   | 1-0 | 1-1 | 1-2 |"
+    "| 2   | 2-0 | mul | 2-2 |"
+);
 
-#[test]
-fn justify_width_min_test() {
-    let table = Matrix::new(3, 3)
+test_table!(
+    justify_width_constant_0_test,
+    Matrix::new(3, 3)
         .with(Style::markdown())
-        .with(Justify::min())
-        .to_string();
-
-    println!("{table}");
+        .with(Justify::new(0)),
+    "|  |  |  |  |"
+    "|--|--|--|--|"
+    "|  |  |  |  |"
+    "|  |  |  |  |"
+    "|  |  |  |  |"
+);
 
-    assert_eq!(
-        table,
-        static_table!(
-            "| N | c | c | c |"
-            "|---|---|---|---|"
-            "| 0 | 0 | 0 | 0 |"
-            "| 1 | 1 | 1 | 1 |"
-            "| 2 | 2 | 2 | 2 |"
-        )
-    );
-}
+test_table!(
+    justify_width_min_test,
+    Matrix::new(3, 3)
+        .with(Style::markdown())
+        .with(Justify::min()),
+    "| N | c | c | c |"
+    "|---|---|---|---|"
+    "| 0 | 0 | 0 | 0 |"
+    "| 1 | 1 | 1 | 1 |"
+    "| 2 | 2 | 2 | 2 |"
+);
 
-#[test]
-fn justify_width_max_test() {
-    let table = Matrix::new(3, 3)
-        .with(Style::markdown())
-        .with(Justify::max())
-        .to_string();
-
-    assert_eq!(
-        table,
-        static_table!(
-            "| N        | column 0 | column 1 | column 2 |"
-            "|----------|----------|----------|----------|"
-            "| 0        | 0-0      | 0-1      | 0-2      |"
-            "| 1        | 1-0      | 1-1      | 1-2      |"
-            "| 2        | 2-0      | 2-1      | 2-2      |"
-        )
-    );
-}
+test_table!(
+    justify_width_max_test,
+    Matrix::new(3, 3)
+        .with(Style::markdown())
+        .with(Justify::max()),
+    "| N        | column 0 | column 1 | column 2 |"
+    "|----------|----------|----------|----------|"
+    "| 0        | 0-0      | 0-1      | 0-2      |"
+    "| 1        | 1-0      | 1-1      | 1-2      |"
+    "| 2        | 2-0      | 2-1      | 2-2      |"
+);
 
-#[test]
-fn max_width_when_cell_has_tabs() {
-    let table = Matrix::new(3, 3)
+test_table!(
+    max_width_when_cell_has_tabs,
+    Matrix::new(3, 3)
         .insert((2, 1).into(), "\tHello\tWorld\t")
         .with(TabSize::new(4))
         .with(Style::markdown())
-        .with(Modify::new(Columns::new(..)).with(Width::truncate(1)))
-        .to_string();
-
-    assert_eq!(
-        table,
-        static_table!(
-            "| N | c | c | c |"
-            "|---|---|---|---|"
-            "| 0 | 0 | 0 | 0 |"
-            "| 1 |   | 1 | 1 |"
-            "| 2 | 2 | 2 | 2 |"
-        )
-    );
-}
+        .with(Modify::new(Columns::new(..)).with(Width::truncate(1))),
+    "| N | c | c | c |"
+    "|---|---|---|---|"
+    "| 0 | 0 | 0 | 0 |"
+    "| 1 |   | 1 | 1 |"
+    "| 2 | 2 | 2 | 2 |"
+);
 
-#[test]
-fn max_width_table_when_cell_has_tabs() {
-    let table = Matrix::new(3, 3)
+test_table!(
+    max_width_table_when_cell_has_tabs,
+    Matrix::new(3, 3)
         .insert((2, 1).into(), "\tHello\tWorld\t")
         .with(TabSize::new(4))
         .with(Style::markdown())
-        .with(Width::truncate(15))
-        .to_string();
-
-    assert_eq!(
-        table,
-        static_table!(
-            "|  | co |  |  |"
-            "|--|----|--|--|"
-            "|  | 0- |  |  |"
-            "|  |    |  |  |"
-            "|  | 2- |  |  |"
-        )
-    );
-}
-
-// WE GOT [["", "column 0", "column 1 ", "column 2  "], ["", "0-0     ", "0-1      ", "0-2       "], ["", "Hello World With Big Line; Here w", "1-1", "1-2"], ["", "2-0     ", "Hello World With Big L", "2-2"]]
-// [2, 10, 11, 12]
-// 40 55 40
-
-// BEFORE ADJ [2, 10, 11, 12]
-
-// WE GOT [["", "column 0", "column 1", "column 2"], ["", "0-0", "0-1", "0-2"], ["", "Hello World With Big Line; Here w", "1-1", "1-2"], ["", "2-0", "Hello World With Big L", "2-2"]]
-// [2, 11, 12, 11]
-// 41 55 40
-
-// adj [2, 10, 10, 10]
+        .with(Width::truncate(15)),
+    "|  | co |  |  |"
+    "|--|----|--|--|"
+    "|  | 0- |  |  |"
+    "|  |    |  |  |"
+    "|  | 2- |  |  |"
+);
 
-#[test]
-fn max_width_truncate_with_big_span() {
-    let table = Matrix::new(3, 3)
+test_table!(
+    max_width_truncate_with_big_span_0,
+    Matrix::new(3, 3)
         .insert((2, 1).into(), "Hello World With Big Line; Here we gooooooo")
         .with(Style::markdown())
         .with(Modify::new((2, 1)).with(Span::column(3)))
-        .with(Width::truncate(40))
-        .to_string();
-
-    assert_eq!(get_text_width(&table), 40);
-    assert_eq!(
-        table,
-        static_table!(
-            "|  | column 0  | column 1  | column 2  |"
-            "|--|-----------|-----------|-----------|"
-            "|  |    0-0    |    0-1    |    0-2    |"
-            "|  | Hello World With Big Line; Here w |"
-            "|  |    2-0    |    2-1    |    2-2    |"
-        )
-    );
+        .with(Width::truncate(40)),
+    "|  | column 0  | column 1  | column 2  |"
+    "|--|-----------|-----------|-----------|"
+    "|  |    0-0    |    0-1    |    0-2    |"
+    "|  | Hello World With Big Line; Here w |"
+    "|  |    2-0    |    2-1    |    2-2    |"
+);
 
-    let table = Matrix::new(3, 3)
+test_table!(
+    max_width_truncate_with_big_span_1,
+    Matrix::new(3, 3)
         .insert((2, 1).into(), "Hello World With Big Line; Here we gooooooo")
         .insert((3, 2).into(), "Hello World With Big Line; Here")
         .with(Style::markdown())
         .with(Modify::new((2, 1)).with(Span::column(3)))
-        .with(Modify::new((3, 2)).with(Span::column(2)))
-        .to_string();
-
-    assert_eq!(
-        table,
-        static_table!(
-            "| N | column 0  |    column 1    |    column 2    |"
-            "|---|-----------|----------------|----------------|"
-            "| 0 |    0-0    |      0-1       |      0-2       |"
-            "| 1 | Hello World With Big Line; Here we gooooooo |"
-            "| 2 |    2-0    | Hello World With Big Line; Here |"
-        )
-    );
+        .with(Modify::new((3, 2)).with(Span::column(2))),
+    "| N | column 0  |    column 1    |    column 2    |"
+    "|---|-----------|----------------|----------------|"
+    "| 0 |    0-0    |      0-1       |      0-2       |"
+    "| 1 | Hello World With Big Line; Here we gooooooo |"
+    "| 2 |    2-0    | Hello World With Big Line; Here |"
+);
 
-    let table = Matrix::new(3, 3)
+test_table!(
+    max_width_truncate_with_big_span_2,
+    Matrix::new(3, 3)
         .insert((2, 1).into(), "Hello World With Big Line; Here we gooooooo")
         .insert((3, 2).into(), "Hello World With Big Line; Here")
         .with(Style::markdown())
         .with(Modify::new((2, 1)).with(Span::column(3)))
         .with(Modify::new((3, 2)).with(Span::column(2)))
-        .with(Width::truncate(40))
-        .to_string();
-
-    assert_eq!(
-        table,
-        static_table!(
-            "|  | colum |  column 1   |  column 2   |"
-            "|--|-------|-------------|-------------|"
-            "|  |  0-0  |     0-1     |     0-2     |"
-            "|  | Hello World With Big Line; Here w |"
-            "|  |  2-0  | Hello World With Big Line |"
-        )
-    );
-    assert_eq!(get_text_width(&table), 40);
+        .with(Width::truncate(40)),
+    "|  | colum |  column 1   |  column 2   |"
+    "|--|-------|-------------|-------------|"
+    "|  |  0-0  |     0-1     |     0-2     |"
+    "|  | Hello World With Big Line; Here w |"
+    "|  |  2-0  | Hello World With Big Line |"
+);
 
-    let table = Matrix::new(3, 3)
+test_table!(
+    max_width_truncate_with_big_span_3,
+    Matrix::new(3, 3)
         .insert((2, 1).into(), "Hello World With Big Line; Here we gooooooo")
         .insert((3, 2).into(), "Hello World With Big Line; Here")
         .with(Style::markdown())
         .with(Modify::new((2, 1)).with(Span::column(2)))
         .with(Modify::new((3, 2)).with(Span::column(2)))
-        .with(Width::truncate(40))
-        .to_string();
-
-    assert_eq!(get_text_width(&table), 40);
-    assert_eq!(
-        table,
-        static_table!(
-            "|  |   column 0    |   column 1    | c |"
-            "|--|---------------|---------------|---|"
-            "|  |      0-0      |      0-1      | 0 |"
-            "|  | Hello World With Big Line; He | 1 |"
-            "|  |      2-0      | Hello World With  |"
-        )
-    );
+        .with(Width::truncate(40)),
+    "|  |   column 0    |   column 1    | c |"
+    "|--|---------------|---------------|---|"
+    "|  |      0-0      |      0-1      | 0 |"
+    "|  | Hello World With Big Line; He | 1 |"
+    "|  |      2-0      | Hello World With  |"
+);
 
-    let table = Matrix::new(3, 3)
+test_table!(
+    max_width_truncate_with_big_span_4,
+    Matrix::new(3, 3)
         .insert((2, 1).into(), "Hello World With Big Line; Here w")
         .insert((3, 2).into(), "Hello World With Big L")
         .with(Style::markdown())
         .with(Modify::new((2, 1)).with(Span::column(3)))
-        .with(Modify::new((3, 2)).with(Span::column(2)))
-        .to_string();
-
-    assert_eq!(
-        table,
-        static_table!(
-            "| N | column 0 |  column 1  | column 2  |"
-            "|---|----------|------------|-----------|"
-            "| 0 |   0-0    |    0-1     |    0-2    |"
-            "| 1 | Hello World With Big Line; Here w |"
-            "| 2 |   2-0    | Hello World With Big L |"
-        )
-    );
-}
+        .with(Modify::new((3, 2)).with(Span::column(2))),
+    "| N | column 0 |  column 1  | column 2  |"
+    "|---|----------|------------|-----------|"
+    "| 0 |   0-0    |    0-1     |    0-2    |"
+    "| 1 | Hello World With Big Line; Here w |"
+    "| 2 |   2-0    | Hello World With Big L |"
+);
 
-#[test]
-fn max_width_truncate_priority_max() {
-    let table = Matrix::new(3, 3)
+test_table!(
+    max_width_truncate_priority_max_0,
+    Matrix::new(3, 3)
         .insert((2, 1).into(), "Hello World With Big Line")
         .with(Style::markdown())
-        .with(Width::truncate(35).priority(PriorityMax::right()))
-        .to_string();
-
-    assert_width!(table, 35);
-    assert_eq!(
-        table,
-        static_table!(
-            "| N | column  | column  | column  |"
-            "|---|---------|---------|---------|"
-            "| 0 |   0-0   |   0-1   |   0-2   |"
-            "| 1 | Hello W |   1-1   |   1-2   |"
-            "| 2 |   2-0   |   2-1   |   2-2   |"
-        )
-    );
+        .with(Width::truncate(35).priority(PriorityMax::right())),
+    "| N | column  | column  | column  |"
+    "|---|---------|---------|---------|"
+    "| 0 |   0-0   |   0-1   |   0-2   |"
+    "| 1 | Hello W |   1-1   |   1-2   |"
+    "| 2 |   2-0   |   2-1   |   2-2   |"
+);
 
-    let table = Matrix::new(3, 3)
+test_table!(
+    max_width_truncate_priority_max_1,
+    Matrix::new(3, 3)
         .insert((2, 1).into(), "Hello World With Big Line")
         .with(Style::markdown())
-        .with(Width::truncate(20).priority(PriorityMax::right()))
-        .to_string();
-
-    assert_width!(table, 20);
-    assert_eq!(
-        table,
-        static_table!(
-            "| N | co | co | co |"
-            "|---|----|----|----|"
-            "| 0 | 0- | 0- | 0- |"
-            "| 1 | He | 1- | 1- |"
-            "| 2 | 2- | 2- | 2- |"
-        )
-    );
+        .with(Width::truncate(20).priority(PriorityMax::right())),
+    "| N | co | co | co |"
+    "|---|----|----|----|"
+    "| 0 | 0- | 0- | 0- |"
+    "| 1 | He | 1- | 1- |"
+    "| 2 | 2- | 2- | 2- |"
+);
 
-    let table = Matrix::new(3, 3)
+test_table!(
+    max_width_truncate_priority_max_2,
+    Matrix::new(3, 3)
         .insert((2, 1).into(), "Hello World With Big Line")
         .with(Style::markdown())
-        .with(Width::truncate(0).priority(PriorityMax::right()))
-        .to_string();
-
-    assert_width!(table, 13);
-    assert_eq!(
-        table,
-        static_table!(
-            "|  |  |  |  |"
-            "|--|--|--|--|"
-            "|  |  |  |  |"
-            "|  |  |  |  |"
-            "|  |  |  |  |"
-        )
-    );
-}
+        .with(Width::truncate(0).priority(PriorityMax::right())),
+    "|  |  |  |  |"
+    "|--|--|--|--|"
+    "|  |  |  |  |"
+    "|  |  |  |  |"
+    "|  |  |  |  |"
+);
 
-#[test]
-fn max_width_truncate_priority_max_with_span() {
-    let table = Matrix::new(3, 3)
+test_table!(
+    max_width_truncate_priority_max_with_span,
+    Matrix::new(3, 3)
         .insert((2, 1).into(), "Hello World With Big Line")
         .with(Style::markdown())
         .with(Modify::new((2, 1)).with(Span::column(2)))
-        .with(Width::truncate(15).priority(PriorityMax::right()))
-        .to_string();
-
-    assert_width!(table, 15);
-    assert_eq!(
-        table,
-        static_table!(
-            "| N | c |  |  |"
-            "|---|---|--|--|"
-            "| 0 | 0 |  |  |"
-            "| 1 | Hell |  |"
-            "| 2 | 2 |  |  |"
-        )
-    );
-}
+        .with(Width::truncate(15).priority(PriorityMax::right())),
+    "| N | c |  |  |"
+    "|---|---|--|--|"
+    "| 0 | 0 |  |  |"
+    "| 1 | Hell |  |"
+    "| 2 | 2 |  |  |"
+);
 
-#[test]
-fn max_width_wrap_priority_max() {
-    let table = Matrix::new(3, 3)
+test_table!(
+    max_width_wrap_priority_max_0,
+    Matrix::new(3, 3)
         .insert((2, 1).into(), "Hello World With Big Line")
         .with(Style::markdown())
-        .with(Width::wrap(35).priority(PriorityMax::right()))
-        .to_string();
-
-    assert_width!(table, 35);
-    assert_eq!(
-        table,
-        static_table!(
-            "| N | column  | column  | column  |"
-            "|   | 0       | 1       | 2       |"
-            "|---|---------|---------|---------|"
-            "| 0 |   0-0   |   0-1   |   0-2   |"
-            "| 1 | Hello W |   1-1   |   1-2   |"
-            "|   | orld Wi |         |         |"
-            "|   | th Big  |         |         |"
-            "|   | Line    |         |         |"
-            "| 2 |   2-0   |   2-1   |   2-2   |"
-        )
-    );
+        .with(Width::wrap(35).priority(PriorityMax::right())),
+    "| N | column  | column  | column  |"
+    "|   | 0       | 1       | 2       |"
+    "|---|---------|---------|---------|"
+    "| 0 |   0-0   |   0-1   |   0-2   |"
+    "| 1 | Hello W |   1-1   |   1-2   |"
+    "|   | orld Wi |         |         |"
+    "|   | th Big  |         |         |"
+    "|   | Line    |         |         |"
+    "| 2 |   2-0   |   2-1   |   2-2   |"
+);
 
-    let table = Matrix::new(3, 3)
+test_table!(
+    max_width_wrap_priority_max_1,
+    Matrix::new(3, 3)
         .insert((2, 1).into(), "Hello World With Big Line")
         .with(Style::markdown())
-        .with(Width::wrap(20).priority(PriorityMax::right()))
-        .to_string();
-
-    assert_width!(table, 20);
-    assert_eq!(
-        table,
-        static_table!(
-            "| N | co | co | co |"
-            "|   | lu | lu | lu |"
-            "|   | mn | mn | mn |"
-            "|   |  0 |  1 |  2 |"
-            "|---|----|----|----|"
-            "| 0 | 0- | 0- | 0- |"
-            "|   | 0  | 1  | 2  |"
-            "| 1 | He | 1- | 1- |"
-            "|   | ll | 1  | 2  |"
-            "|   | o  |    |    |"
-            "|   | Wo |    |    |"
-            "|   | rl |    |    |"
-            "|   | d  |    |    |"
-            "|   | Wi |    |    |"
-            "|   | th |    |    |"
-            "|   |  B |    |    |"
-            "|   | ig |    |    |"
-            "|   |  L |    |    |"
-            "|   | in |    |    |"
-            "|   | e  |    |    |"
-            "| 2 | 2- | 2- | 2- |"
-            "|   | 0  | 1  | 2  |"
-        )
-    );
+        .with(Width::wrap(20).priority(PriorityMax::right())),
+    "| N | co | co | co |"
+    "|   | lu | lu | lu |"
+    "|   | mn | mn | mn |"
+    "|   |  0 |  1 |  2 |"
+    "|---|----|----|----|"
+    "| 0 | 0- | 0- | 0- |"
+    "|   | 0  | 1  | 2  |"
+    "| 1 | He | 1- | 1- |"
+    "|   | ll | 1  | 2  |"
+    "|   | o  |    |    |"
+    "|   | Wo |    |    |"
+    "|   | rl |    |    |"
+    "|   | d  |    |    |"
+    "|   | Wi |    |    |"
+    "|   | th |    |    |"
+    "|   |  B |    |    |"
+    "|   | ig |    |    |"
+    "|   |  L |    |    |"
+    "|   | in |    |    |"
+    "|   | e  |    |    |"
+    "| 2 | 2- | 2- | 2- |"
+    "|   | 0  | 1  | 2  |"
+);
 
-    let table = Matrix::new(3, 3)
+test_table!(
+    max_width_wrap_priority_max_2,
+    Matrix::new(3, 3)
         .insert((2, 1).into(), "Hello World With Big Line")
         .with(Style::markdown())
-        .with(Width::wrap(0).priority(PriorityMax::right()))
-        .to_string();
-
-    assert_width!(table, 13);
-    assert_eq!(
-        table,
-        static_table!(
-            "|  |  |  |  |"
-            "|--|--|--|--|"
-            "|  |  |  |  |"
-            "|  |  |  |  |"
-            "|  |  |  |  |"
-        )
-    );
-}
+        .with(Width::wrap(0).priority(PriorityMax::right())),
+    "|  |  |  |  |"
+    "|--|--|--|--|"
+    "|  |  |  |  |"
+    "|  |  |  |  |"
+    "|  |  |  |  |"
+);
 
-#[test]
-fn max_width_wrap_priority_max_with_span() {
-    let table = Matrix::new(3, 3)
+test_table!(
+    max_width_wrap_priority_max_with_span,
+    Matrix::new(3, 3)
         .insert((2, 1).into(), "Hello World With Big Line")
         .with(Style::markdown())
         .with(Modify::new((2, 1)).with(Span::column(2)))
-        .with(Width::wrap(15).priority(PriorityMax::right()))
-        .to_string();
-
-    assert_width!(table, 15);
-    assert_eq!(
-        table,
-        static_table!(
-            "| N | c |  |  |"
-            "|   | o |  |  |"
-            "|   | l |  |  |"
-            "|   | u |  |  |"
-            "|   | m |  |  |"
-            "|   | n |  |  |"
-            "|   |   |  |  |"
-            "|   | 0 |  |  |"
-            "|---|---|--|--|"
-            "| 0 | 0 |  |  |"
-            "|   | - |  |  |"
-            "|   | 0 |  |  |"
-            "| 1 | Hell |  |"
-            "|   | o Wo |  |"
-            "|   | rld  |  |"
-            "|   | With |  |"
-            "|   |  Big |  |"
-            "|   |  Lin |  |"
-            "|   | e    |  |"
-            "| 2 | 2 |  |  |"
-            "|   | - |  |  |"
-            "|   | 0 |  |  |"
-        )
-    );
-}
+        .with(Width::wrap(15).priority(PriorityMax::right())),
+    "| N | c |  |  |"
+    "|   | o |  |  |"
+    "|   | l |  |  |"
+    "|   | u |  |  |"
+    "|   | m |  |  |"
+    "|   | n |  |  |"
+    "|   |   |  |  |"
+    "|   | 0 |  |  |"
+    "|---|---|--|--|"
+    "| 0 | 0 |  |  |"
+    "|   | - |  |  |"
+    "|   | 0 |  |  |"
+    "| 1 | Hell |  |"
+    "|   | o Wo |  |"
+    "|   | rld  |  |"
+    "|   | With |  |"
+    "|   |  Big |  |"
+    "|   |  Lin |  |"
+    "|   | e    |  |"
+    "| 2 | 2 |  |  |"
+    "|   | - |  |  |"
+    "|   | 0 |  |  |"
+);
 
-#[test]
-fn max_width_truncate_priority_min() {
-    let table = Matrix::new(3, 3)
+test_table!(
+    max_width_truncate_priority_min_0,
+    Matrix::new(3, 3)
         .insert((2, 1).into(), "Hello World With Big Line")
         .with(Style::markdown())
-        .with(Width::truncate(35).priority(PriorityMin::right()))
-        .to_string();
-
-    assert_width!(table, 35);
-    assert_eq!(
-        table,
-        static_table!(
-            "|  |        column 0        |  |  |"
-            "|--|------------------------|--|--|"
-            "|  |          0-0           |  |  |"
-            "|  | Hello World With Big L |  |  |"
-            "|  |          2-0           |  |  |"
-        )
-    );
+        .with(Width::truncate(35).priority(PriorityMin::right())),
+    "|  |        column 0        |  |  |"
+    "|--|------------------------|--|--|"
+    "|  |          0-0           |  |  |"
+    "|  | Hello World With Big L |  |  |"
+    "|  |          2-0           |  |  |"
+);
 
-    let table = Matrix::new(3, 3)
+test_table!(
+    max_width_truncate_priority_min_1,
+    Matrix::new(3, 3)
         .insert((2, 1).into(), "Hello World With Big Line")
         .with(Style::markdown())
-        .with(Width::truncate(20).priority(PriorityMin::right()))
-        .to_string();
-
-    assert_width!(table, 20);
-    assert_eq!(
-        table,
-        static_table!(
-            "|  | column  |  |  |"
-            "|--|---------|--|--|"
-            "|  |   0-0   |  |  |"
-            "|  | Hello W |  |  |"
-            "|  |   2-0   |  |  |"
-        )
-    );
+        .with(Width::truncate(20).priority(PriorityMin::right())),
+    "|  | column  |  |  |"
+    "|--|---------|--|--|"
+    "|  |   0-0   |  |  |"
+    "|  | Hello W |  |  |"
+    "|  |   2-0   |  |  |"
+);
 
-    let table = Matrix::new(3, 3)
+test_table!(
+    max_width_truncate_priority_min_2,
+    Matrix::new(3, 3)
         .insert((2, 1).into(), "Hello World With Big Line")
         .with(Style::markdown())
-        .with(Width::truncate(0).priority(PriorityMin::right()))
-        .to_string();
-
-    assert_width!(table, 13);
-    assert_eq!(
-        table,
-        static_table!(
-            "|  |  |  |  |"
-            "|--|--|--|--|"
-            "|  |  |  |  |"
-            "|  |  |  |  |"
-            "|  |  |  |  |"
-        )
-    );
-}
+        .with(Width::truncate(0).priority(PriorityMin::right())),
+    "|  |  |  |  |"
+    "|--|--|--|--|"
+    "|  |  |  |  |"
+    "|  |  |  |  |"
+    "|  |  |  |  |"
+);
 
-#[test]
-fn max_width_truncate_priority_min_with_span() {
-    let table = Matrix::new(3, 3)
+test_table!(
+    max_width_truncate_priority_min_with_span_0,
+    Matrix::new(3, 3)
         .insert((2, 1).into(), "Hello World With Big Line")
         .with(Style::markdown())
         .with(Modify::new((2, 1)).with(Span::column(2)))
-        .with(Width::truncate(15).priority(PriorityMin::right()))
-        .to_string();
-
-    assert_width!(table, 15);
-    assert_eq!(
-        table,
-        static_table!(
-            "|  |  | co |  |"
-            "|--|--|----|--|"
-            "|  |  | 0- |  |"
-            "|  | Hello |  |"
-            "|  |  | 2- |  |"
-        )
-    );
+        .with(Width::truncate(15).priority(PriorityMin::right())),
+    "|  |  | co |  |"
+    "|--|--|----|--|"
+    "|  |  | 0- |  |"
+    "|  | Hello |  |"
+    "|  |  | 2- |  |"
+);
 
-    let table = Matrix::new(3, 3)
+test_table!(
+    max_width_truncate_priority_min_with_span_1,
+    Matrix::new(3, 3)
         .insert((2, 1).into(), "Hello World With Big Line")
         .with(Style::markdown())
         .with(Modify::new((2, 1)).with(Span::column(2)))
-        .with(Width::truncate(17).priority(PriorityMin::right()))
-        .to_string();
-
-    assert_width!(table, 17);
-    assert_eq!(
-        table,
-        static_table!(
-            "|  |  | colu |  |"
-            "|--|--|------|--|"
-            "|  |  | 0-1  |  |"
-            "|  | Hello W |  |"
-            "|  |  | 2-1  |  |"
-        )
-    );
-}
+        .with(Width::truncate(17).priority(PriorityMin::right())),
+    "|  |  | colu |  |"
+    "|--|--|------|--|"
+    "|  |  | 0-1  |  |"
+    "|  | Hello W |  |"
+    "|  |  | 2-1  |  |"
+);
 
-#[test]
-fn max_width_wrap_priority_min() {
-    let table = Matrix::new(3, 3)
+test_table!(
+    max_width_wrap_priority_min_0,
+    Matrix::new(3, 3)
         .insert((2, 1).into(), "Hello World With Big Line")
         .with(Style::markdown())
-        .with(Width::wrap(35).priority(PriorityMin::right()))
-        .to_string();
-
-    assert_width!(table, 35);
-    assert_eq!(
-        table,
-        static_table!(
-            "|  |        column 0        |  |  |"
-            "|--|------------------------|--|--|"
-            "|  |          0-0           |  |  |"
-            "|  | Hello World With Big L |  |  |"
-            "|  | ine                    |  |  |"
-            "|  |          2-0           |  |  |"
-        )
-    );
+        .with(Width::wrap(35).priority(PriorityMin::right())),
+    "|  |        column 0        |  |  |"
+    "|--|------------------------|--|--|"
+    "|  |          0-0           |  |  |"
+    "|  | Hello World With Big L |  |  |"
+    "|  | ine                    |  |  |"
+    "|  |          2-0           |  |  |"
+);
 
-    let table = Matrix::new(3, 3)
+test_table!(
+    max_width_wrap_priority_min_1,
+    Matrix::new(3, 3)
         .insert((2, 1).into(), "Hello World With Big Line")
         .with(Style::markdown())
-        .with(Width::wrap(20).priority(PriorityMin::right()))
-        .to_string();
-
-    assert_width!(table, 20);
-    assert_eq!(
-        table,
-        static_table!(
-            "|  | column  |  |  |"
-            "|  | 0       |  |  |"
-            "|--|---------|--|--|"
-            "|  |   0-0   |  |  |"
-            "|  | Hello W |  |  |"
-            "|  | orld Wi |  |  |"
-            "|  | th Big  |  |  |"
-            "|  | Line    |  |  |"
-            "|  |   2-0   |  |  |"
-        )
-    );
+        .with(Width::wrap(20).priority(PriorityMin::right())),
+    "|  | column  |  |  |"
+    "|  | 0       |  |  |"
+    "|--|---------|--|--|"
+    "|  |   0-0   |  |  |"
+    "|  | Hello W |  |  |"
+    "|  | orld Wi |  |  |"
+    "|  | th Big  |  |  |"
+    "|  | Line    |  |  |"
+    "|  |   2-0   |  |  |"
+);
 
-    let table = Matrix::new(3, 3)
+test_table!(
+    max_width_wrap_priority_min_2,
+    Matrix::new(3, 3)
         .insert((2, 1).into(), "Hello World With Big Line")
         .with(Style::markdown())
-        .with(Width::wrap(0).priority(PriorityMin::right()))
-        .to_string();
-
-    assert_width!(table, 13);
-    assert_eq!(
-        table,
-        static_table!(
-            "|  |  |  |  |"
-            "|--|--|--|--|"
-            "|  |  |  |  |"
-            "|  |  |  |  |"
-            "|  |  |  |  |"
-        )
-    );
-}
+        .with(Width::wrap(0).priority(PriorityMin::right())),
+    "|  |  |  |  |"
+    "|--|--|--|--|"
+    "|  |  |  |  |"
+    "|  |  |  |  |"
+    "|  |  |  |  |"
+);
 
-#[test]
-fn max_width_wrap_priority_min_with_span() {
-    let table = Matrix::new(3, 3)
+test_table!(
+    max_width_wrap_priority_min_with_span,
+    Matrix::new(3, 3)
         .insert((2, 1).into(), "Hello World With Big Line")
         .with(Style::markdown())
         .with(Modify::new((2, 1)).with(Span::column(2)))
-        .with(Width::wrap(15).priority(PriorityMin::right()))
-        .to_string();
-
-    assert_width!(table, 15);
-    assert_eq!(
-        table,
-        static_table!(
-            "|  |  | co |  |"
-            "|  |  | lu |  |"
-            "|  |  | mn |  |"
-            "|  |  |  1 |  |"
-            "|--|--|----|--|"
-            "|  |  | 0- |  |"
-            "|  |  | 1  |  |"
-            "|  | Hello |  |"
-            "|  |  Worl |  |"
-            "|  | d Wit |  |"
-            "|  | h Big |  |"
-            "|  |  Line |  |"
-            "|  |  | 2- |  |"
-            "|  |  | 1  |  |"
-        )
-    );
-}
+        .with(Width::wrap(15).priority(PriorityMin::right())),
+    "|  |  | co |  |"
+    "|  |  | lu |  |"
+    "|  |  | mn |  |"
+    "|  |  |  1 |  |"
+    "|--|--|----|--|"
+    "|  |  | 0- |  |"
+    "|  |  | 1  |  |"
+    "|  | Hello |  |"
+    "|  |  Worl |  |"
+    "|  | d Wit |  |"
+    "|  | h Big |  |"
+    "|  |  Line |  |"
+    "|  |  | 2- |  |"
+    "|  |  | 1  |  |"
+);
 
-#[test]
-fn min_width_priority_max() {
-    let table = Matrix::new(3, 3)
-        .with(Style::markdown())
-        .with(MinWidth::new(60).priority(PriorityMax::right()))
-        .to_string();
-
-    assert_eq!(get_text_width(&table), 60);
-    assert_eq!(
-        table,
-        static_table!(
-            "| N | column 0 | column 1 |            column 2            |"
-            "|---|----------|----------|--------------------------------|"
-            "| 0 |   0-0    |   0-1    |              0-2               |"
-            "| 1 |   1-0    |   1-1    |              1-2               |"
-            "| 2 |   2-0    |   2-1    |              2-2               |"
-        ),
-    );
-}
+test_table!(
+    min_width_priority_max,
+    Matrix::new(3, 3)
+        .with(Style::markdown())
+        .with(MinWidth::new(60).priority(PriorityMax::right())),
+    "| N | column 0 | column 1 |            column 2            |"
+    "|---|----------|----------|--------------------------------|"
+    "| 0 |   0-0    |   0-1    |              0-2               |"
+    "| 1 |   1-0    |   1-1    |              1-2               |"
+    "| 2 |   2-0    |   2-1    |              2-2               |"
+);
 
-#[test]
-fn min_width_priority_min() {
-    let table = Matrix::new(3, 3)
-        .with(Style::markdown())
-        .with(MinWidth::new(60).priority(PriorityMin::right()))
-        .to_string();
-
-    assert_eq!(get_text_width(&table), 60);
-    assert_eq!(
-        table,
-        static_table!(
-            "|      N       |   column 0   |   column 1   |  column 2   |"
-            "|--------------|--------------|--------------|-------------|"
-            "|      0       |     0-0      |     0-1      |     0-2     |"
-            "|      1       |     1-0      |     1-1      |     1-2     |"
-            "|      2       |     2-0      |     2-1      |     2-2     |"
-        ),
-    );
-}
+test_table!(
+    min_width_priority_min,
+    Matrix::new(3, 3)
+        .with(Style::markdown())
+        .with(MinWidth::new(60).priority(PriorityMin::right())),
+    "|      N       |   column 0   |   column 1   |  column 2   |"
+    "|--------------|--------------|--------------|-------------|"
+    "|      0       |     0-0      |     0-1      |     0-2     |"
+    "|      1       |     1-0      |     1-1      |     1-2     |"
+    "|      2       |     2-0      |     2-1      |     2-2     |"
+);
 
-#[test]
-fn max_width_tab_0() {
-    let table =
-        Matrix::iter(["\t\tTigre Ecuador\tOMYA Andina\t3824909999\tCalcium carbonate\tColombia\t"])
+test_table!(
+    max_width_tab_0,
+    Matrix::iter(["\t\tTigre Ecuador\tOMYA Andina\t3824909999\tCalcium carbonate\tColombia\t"])
             .with(TabSize::new(4))
             .with(Style::markdown())
-            .with(Width::wrap(60))
-            .to_string();
-
-    assert_width!(table, 60);
-    assert_eq!(
-        table,
-        static_table!(
-            "|                           &str                           |"
-            "|----------------------------------------------------------|"
-            "|         Tigre Ecuador    OMYA Andina    3824909999    Ca |"
-            "| lcium carbonate    Colombia                              |"
-        )
-    );
-}
+            .with(Width::wrap(60)),
+    "|                           &str                           |"
+    "|----------------------------------------------------------|"
+    "|         Tigre Ecuador    OMYA Andina    3824909999    Ca |"
+    "| lcium carbonate    Colombia                              |"
+);
 
-#[test]
-fn min_width_is_not_used_after_padding() {
-    let table = Matrix::new(3, 3)
+test_table!(
+    min_width_is_not_used_after_padding,
+    Matrix::new(3, 3)
         .with(Style::markdown())
         .with(MinWidth::new(60))
-        .with(Modify::new((0, 0)).with(Padding::new(2, 2, 0, 0)))
-        .to_string();
-
-    assert_eq!(get_text_width(&table), 40);
-    assert_eq!(
-        table,
-        static_table!(
-            "|  N  | column 0 | column 1 | column 2 |"
-            "|-----|----------|----------|----------|"
-            "|  0  |   0-0    |   0-1    |   0-2    |"
-            "|  1  |   1-0    |   1-1    |   1-2    |"
-            "|  2  |   2-0    |   2-1    |   2-2    |"
-        ),
-    );
-}
+        .modify((0, 0), Padding::new(2, 2, 0, 0)),
+    "|  N  | column 0 | column 1 | column 2 |"
+    "|-----|----------|----------|----------|"
+    "|  0  |   0-0    |   0-1    |   0-2    |"
+    "|  1  |   1-0    |   1-1    |   1-2    |"
+    "|  2  |   2-0    |   2-1    |   2-2    |"
+);
 
-#[test]
-fn min_width_is_used_after_margin() {
-    let table = Matrix::new(3, 3)
+test_table!(
+    min_width_is_used_after_margin,
+    Matrix::new(3, 3)
         .with(Style::markdown())
         .with(Margin::new(1, 1, 1, 1))
-        .with(Width::increase(60))
-        .to_string();
-
-    assert_eq!(get_text_width(&table), 60);
-    assert_eq!(
-        table,
-        static_table!(
-            "                                                            "
-            " |   N    |   column 0    |   column 1    |   column 2    | "
-            " |--------|---------------|---------------|---------------| "
-            " |   0    |      0-0      |      0-1      |      0-2      | "
-            " |   1    |      1-0      |      1-1      |      1-2      | "
-            " |   2    |      2-0      |      2-1      |      2-2      | "
-            "                                                            "
-        ),
-    );
-}
+        .with(Width::increase(60)),
+    "                                                            "
+    " |   N    |   column 0    |   column 1    |   column 2    | "
+    " |--------|---------------|---------------|---------------| "
+    " |   0    |      0-0      |      0-1      |      0-2      | "
+    " |   1    |      1-0      |      1-1      |      1-2      | "
+    " |   2    |      2-0      |      2-1      |      2-2      | "
+    "                                                            "
+);
 
-#[test]
-fn wrap_keeping_words_0() {
-    let data = vec![["Hello world"]];
-    let table = tabled::Table::new(data)
-        .with(Width::wrap(8).keep_words(true))
-        .to_string();
-
-    assert_eq!(tabled::grid::util::string::get_text_width(&table), 8);
-
-    assert_eq!(
-        table,
-        static_table!(
-            "+------+"
-            "| 0    |"
-            "+------+"
-            "| Hell |"
-            "| o wo |"
-            "| rld  |"
-            "+------+"
-        )
-    );
-}
+test_table!(
+    wrap_keeping_words_0,
+    Table::new(vec![["Hello world"]])
+        .with(Width::wrap(8).keep_words(true)),
+    "+------+"
+    "| 0    |"
+    "+------+"
+    "| Hell |"
+    "| o wo |"
+    "| rld  |"
+    "+------+"
+);
 
-#[test]
-fn cell_truncate_multiline() {
-    let table = Matrix::new(3, 3)
+test_table!(
+    cell_truncate_multiline,
+    Matrix::new(3, 3)
         .insert((1, 1).into(), "H\nel\nlo World")
         .insert((3, 2).into(), "multi\nline string\n")
         .with(Style::markdown())
-        .with(
-            Modify::new(Columns::new(1..2).not(Rows::single(0)))
-                .with(Width::truncate(1).multiline(true)),
-        )
-        .to_string();
-
-    assert_eq!(
-        table,
-        static_table!(
-            "| N | column 0 |  column 1   | column 2 |"
-            "|---|----------|-------------|----------|"
-            "| 0 |    H     |     0-1     |   0-2    |"
-            "|   |    e     |             |          |"
-            "|   |    l     |             |          |"
-            "| 1 |    1     |     1-1     |   1-2    |"
-            "| 2 |    2     | multi       |   2-2    |"
-            "|   |          | line string |          |"
-            "|   |          |             |          |"
-        )
-    );
-}
+        .modify(
+            Columns::new(1..2).not(Rows::single(0)),
+            Width::truncate(1).multiline(true),
+        ),
+    "| N | column 0 |  column 1   | column 2 |"
+    "|---|----------|-------------|----------|"
+    "| 0 |    H     |     0-1     |   0-2    |"
+    "|   |    e     |             |          |"
+    "|   |    l     |             |          |"
+    "| 1 |    1     |     1-1     |   1-2    |"
+    "| 2 |    2     | multi       |   2-2    |"
+    "|   |          | line string |          |"
+    "|   |          |             |          |"
+);
 
-#[test]
-fn cell_truncate_multiline_with_suffix() {
-    let table = Matrix::new(3, 3)
+test_table!(
+    cell_truncate_multiline_with_suffix,
+    Matrix::new(3, 3)
         .insert((1, 1).into(), "H\nel\nlo World")
         .insert((3, 2).into(), "multi\nline string\n")
         .with(Style::markdown())
         .with(
             Modify::new(Columns::new(1..2).not(Rows::single(0)))
                 .with(Width::truncate(1).multiline(true).suffix(".")),
-        )
-        .to_string();
-
-    assert_eq!(
-        table,
-        static_table!(
-            "| N | column 0 |  column 1   | column 2 |"
-            "|---|----------|-------------|----------|"
-            "| 0 |    .     |     0-1     |   0-2    |"
-            "|   |    .     |             |          |"
-            "|   |    .     |             |          |"
-            "| 1 |    .     |     1-1     |   1-2    |"
-            "| 2 |    .     | multi       |   2-2    |"
-            "|   |          | line string |          |"
-            "|   |          |             |          |"
-        )
-    );
-}
+        ),
+    "| N | column 0 |  column 1   | column 2 |"
+    "|---|----------|-------------|----------|"
+    "| 0 |    .     |     0-1     |   0-2    |"
+    "|   |    .     |             |          |"
+    "|   |    .     |             |          |"
+    "| 1 |    .     |     1-1     |   1-2    |"
+    "| 2 |    .     | multi       |   2-2    |"
+    "|   |          | line string |          |"
+    "|   |          |             |          |"
+);
 
-#[test]
-fn table_truncate_multiline() {
-    let table = Matrix::new(3, 3)
+test_table!(
+    table_truncate_multiline,
+    Matrix::new(3, 3)
         .insert((1, 1).into(), "H\nel\nlo World")
         .insert((3, 2).into(), "multi\nline string\n")
         .with(Style::markdown())
-        .with(Width::truncate(20).multiline(true))
-        .to_string();
-
-    assert_eq!(
-        table,
-        static_table!(
-            "|  | c | colu | co |"
-            "|--|---|------|----|"
-            "|  | H | 0-1  | 0- |"
-            "|  | e |      |    |"
-            "|  | l |      |    |"
-            "|  | 1 | 1-1  | 1- |"
-            "|  | 2 | mult | 2- |"
-            "|  |   | line |    |"
-            "|  |   |      |    |"
-        )
-    );
-}
+        .with(Width::truncate(20).multiline(true)),
+    "|  | c | colu | co |"
+    "|--|---|------|----|"
+    "|  | H | 0-1  | 0- |"
+    "|  | e |      |    |"
+    "|  | l |      |    |"
+    "|  | 1 | 1-1  | 1- |"
+    "|  | 2 | mult | 2- |"
+    "|  |   | line |    |"
+    "|  |   |      |    |"
+);
 
-#[test]
-fn table_truncate_multiline_with_suffix() {
-    let table = Matrix::new(3, 3)
+test_table!(
+    table_truncate_multiline_with_suffix,
+    Matrix::new(3, 3)
         .insert((1, 1).into(), "H\nel\nlo World")
         .insert((3, 2).into(), "multi\nline string\n")
         .with(Style::markdown())
-        .with(Width::truncate(20).suffix(".").multiline(true))
-        .to_string();
-
-    assert_eq!(
-        table,
-        static_table!(
-            "|  | . | col. | c. |"
-            "|--|---|------|----|"
-            "|  | . | 0-1  | 0. |"
-            "|  | . |      |    |"
-            "|  | . |      |    |"
-            "|  | . | 1-1  | 1. |"
-            "|  | . | mul. | 2. |"
-            "|  |   | lin. |    |"
-            "|  |   | .    |    |"
-        )
-    );
-}
+        .with(Width::truncate(20).suffix(".").multiline(true)),
+    "|  | . | col. | c. |"
+    "|--|---|------|----|"
+    "|  | . | 0-1  | 0. |"
+    "|  | . |      |    |"
+    "|  | . |      |    |"
+    "|  | . | 1-1  | 1. |"
+    "|  | . | mul. | 2. |"
+    "|  |   | lin. |    |"
+    "|  |   | .    |    |"
+);
 
 test_table!(
     test_priority_left,
@@ -2546,7 +2067,9 @@ test_table!(
 mod derived {
     use super::*;
 
+    use tabled::grid::util::string::get_text_width;
     use tabled::Tabled;
+    use testing_table::static_table;
 
     #[test]
     fn wrapping_as_total_multiline() {