nandi/frqpublic Fork 0
284b59c6810a1b2abace25c071e9d166cd0dafc9
Commits
Clone
git clone https://git.rickub.com/nandi/frq.git
git clone ssh://git@rickub.com/nandi/frq.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

Four more modules into Nim: members, glyphs, emoji, store 3975b4b · on 284b59c6810a1b2abace25c071e9d166cd0dafc9 · nandi · 11h ago
tmembers.nim · 110 lines · 3.7 KBNim Blame HistoryRaw
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
## Membership, modes, and Tab completion.

import std/[sequtils, tables, unittest]
import frq/members

suite "splitPrefix":
  test "a mode in front of a nick":
    check splitPrefix("@alice") == ("@", "alice")
    check splitPrefix("+bob") == ("+", "bob")
  test "a bare nick":
    check splitPrefix("carol") == ("", "carol")
  test "an empty entry":
    check splitPrefix("") == ("", "")

suite "withNames":
  test "folds a 353 into the pending list":
    var acc = initTable[string, string]()
    acc.withNames("@alice bob +carol")
    check acc["alice"] == "@"
    check acc["bob"] == ""
    check acc["carol"] == "+"

  test "several replies accumulate rather than replace":
    # NAMES arrives over as many lines as it takes.
    var acc = initTable[string, string]()
    acc.withNames("@alice")
    acc.withNames("bob")
    check acc.len == 2

  test "runs of spaces do not become members":
    var acc = initTable[string, string]()
    acc.withNames("alice   bob")
    check acc.len == 2

suite "withMode":
  setup:
    var users = {"alice": "", "bob": "", "carol": ""}.toTable

  test "granting op":
    users.withMode("+o", @["alice"])
    check users["alice"] == "@"

  test "taking it away":
    users.withMode("+o", @["alice"])
    users.withMode("-o", @["alice"])
    check users["alice"] == ""

  test "several at once, in order":
    users.withMode("+ov", @["alice", "bob"])
    check users["alice"] == "@"
    check users["bob"] == "+"

  test "a mode naming nobody still eats its argument":
    # The rule this exists for: `+ko secret alice` sets a key and then ops
    # alice. Reading the next letter's nick out of the wrong place would put
    # the op on whoever `secret` happened to match.
    users.withMode("+ko", @["secret", "alice"])
    check users["alice"] == "@"
    check users["bob"] == ""

  test "a mode for somebody who is not here changes nothing":
    users.withMode("+o", @["stranger"])
    check "stranger" notin users

  test "removing a mode takes no argument on some servers, and we do not eat one":
    users.withMode("+o", @["alice"])
    users.withMode("-l+v", @["bob"])
    check users["bob"] == "+"

suite "memberList":
  test "ops first, then alphabetically":
    let users = {"zoe": "", "alice": "", "bob": "@", "carol": "+"}.toTable
    check memberList(users).mapIt(it.nick) == @["bob", "carol", "alice", "zoe"]

  test "the prefix order is the server's":
    let users = {"v": "+", "o": "@", "q": "~", "plain": ""}.toTable
    check memberList(users).mapIt(it.nick) == @["q", "o", "v", "plain"]

  test "case does not decide the alphabetical order":
    let users = {"Bob": "", "alice": ""}.toTable
    check memberList(users).mapIt(it.nick) == @["alice", "Bob"]

suite "completeNick":
  let nicks = @["alice", "alison", "bob"]

  test "one match is taken whole":
    check completeNick("hi bo", nicks) == ("hi bob ", true)

  test "at the start of a line it is an address, elsewhere a mention":
    # `eve: watch this` reads as talking TO eve; mid-sentence it is just a
    # name, so it gets a plain space.
    check completeNick("bo", nicks)[0] == "bob: "
    check completeNick("hi bo", nicks)[0] == "hi bob "

  test "several matches go as far as they agree":
    check completeNick("al", nicks) == ("ali", true)

  test "no match leaves the draft alone":
    check completeNick("zz", nicks) == ("zz", false)

  test "nothing to complete":
    check completeNick("", nicks)[1] == false
    check completeNick("hi ", nicks)[1] == false

  test "case is ignored, and the nick's own case lands":
    check completeNick("hi BO", nicks) == ("hi bob ", true)

  test "a completed word is not completed again":
    # "ali" already agrees with both; there is nothing more to add.
    check completeNick("ali", nicks)[1] == false