vcard4: Complete implementation.
- Parsers and serializers are now present for all property types. - Tests exist to cover parsing for most value types. Many property types share the same parsing logic based on their value type. We have created unit tests to cover each value type, not neccesarily all properties individually.
This commit is contained in:
1
tests/allen.foster.jpg.uri
Normal file
1
tests/allen.foster.jpg.uri
Normal file
File diff suppressed because one or more lines are too long
212
tests/allen.foster.v4.vcf
Normal file
212
tests/allen.foster.v4.vcf
Normal file
@ -0,0 +1,212 @@
|
||||
BEGIN:VCARD
|
||||
VERSION:4.0
|
||||
PRODID:+//IDN bitfire.at//DAVx5/4.1.1-gplay ez-vcard/0.11.3
|
||||
UID:b7047a2e-c46b-47cb-af0b-94d354b7746a
|
||||
FN:Dr. Allen Foster
|
||||
N;SORT-AS=Foster,Allen,,,:Foster;Jack;John,Allen;Dr.;II
|
||||
NICKNAME:Jack Jr.
|
||||
NICKNAME;TYPE=work;PREF=1:Doc A
|
||||
TEL;TYPE=cell:+1 555-123-4567
|
||||
TEL;TYPE=cell:(555) 123-4567
|
||||
TEL;TYPE=work,voice;VALUE=uri:tel:+1-555-874-1234
|
||||
EMAIL;TYPE=work;PREF=2:jack.foster@company.test
|
||||
EMAIL;TYPE=home;PREF=1:allen@fosters.test
|
||||
SOURCE;VALUE=uri:https://carddav.fosters.test/allen.vcf
|
||||
KIND:individual
|
||||
REV:20220226T060828Z
|
||||
BDAY;ALTID=1;VALUE=date-and-or-time:--1224
|
||||
BDAY;ALTID=1;VALUE=text:Christmas Eve
|
||||
ANNIVERSARY:20140612T163000-0500
|
||||
GENDER:M;male
|
||||
MADE-UP-PROP:Sample value for my made-up prop.
|
||||
NOTE;LANG=en-us:This is an example\, for clarity; in text value cases the parser
|
||||
will recognize escape values for '\,'\, '\\'\, and newlines. For example:\n 12
|
||||
3 Flagstaff Road\N Placeville\, MA
|
||||
X-CUSTOM-EXAMPLE;PARAM="How one says, ^'Hello.^'";LABEL=^^top^nsecond line:This
|
||||
is an example, for clarity; in straight value cases, the parser does not reco
|
||||
gnize any escape values, as the meaning of the content is implementation-speci
|
||||
fic.
|
||||
PHOTO;ALTID=1;VALUE=uri:https://tile.loc.gov/storage-services/service/pnp/
|
||||
bellcm/02200/02297r.jpg
|
||||
URL:https://allen.fosters.test/
|
||||
PHOTO;ALTID=1:data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEFeAV4AAD/4QCuRXhpZgAASU
|
||||
kqAAgAAAAHABIBAwABAAAAAQAAABoBBQABAAAAYgAAABsBBQABAAAAagAAACgBAwABAAAAAgAAADEB
|
||||
AgANAAAAcgAAADIBAgAUAAAAgAAAAGmHBAABAAAAlAAAAAAAAAB4BQAAAQAAAHgFAAABAAAAR0lNUC
|
||||
AyLjEwLjM0AAAyMDIzOjA0OjI1IDE2OjQzOjUyAAEAAaADAAEAAAABAAAAAAAAAP/hDM1odHRwOi8v
|
||||
bnMuYWRvYmUuY29tL3hhcC8xLjAvADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaU
|
||||
h6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1w
|
||||
dGs9IlhNUCBDb3JlIDQuNC4wLUV4aXYyIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3Ln
|
||||
czLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJv
|
||||
dXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOn
|
||||
N0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiIHht
|
||||
bG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6R0lNUD0iaHR0cD
|
||||
ovL3d3dy5naW1wLm9yZy94bXAvIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEu
|
||||
MC8iIHhtcE1NOkRvY3VtZW50SUQ9ImdpbXA6ZG9jaWQ6Z2ltcDpmYzVkZDFkMC05ZmNiLTRhZjAtOG
|
||||
UzNS1jMTMyMDU4NTUwMmEiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6YmEyOThkOGYtMDY3NC00
|
||||
ZDgzLWJhZGMtNWVkY2Y2OTg2NTBjIiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6Nz
|
||||
JjYWViYjMtMjkzMy00ZGJmLTg0M2EtYzYwYjBkZWYzMzdlIiBkYzpGb3JtYXQ9ImltYWdlL2pwZWci
|
||||
IEdJTVA6QVBJPSIyLjAiIEdJTVA6UGxhdGZvcm09IldpbmRvd3MiIEdJTVA6VGltZVN0YW1wPSIxNj
|
||||
gyNDU5MDQ2MjA4NjE3IiBHSU1QOlZlcnNpb249IjIuMTAuMzQiIHhtcDpDcmVhdG9yVG9vbD0iR0lN
|
||||
UCAyLjEwIiB4bXA6TWV0YWRhdGFEYXRlPSIyMDIzOjA0OjI1VDE2OjQzOjUyLTA1OjAwIiB4bXA6TW
|
||||
9kaWZ5RGF0ZT0iMjAyMzowNDoyNVQxNjo0Mzo1Mi0wNTowMCI+IDx4bXBNTTpIaXN0b3J5PiA8cmRm
|
||||
OlNlcT4gPHJkZjpsaSBzdEV2dDphY3Rpb249InNhdmVkIiBzdEV2dDpjaGFuZ2VkPSIvIiBzdEV2dD
|
||||
ppbnN0YW5jZUlEPSJ4bXAuaWlkOjU2YzcxYmUyLWExNmMtNDE2OC1iNDA5LWI3YjRlMTgwZTFmMyIg
|
||||
c3RFdnQ6c29mdHdhcmVBZ2VudD0iR2ltcCAyLjEwIChXaW5kb3dzKSIgc3RFdnQ6d2hlbj0iMjAyMy
|
||||
0wNC0yNVQxNjo0NDowNiIvPiA8L3JkZjpTZXE+IDwveG1wTU06SGlzdG9yeT4gPC9yZGY6RGVzY3Jp
|
||||
cHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+ICAgICAgICAgICAgICAgICAgICAgICAgICAgIC
|
||||
AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC
|
||||
AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC
|
||||
AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC
|
||||
AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC
|
||||
AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC
|
||||
AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC
|
||||
AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC
|
||||
AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC
|
||||
AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC
|
||||
AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC
|
||||
AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC
|
||||
AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC
|
||||
AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC
|
||||
AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC
|
||||
AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC
|
||||
AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC
|
||||
AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
|
||||
ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC
|
||||
AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPD94cGFja2V0IGVuZD0idyI/Pv/iAjBJQ0Nf
|
||||
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
|
||||
GAaDKL5DfxBTTUUbUr1Zb/APP/AP/Z
|
||||
END:VCARD
|
@ -1,4 +1,5 @@
|
||||
import options, unittest, zero_functional
|
||||
import std/[options, strutils, tables, unittest]
|
||||
import zero_functional
|
||||
|
||||
import ./vcard
|
||||
import ./vcard/vcard4
|
||||
@ -7,3 +8,243 @@ suite "vcard/vcard4":
|
||||
|
||||
test "vcard4/private tests":
|
||||
runVcard4PrivateTests()
|
||||
|
||||
let v4ExampleStr = readFile("tests/allen.foster.v4.vcf")
|
||||
|
||||
let testVCardTemplate =
|
||||
"BEGIN:VCARD\r\n" &
|
||||
"VERSION:4.0\r\n" &
|
||||
"$#" &
|
||||
"END:VCARD\r\n"
|
||||
|
||||
test "parseVCard4":
|
||||
check parseVCards(v4ExampleStr).len == 1
|
||||
|
||||
test "parseVCard4File":
|
||||
check parseVCardsFromFile("tests/allen.foster.v4.vcf").len == 1
|
||||
|
||||
# TODO: remove cast after finishing VCard4 implementation
|
||||
let v4Ex = cast[VCard4](parseVCards(v4ExampleStr)[0])
|
||||
|
||||
test "RFC 6350 author's VCard":
|
||||
let vcardStr =
|
||||
"BEGIN:VCARD\r\n" &
|
||||
"VERSION:4.0\r\n" &
|
||||
"FN:Simon Perreault\r\n" &
|
||||
"N:Perreault;Simon;;;ing. jr,M.Sc.\r\n" &
|
||||
"BDAY:--0203\r\n" &
|
||||
"ANNIVERSARY:20090808T1430-0500\r\n" &
|
||||
"GENDER:M\r\n" &
|
||||
"LANG;PREF=1:fr\r\n" &
|
||||
"LANG;PREF=2:en\r\n" &
|
||||
"ORG;TYPE=work:Viagenie\r\n" &
|
||||
"ADR;TYPE=work:;Suite D2-630;2875 Laurier;\r\n" &
|
||||
" Quebec;QC;G1V 2M2;Canada\r\n" &
|
||||
"TEL;VALUE=uri;TYPE=\"work,voice\";PREF=1:tel:+1-418-656-9254;ext=102\r\n" &
|
||||
"TEL;VALUE=uri;TYPE=\"work,cell,voice,video,text\":tel:+1-418-262-6501\r\n" &
|
||||
"EMAIL;TYPE=work:simon.perreault@viagenie.ca\r\n" &
|
||||
"GEO;TYPE=work:geo:46.772673,-71.282945\r\n" &
|
||||
"KEY;TYPE=work;VALUE=uri:\r\n" &
|
||||
" http://www.viagenie.ca/simon.perreault/simon.asc\r\n" &
|
||||
"TZ:-0500\r\n" &
|
||||
"URL;TYPE=home:http://nomis80.org\r\n" &
|
||||
"END:VCARD\r\n"
|
||||
|
||||
let vcards = parseVCards(vcardStr)
|
||||
check vcards.len == 1
|
||||
let sp = cast[VCard4](vcards[0])
|
||||
check:
|
||||
sp.fn.len == 1
|
||||
sp.fn[0].value == "Simon Perreault"
|
||||
sp.gender.isSome
|
||||
sp.gender.get.sex == some(VC4_Sex.Male)
|
||||
sp.gender.get.genderIdentity.isNone
|
||||
sp.lang.len == 2
|
||||
sp.lang --> map(it.value) == @["fr", "en"]
|
||||
|
||||
test "custom properties are serialized":
|
||||
let email = newVC4_Email(
|
||||
value ="john.smith@testco.test",
|
||||
types = @["work", "internet"],
|
||||
params = @[("PREF", @["1"]), ("X-ATTACHMENT-LIMIT", @["25MB"])])
|
||||
|
||||
check serialize(email) ==
|
||||
"EMAIL;X-ATTACHMENT-LIMIT=25MB;TYPE=work,internet;PREF=1:john.smith@testco.test"
|
||||
|
||||
test "can parse properties with escaped characters":
|
||||
check v4Ex.note.len == 1
|
||||
let note = v4Ex.note[0]
|
||||
|
||||
check note.value ==
|
||||
"This is an example, for clarity; in text value cases the parser " &
|
||||
"will recognize escape values for ',', '\\', and newlines. For " &
|
||||
"example:" &
|
||||
"\n\t123 Flagstaff Road" &
|
||||
"\n\tPlaceville, MA"
|
||||
|
||||
test "can parse parameters with escaped characters":
|
||||
let prop = v4Ex.customProp("X-CUSTOM-EXAMPLE")[0]
|
||||
check prop.value ==
|
||||
"This is an example, for clarity; in straight value cases, the parser " &
|
||||
"does not recognize any escape values, as the meaning of the content " &
|
||||
"is implementation-specific."
|
||||
let param1 = prop.params --> filter(it.name == "PARAM")
|
||||
let label = prop.params --> filter(it.name == "LABEL")
|
||||
check:
|
||||
param1.len == 1
|
||||
param1[0].values == @["How one says, \"Hello.\""]
|
||||
label.len == 1
|
||||
label[0].values == @["^top\nsecond line"]
|
||||
|
||||
test "Data URIs are parsed correctly":
|
||||
let expectedB64 = readFile("tests/allen.foster.jpg.uri")
|
||||
|
||||
check:
|
||||
v4Ex.photo.len == 2
|
||||
v4Ex.photo[0].altId == some("1")
|
||||
v4Ex.photo[0].value ==
|
||||
"https://tile.loc.gov/storage-services/service/pnp/bellcm/02200/02297r.jpg"
|
||||
v4Ex.photo[0].valueType == some("uri")
|
||||
v4Ex.photo[1].altId == some("1")
|
||||
v4Ex.photo[1].value == expectedB64
|
||||
v4Ex.photo[1].valueType.isNone
|
||||
|
||||
test "URI-type properties are parsed correctly":
|
||||
# Covers SOURCE, PHOTO, IMPP, GEO, LOGO, MEMBER, SOUND, URL, FBURL,
|
||||
# CALADRURI, and CALURI
|
||||
check:
|
||||
v4Ex.source.len == 1
|
||||
v4Ex.source[0].value == "https://carddav.fosters.test/allen.vcf"
|
||||
v4Ex.source[0].valueType == some("uri")
|
||||
v4Ex.url.len == 1
|
||||
v4Ex.url[0].value == "https://allen.fosters.test/"
|
||||
|
||||
test "URI-type properties are serialized correctly":
|
||||
# Covers SOURCE, PHOTO, IMPP, GEO, LOGO, MEMBER, SOUND, URL, FBURL,
|
||||
# CALADRURI, and CALURI
|
||||
let src = newVC4_Source(value="https://carddav.example.test/john-smith.vcf")
|
||||
check serialize(src) == "SOURCE:https://carddav.example.test/john-smith.vcf"
|
||||
|
||||
test "Single-text properties are parsed correctly":
|
||||
# Covers KIND, XML, FN, NICKNAME, EMAIL, LANG, TZ, TITLE, ROLE, ORG, NOTE,
|
||||
# PRODID, and VERSION
|
||||
check:
|
||||
v4Ex.kind.isSome
|
||||
v4Ex.kind.get.value == "individual"
|
||||
v4Ex.nickname.len == 2
|
||||
v4Ex.nickname[0].value == @["Jack Jr."]
|
||||
v4Ex.nickname[1].value == @["Doc A"]
|
||||
v4Ex.fn.len == 1
|
||||
v4Ex.fn[0].value == "Dr. Allen Foster"
|
||||
v4Ex.email.len == 2
|
||||
v4Ex.email[0].value == "jack.foster@company.test"
|
||||
v4Ex.email[0].types == @["work"]
|
||||
|
||||
test "URI or Text properties are parsed correctly":
|
||||
# Covers TEL, RELATED, UID, KEY
|
||||
check:
|
||||
v4Ex.tel.len == 3
|
||||
v4ex.tel[0].types == @[$VC4_TelType.ttCell]
|
||||
v4Ex.tel[0].value == "+1 555-123-4567"
|
||||
v4Ex.tel[2].types == @[$VC4_TelType.ttWork,$VC4_TelType.ttVoice]
|
||||
v4Ex.tel[2].valueType == some($vtUri)
|
||||
v4Ex.tel[2].value == "tel:+1-555-874-1234"
|
||||
|
||||
test "N is parsed correctly":
|
||||
check:
|
||||
v4Ex.n.isSome
|
||||
v4Ex.n.get.given == @["Jack"]
|
||||
v4Ex.n.get.family == @["Foster"]
|
||||
v4Ex.n.get.additional == @["John", "Allen"]
|
||||
v4Ex.n.get.prefixes == @["Dr."]
|
||||
v4Ex.n.get.suffixes == @["II"]
|
||||
|
||||
test "BDAY is parsed correctly":
|
||||
check:
|
||||
v4Ex.bday.isSome
|
||||
v4Ex.bday.get.value == "--1224"
|
||||
v4Ex.bday.get.year.isNone
|
||||
v4Ex.bday.get.month == some(12)
|
||||
v4Ex.bday.get.day == some(24)
|
||||
|
||||
test "ANNIVERSARY is parsed correctly":
|
||||
check:
|
||||
v4Ex.anniversary.isSome
|
||||
v4Ex.anniversary.get.value == "20140612T163000-0500"
|
||||
v4Ex.anniversary.get.year == some(2014)
|
||||
v4Ex.anniversary.get.hour == some(16)
|
||||
v4Ex.anniversary.get.minute == some(30)
|
||||
v4Ex.anniversary.get.timezone == some("-0500")
|
||||
|
||||
test "GENDER is parsed correctly":
|
||||
check:
|
||||
v4Ex.gender.isSome
|
||||
v4Ex.gender.get.sex == some(VC4_Sex.Male)
|
||||
v4Ex.gender.get.genderIdentity == some("male")
|
||||
|
||||
#[
|
||||
test "CATEGORIES is parsed correctly":
|
||||
test "REV is parsed correctly":
|
||||
test "CLIENTPIDMAP is parsed correctly":
|
||||
]#
|
||||
|
||||
test "unknown properties are parsed correctly":
|
||||
|
||||
check v4Ex.customProp("MADE-UP-PROP").len == 1
|
||||
let madeUpProp = v4Ex.customProp("MADE-UP-PROP")[0]
|
||||
check:
|
||||
madeUpProp.name == "MADE-UP-PROP"
|
||||
madeUpProp.value == "Sample value for my made-up prop."
|
||||
|
||||
let cardWithAltBdayStr = testVCardTemplate % [(
|
||||
"BDAY;VALUE=text;ALTID=1:20th century\r\n" &
|
||||
"BDAY;VALUE=date-and-or-time;ALTID=1:19650321\r\n"
|
||||
)]
|
||||
|
||||
test "single-cardinality properties allow multiples with ALTID":
|
||||
check parseVCards(cardWithAltBdayStr).len == 1
|
||||
|
||||
let hasAltBdays = cast[VCard4](parseVCards(cardWithAltBdayStr)[0])
|
||||
|
||||
test "properties with cardinality 1 and altids return the first found by default":
|
||||
check:
|
||||
hasAltBdays.bday.isSome
|
||||
hasAltBdays.bday.get.value == "20th century"
|
||||
hasAltBdays.bday.get.year.isNone
|
||||
|
||||
test "allAlternatives":
|
||||
check:
|
||||
hasAltBdays.content.len == 3
|
||||
hasAltBdays.bday.isSome
|
||||
|
||||
let allBdays = allAlternatives[VC4_Bday](hasAltBdays)
|
||||
check:
|
||||
allBdays.len == 1
|
||||
allBdays.contains("1")
|
||||
allBdays["1"].len == 2
|
||||
|
||||
let bday0 = allBdays["1"][0]
|
||||
check:
|
||||
bday0.value == "20th century"
|
||||
bday0.year.isNone
|
||||
bday0.month.isNone
|
||||
bday0.day.isNone
|
||||
bday0.hour.isNone
|
||||
bday0.minute.isNone
|
||||
bday0.second.isNone
|
||||
bday0.timezone.isNone
|
||||
|
||||
let bday1 = allBDays["1"][1]
|
||||
check:
|
||||
bday1.value == "19650321"
|
||||
bday1.year == some(1965)
|
||||
bday1.month == some(3)
|
||||
bday1.day == some(21)
|
||||
bday1.hour.isNone
|
||||
bday1.minute.isNone
|
||||
bday1.second.isNone
|
||||
|
||||
test "PREF ordering":
|
||||
check:
|
||||
v4Ex.nickname --> map(it.value) == @[@["Jack Jr."], @["Doc A"]]
|
||||
v4Ex.nickname.inPrefOrder --> map(it.value) == @[@["Doc A"], @["Jack Jr."]]
|
||||
|
Reference in New Issue
Block a user