| Four more modules into Nim: members, glyphs, emoji, store 3975b4b nandi 12h ago | 1 | ## Splitting a line into words and pictures. |
| 2 | |
| 3 | import std/[sequtils, strutils, unittest] |
| 4 | import frq/[glyphs, emoji] |
| 5 | |
| 6 | proc kinds(s: string): seq[RunKind] = runs(s).mapIt(it.kind) |
| 7 | proc values(s: string): seq[string] = runs(s).mapIt(it.value) |
| 8 | |
| 9 | suite "the catalogue": |
| 10 | test "is the whole of Unicode's list, filtered to what can be drawn": |
| 11 | check catalog.len == 1884 |
| 12 | check popular.len == 16 |
| 13 | check groups.len == 9 |
| 14 | test "every entry has all three fields": |
| 15 | for e in catalog: |
| 16 | check e.glyph.len > 0 |
| 17 | check e.name.len > 0 |
| 18 | check e.group.len > 0 |
| 19 | |
| 20 | suite "runs": |
| 21 | test "plain text is one run": |
| 22 | check kinds("hello") == @[gkText] |
| 23 | check values("hello") == @["hello"] |
| 24 | |
| 25 | test "a bare emoji is one picture": |
| 26 | check kinds("👍") == @[gkEmoji] |
| 27 | check values("👍") == @["👍"] |
| 28 | |
| 29 | test "text around an emoji": |
| 30 | check kinds("hi 👍 there") == @[gkText, gkEmoji, gkText] |
| 31 | check values("hi 👍 there") == @["hi ", "👍", " there"] |
| 32 | |
| 33 | test "two emoji side by side are two runs": |
| 34 | # A node draws one picture. |
| 35 | check kinds("👍🎉") == @[gkEmoji, gkEmoji] |
| 36 | |
| 37 | test "empty text is no runs": |
| 38 | check runs("").len == 0 |
| 39 | |
| 40 | test "a family is one glyph, not its parts": |
| 41 | # 👨 is the head of 👨👩👧; taking the man would leave his family as |
| 42 | # three more glyphs and two tofu joiners. |
| 43 | let got = runs("👨👩👧") |
| 44 | check got.len == 1 |
| 45 | check got[0].kind == gkEmoji |
| 46 | |
| 47 | test "a toned emoji is one picture, and keeps its tone": |
| 48 | # The catalogue leaves toned variants out; the pack has them, so the tone |
| 49 | # is stripped for the lookup and kept for the drawing. |
| 50 | let got = runs("👍🏽") |
| 51 | check got.len == 1 |
| 52 | check got[0].kind == gkEmoji |
| 53 | check "🏽" in got[0].value |
| 54 | |
| 55 | test "a character the pack has no picture for stays text": |
| 56 | check kinds("←") == @[gkText] # ← is not in the pack |
| 57 | |
| 58 | test "non-ASCII text that is not emoji is left alone": |
| 59 | check values("héllo wörld") == @["héllo wörld"] |
| 60 | |
| 61 | suite "hasEmoji": |
| 62 | test "yes": |
| 63 | check runs("a 👍").hasEmoji |
| 64 | test "no": |
| 65 | check not runs("just words").hasEmoji |
| 66 | |
| 67 | suite "pickerEmoji": |
| 68 | test "nothing selected shows the popular row": |
| 69 | let got = pickerEmoji("", "") |
| 70 | check got.len == popular.len |
| 71 | check got[0].glyph == popular[0] |
| 72 | |
| 73 | test "a group shows that group": |
| 74 | let got = pickerEmoji("", "Flags") |
| 75 | check got.len > 0 |
| 76 | check got.allIt(it.group == "Flags") |
| 77 | |
| 78 | test "search finds by name": |
| 79 | let got = pickerEmoji("grinning", "") |
| 80 | check got.len > 0 |
| 81 | check got.allIt("grinning" in it.name.toLower()) |
| 82 | |
| 83 | test "search finds the cat and the cat face": |
| 84 | check pickerEmoji("cat", "").len > 1 |
| 85 | |
| 86 | test "search finds a pasted glyph": |
| 87 | let got = pickerEmoji("👍", "") |
| 88 | check got.len == 1 |
| 89 | check got[0].glyph == "👍" |
| 90 | |
| 91 | test "search beats a selected group": |
| 92 | # A search is what the reader just typed; the group is where they were. |
| 93 | check pickerEmoji("grinning", "Flags").allIt(it.group != "Flags") |