skipped 54 lines 55 55 wantErr: true, 56 56 }, 57 57 { 58 + desc: "fails when MaxTextCells is negative", 59 + opts: []Option{ 60 + MaxTextCells(-1), 61 + }, 62 + canvas: image.Rect(0, 0, 1, 1), 63 + want: func(size image.Point) *faketerm.Terminal { 64 + return faketerm.MustNew(size) 65 + }, 66 + wantErr: true, 67 + }, 68 + { 58 69 desc: "fails when scroll mouse buttons aren't unique", 59 70 opts: []Option{ 60 71 ScrollMouseButtons(mouse.ButtonLeft, mouse.ButtonLeft), skipped 748 lines 809 820 return ft 810 821 }, 811 822 }, 823 + { 824 + desc: "tests maxTextCells length being applied - multiline", 825 + canvas: image.Rect(0, 0, 10, 3), 826 + opts: []Option{ 827 + MaxTextCells(10), 828 + RollContent(), 829 + }, 830 + writes: func(widget *Text) error { 831 + return widget.Write("line0\nline1\nline2\nline3\nline4") 832 + }, 833 + want: func(size image.Point) *faketerm.Terminal { 834 + ft := faketerm.MustNew(size) 835 + c := testcanvas.MustNew(ft.Area()) 836 + // \n still counts as a chacter in the string length 837 + testdraw.MustText(c, "ine3", image.Point{0, 0}) 838 + testdraw.MustText(c, "line4", image.Point{0, 1}) 839 + testcanvas.MustApply(c, ft) 840 + return ft 841 + }, 842 + }, 843 + { 844 + desc: "tests maxTextCells - multiple writes - first one fits", 845 + canvas: image.Rect(0, 0, 10, 3), 846 + opts: []Option{ 847 + MaxTextCells(10), 848 + RollContent(), 849 + }, 850 + writes: func(widget *Text) error { 851 + if err := widget.Write("line0\nline"); err != nil { 852 + return err 853 + } 854 + return widget.Write("1\nline2\nline3\nline4") 855 + }, 856 + want: func(size image.Point) *faketerm.Terminal { 857 + ft := faketerm.MustNew(size) 858 + c := testcanvas.MustNew(ft.Area()) 859 + // \n still counts as a chacter in the string length 860 + testdraw.MustText(c, "ine3", image.Point{0, 0}) 861 + testdraw.MustText(c, "line4", image.Point{0, 1}) 862 + testcanvas.MustApply(c, ft) 863 + return ft 864 + }, 865 + }, 866 + { 867 + desc: "tests maxTextCells - multiple writes - first one does not fit", 868 + canvas: image.Rect(0, 0, 10, 3), 869 + opts: []Option{ 870 + MaxTextCells(10), 871 + RollContent(), 872 + }, 873 + writes: func(widget *Text) error { 874 + if err := widget.Write("line0\nline123"); err != nil { 875 + return err 876 + } 877 + return widget.Write("1\nline2\nline3\nline4") 878 + }, 879 + want: func(size image.Point) *faketerm.Terminal { 880 + ft := faketerm.MustNew(size) 881 + c := testcanvas.MustNew(ft.Area()) 882 + testdraw.MustText(c, "ine3", image.Point{0, 0}) 883 + testdraw.MustText(c, "line4", image.Point{0, 1}) 884 + testcanvas.MustApply(c, ft) 885 + return ft 886 + }, 887 + }, 888 + { 889 + desc: "tests maxTextCells - accounts for pre-existing full-width runes on the content", 890 + canvas: image.Rect(0, 0, 10, 3), 891 + opts: []Option{ 892 + MaxTextCells(3), 893 + RollContent(), 894 + }, 895 + writes: func(widget *Text) error { 896 + if err := widget.Write("界"); err != nil { 897 + return err 898 + } 899 + return widget.Write("ab") 900 + }, 901 + want: func(size image.Point) *faketerm.Terminal { 902 + ft := faketerm.MustNew(size) 903 + c := testcanvas.MustNew(ft.Area()) 904 + testdraw.MustText(c, "ab", image.Point{0, 0}) 905 + testcanvas.MustApply(c, ft) 906 + return ft 907 + }, 908 + }, 909 + { 910 + desc: "tests maxTextCells exact length of 5", 911 + canvas: image.Rect(0, 0, 10, 1), 912 + opts: []Option{ 913 + RollContent(), 914 + MaxTextCells(5), 915 + }, 916 + writes: func(widget *Text) error { 917 + return widget.Write("12345") 918 + }, 919 + want: func(size image.Point) *faketerm.Terminal { 920 + ft := faketerm.MustNew(size) 921 + c := testcanvas.MustNew(ft.Area()) 922 + // Line return (\n) counts as one character 923 + testdraw.MustText( 924 + c, 925 + "12345", 926 + image.Point{0, 0}, 927 + ) 928 + testcanvas.MustApply(c, ft) 929 + return ft 930 + }, 931 + }, 932 + { 933 + desc: "tests maxTextCells partial bufffer replacement", 934 + canvas: image.Rect(0, 0, 10, 1), 935 + opts: []Option{ 936 + RollContent(), 937 + MaxTextCells(10), 938 + }, 939 + writes: func(widget *Text) error { 940 + return widget.Write("hello wor你12345678") 941 + }, 942 + want: func(size image.Point) *faketerm.Terminal { 943 + ft := faketerm.MustNew(size) 944 + c := testcanvas.MustNew(ft.Area()) 945 + testdraw.MustText( 946 + c, 947 + "你12345678", 948 + image.Point{0, 0}, 949 + ) 950 + testcanvas.MustApply(c, ft) 951 + return ft 952 + }, 953 + }, 954 + { 955 + desc: "tests maxTextCells length not being limited", 956 + canvas: image.Rect(0, 0, 72, 1), 957 + opts: []Option{ 958 + RollContent(), 959 + }, 960 + writes: func(widget *Text) error { 961 + return widget.Write("1234567890abcdefghijklmnopqrstuvwxyz") 962 + }, 963 + want: func(size image.Point) *faketerm.Terminal { 964 + ft := faketerm.MustNew(size) 965 + c := testcanvas.MustNew(ft.Area()) 966 + testdraw.MustText( 967 + c, 968 + "1234567890abcdefghijklmnopqrstuvwxyz", 969 + image.Point{0, 0}, 970 + ) 971 + testcanvas.MustApply(c, ft) 972 + return ft 973 + }, 974 + }, 975 + { 976 + desc: "tests maxTextCells length being applied - single line", 977 + canvas: image.Rect(0, 0, 10, 3), 978 + opts: []Option{ 979 + MaxTextCells(5), 980 + RollContent(), 981 + }, 982 + writes: func(widget *Text) error { 983 + return widget.Write("1234567890abcdefghijklmnopqrstuvwxyz") 984 + }, 985 + want: func(size image.Point) *faketerm.Terminal { 986 + ft := faketerm.MustNew(size) 987 + c := testcanvas.MustNew(ft.Area()) 988 + testdraw.MustText(c, "vwxyz", image.Point{0, 0}) 989 + testcanvas.MustApply(c, ft) 990 + return ft 991 + }, 992 + }, 812 993 } 813 994 814 995 for _, tc := range tests { skipped 87 lines 902 1083 } 903 1084 } 904 1085 1086 + func TestTruncateToCells(t *testing.T) { 1087 + tests := []struct { 1088 + desc string 1089 + text string 1090 + maxCells int 1091 + want string 1092 + }{ 1093 + { 1094 + desc: "returns empty on empty text", 1095 + text: "", 1096 + maxCells: 0, 1097 + want: "", 1098 + }, 1099 + { 1100 + desc: "no need to truncate, length matches max", 1101 + text: "a", 1102 + maxCells: 1, 1103 + want: "a", 1104 + }, 1105 + { 1106 + desc: "no need to truncate, shorter than max", 1107 + text: "a", 1108 + maxCells: 2, 1109 + want: "a", 1110 + }, 1111 + { 1112 + desc: "no need to truncate, maxCells set to zero", 1113 + text: "a", 1114 + maxCells: 0, 1115 + want: "a", 1116 + }, 1117 + { 1118 + desc: "truncates single rune to enforce max cells", 1119 + text: "abc", 1120 + maxCells: 2, 1121 + want: "bc", 1122 + }, 1123 + { 1124 + desc: "truncates multiple runes to enforce max cells", 1125 + text: "abcde", 1126 + maxCells: 3, 1127 + want: "cde", 1128 + }, 1129 + { 1130 + desc: "accounts for cells taken by newline characters", 1131 + text: "a\ncde", 1132 + maxCells: 3, 1133 + want: "cde", 1134 + }, 1135 + { 1136 + desc: "truncates full-width rune on its edge", 1137 + text: "世界", 1138 + maxCells: 2, 1139 + want: "界", 1140 + }, 1141 + { 1142 + desc: "truncates full-width rune because only half of it fits", 1143 + text: "世界", 1144 + maxCells: 3, 1145 + want: "界", 1146 + }, 1147 + { 1148 + desc: "full-width runes - truncating not needed", 1149 + text: "世界", 1150 + maxCells: 4, 1151 + want: "世界", 1152 + }, 1153 + } 1154 + 1155 + for _, tc := range tests { 1156 + t.Run(tc.desc, func(t *testing.T) { 1157 + got := truncateToCells(tc.text, tc.maxCells) 1158 + if diff := pretty.Compare(tc.want, got); diff != "" { 1159 + t.Errorf("truncateToCells => unexpected diff (-want, +got):\n%s", diff) 1160 + } 1161 + }) 1162 + } 1163 + } 1164 +