textElement.test.ts 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. import { BOUND_TEXT_PADDING } from "../constants";
  2. import { API } from "../tests/helpers/api";
  3. import {
  4. computeContainerHeightForBoundText,
  5. getContainerCoords,
  6. getMaxContainerWidth,
  7. getMaxContainerHeight,
  8. measureText,
  9. wrapText,
  10. } from "./textElement";
  11. import { FontString } from "./types";
  12. describe("Test wrapText", () => {
  13. const font = "20px Cascadia, width: Segoe UI Emoji" as FontString;
  14. it("shouldn't add new lines for trailing spaces", () => {
  15. const text = "Hello whats up ";
  16. const maxWidth = 200 - BOUND_TEXT_PADDING * 2;
  17. const res = wrapText(text, font, maxWidth);
  18. expect(res).toBe("Hello whats up ");
  19. });
  20. it("should work with emojis", () => {
  21. const text = "😀";
  22. const maxWidth = 1;
  23. const res = wrapText(text, font, maxWidth);
  24. expect(res).toBe("😀");
  25. });
  26. it("should show the text correctly when min width reached", () => {
  27. const text = "Hello😀";
  28. const maxWidth = 10;
  29. const res = wrapText(text, font, maxWidth);
  30. expect(res).toBe("H\ne\nl\nl\no\n😀");
  31. });
  32. describe("When text doesn't contain new lines", () => {
  33. const text = "Hello whats up";
  34. [
  35. {
  36. desc: "break all words when width of each word is less than container width",
  37. width: 90,
  38. res: `Hello
  39. whats
  40. up`,
  41. },
  42. {
  43. desc: "break all characters when width of each character is less than container width",
  44. width: 25,
  45. res: `H
  46. e
  47. l
  48. l
  49. o
  50. w
  51. h
  52. a
  53. t
  54. s
  55. u
  56. p`,
  57. },
  58. {
  59. desc: "break words as per the width",
  60. width: 150,
  61. res: `Hello whats
  62. up`,
  63. },
  64. {
  65. desc: "fit the container",
  66. width: 250,
  67. res: "Hello whats up",
  68. },
  69. ].forEach((data) => {
  70. it(`should ${data.desc}`, () => {
  71. const res = wrapText(text, font, data.width - BOUND_TEXT_PADDING * 2);
  72. expect(res).toEqual(data.res);
  73. });
  74. });
  75. });
  76. describe("When text contain new lines", () => {
  77. const text = `Hello
  78. whats up`;
  79. [
  80. {
  81. desc: "break all words when width of each word is less than container width",
  82. width: 90,
  83. res: `Hello
  84. whats
  85. up`,
  86. },
  87. {
  88. desc: "break all characters when width of each character is less than container width",
  89. width: 25,
  90. res: `H
  91. e
  92. l
  93. l
  94. o
  95. w
  96. h
  97. a
  98. t
  99. s
  100. u
  101. p`,
  102. },
  103. {
  104. desc: "break words as per the width",
  105. width: 150,
  106. res: `Hello
  107. whats up`,
  108. },
  109. {
  110. desc: "fit the container",
  111. width: 250,
  112. res: `Hello
  113. whats up`,
  114. },
  115. ].forEach((data) => {
  116. it(`should respect new lines and ${data.desc}`, () => {
  117. const res = wrapText(text, font, data.width - BOUND_TEXT_PADDING * 2);
  118. expect(res).toEqual(data.res);
  119. });
  120. });
  121. });
  122. describe("When text is long", () => {
  123. const text = `hellolongtextthisiswhatsupwithyouIamtypingggggandtypinggg break it now`;
  124. [
  125. {
  126. desc: "fit characters of long string as per container width",
  127. width: 170,
  128. res: `hellolongtextth
  129. isiswhatsupwith
  130. youIamtypingggg
  131. gandtypinggg
  132. break it now`,
  133. },
  134. {
  135. desc: "fit characters of long string as per container width and break words as per the width",
  136. width: 130,
  137. res: `hellolongte
  138. xtthisiswha
  139. tsupwithyou
  140. Iamtypinggg
  141. ggandtyping
  142. gg break it
  143. now`,
  144. },
  145. {
  146. desc: "fit the long text when container width is greater than text length and move the rest to next line",
  147. width: 600,
  148. res: `hellolongtextthisiswhatsupwithyouIamtypingggggandtypinggg
  149. break it now`,
  150. },
  151. ].forEach((data) => {
  152. it(`should ${data.desc}`, () => {
  153. const res = wrapText(text, font, data.width - BOUND_TEXT_PADDING * 2);
  154. expect(res).toEqual(data.res);
  155. });
  156. });
  157. });
  158. });
  159. describe("Test measureText", () => {
  160. const font = "20px Cascadia, width: Segoe UI Emoji" as FontString;
  161. const text = "Hello World";
  162. it("should add correct attributes when maxWidth is passed", () => {
  163. const maxWidth = 200 - BOUND_TEXT_PADDING * 2;
  164. const res = measureText(text, font, maxWidth);
  165. expect(res.container).toMatchInlineSnapshot(`
  166. <div
  167. style="position: absolute; white-space: pre-wrap; font: Emoji 20px 20px; min-height: 1em; max-width: 191px; overflow: hidden; word-break: break-word; line-height: 0px;"
  168. >
  169. <span
  170. style="display: inline-block; overflow: hidden; width: 1px; height: 1px;"
  171. />
  172. </div>
  173. `);
  174. });
  175. it("should add correct attributes when maxWidth is not passed", () => {
  176. const res = measureText(text, font);
  177. expect(res.container).toMatchInlineSnapshot(`
  178. <div
  179. style="position: absolute; white-space: pre; font: Emoji 20px 20px; min-height: 1em;"
  180. >
  181. <span
  182. style="display: inline-block; overflow: hidden; width: 1px; height: 1px;"
  183. />
  184. </div>
  185. `);
  186. });
  187. describe("Test getContainerCoords", () => {
  188. const params = { width: 200, height: 100, x: 10, y: 20 };
  189. it("should compute coords correctly when ellipse", () => {
  190. const element = API.createElement({
  191. type: "ellipse",
  192. ...params,
  193. });
  194. expect(getContainerCoords(element)).toEqual({
  195. x: 44.2893218813452455,
  196. y: 39.64466094067262,
  197. });
  198. });
  199. it("should compute coords correctly when rectangle", () => {
  200. const element = API.createElement({
  201. type: "rectangle",
  202. ...params,
  203. });
  204. expect(getContainerCoords(element)).toEqual({
  205. x: 15,
  206. y: 25,
  207. });
  208. });
  209. it("should compute coords correctly when diamond", () => {
  210. const element = API.createElement({
  211. type: "diamond",
  212. ...params,
  213. });
  214. expect(getContainerCoords(element)).toEqual({
  215. x: 65,
  216. y: 50,
  217. });
  218. });
  219. });
  220. describe("Test computeContainerHeightForBoundText", () => {
  221. const params = {
  222. width: 178,
  223. height: 194,
  224. };
  225. it("should compute container height correctly for rectangle", () => {
  226. const element = API.createElement({
  227. type: "rectangle",
  228. ...params,
  229. });
  230. expect(computeContainerHeightForBoundText(element, 150)).toEqual(160);
  231. });
  232. it("should compute container height correctly for ellipse", () => {
  233. const element = API.createElement({
  234. type: "ellipse",
  235. ...params,
  236. });
  237. expect(computeContainerHeightForBoundText(element, 150)).toEqual(212);
  238. });
  239. it("should compute container height correctly for diamond", () => {
  240. const element = API.createElement({
  241. type: "diamond",
  242. ...params,
  243. });
  244. expect(computeContainerHeightForBoundText(element, 150)).toEqual(300);
  245. });
  246. });
  247. describe("Test getMaxContainerWidth", () => {
  248. const params = {
  249. width: 178,
  250. height: 194,
  251. };
  252. it("should return max width when container is rectangle", () => {
  253. const container = API.createElement({ type: "rectangle", ...params });
  254. expect(getMaxContainerWidth(container)).toBe(168);
  255. });
  256. it("should return max width when container is ellipse", () => {
  257. const container = API.createElement({ type: "ellipse", ...params });
  258. expect(getMaxContainerWidth(container)).toBe(116);
  259. });
  260. it("should return max width when container is diamond", () => {
  261. const container = API.createElement({ type: "diamond", ...params });
  262. expect(getMaxContainerWidth(container)).toBe(79);
  263. });
  264. });
  265. describe("Test getMaxContainerHeight", () => {
  266. const params = {
  267. width: 178,
  268. height: 194,
  269. };
  270. it("should return max height when container is rectangle", () => {
  271. const container = API.createElement({ type: "rectangle", ...params });
  272. expect(getMaxContainerHeight(container)).toBe(184);
  273. });
  274. it("should return max height when container is ellipse", () => {
  275. const container = API.createElement({ type: "ellipse", ...params });
  276. expect(getMaxContainerHeight(container)).toBe(127);
  277. });
  278. it("should return max height when container is diamond", () => {
  279. const container = API.createElement({ type: "diamond", ...params });
  280. expect(getMaxContainerHeight(container)).toBe(87);
  281. });
  282. });
  283. });