js: improve tests + some docs (#16727)

* js: improve tests

* _

* _

* _

* fixup
This commit is contained in:
Timothee Cour 2021-01-16 03:08:40 -08:00 • committed by GitHub
commit 18e14f5920
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 175 additions and 253 deletions

View file

@ -180,6 +180,7 @@ proc `<` *(x, y: JsObject): JsObject {.importcpp: "(# < #)".}
proc `>=` *(x, y: JsObject): JsObject {.importcpp: "(# >= #)".} proc `>=` *(x, y: JsObject): JsObject {.importcpp: "(# >= #)".}
proc `<=` *(x, y: JsObject): JsObject {.importcpp: "(# <= #)".} proc `<=` *(x, y: JsObject): JsObject {.importcpp: "(# <= #)".}
proc `**` *(x, y: JsObject): JsObject {.importcpp: "((#) ** #)".} proc `**` *(x, y: JsObject): JsObject {.importcpp: "((#) ** #)".}
# (#) needed, refs https://github.com/nim-lang/Nim/pull/16409#issuecomment-760550812
proc `and`*(x, y: JsObject): JsObject {.importcpp: "(# && #)".} proc `and`*(x, y: JsObject): JsObject {.importcpp: "(# && #)".}
proc `or` *(x, y: JsObject): JsObject {.importcpp: "(# || #)".} proc `or` *(x, y: JsObject): JsObject {.importcpp: "(# || #)".}
proc `not`*(x: JsObject): JsObject {.importcpp: "(!#)".} proc `not`*(x: JsObject): JsObject {.importcpp: "(!#)".}

View file

@ -92,8 +92,18 @@ func `==`*(x, y: JsBigInt): bool {.importjs: "(# == #)".} =
doAssert big"42" == big"42" doAssert big"42" == big"42"
func `**`*(x, y: JsBigInt): JsBigInt {.importjs: "((#) $1 #)".} = func `**`*(x, y: JsBigInt): JsBigInt {.importjs: "((#) $1 #)".} =
# (#) needed, refs https://github.com/nim-lang/Nim/pull/16409#issuecomment-760550812
runnableExamples: runnableExamples:
doAssert (big"9" ** big"5") == big"59049" doAssert big"2" ** big"64" == big"18446744073709551616"
doAssert big"-2" ** big"3" == big"-8"
doAssert -big"2" ** big"2" == big"4" # parsed as: (-2n) ** 2n
doAssert big"0" ** big"0" == big"1" # edge case
var ok = false
try: discard big"2" ** big"-1" # raises foreign `RangeError`
except: ok = true
doAssert ok
# pending https://github.com/nim-lang/Nim/pull/15940, simplify to:
# doAssertRaises: discard big"2" ** big"-1" # raises foreign `RangeError`
func `xor`*(x, y: JsBigInt): JsBigInt {.importjs: "(# ^ #)".} = func `xor`*(x, y: JsBigInt): JsBigInt {.importjs: "(# ^ #)".} =
runnableExamples: runnableExamples:

View file

@ -1,291 +1,196 @@
discard """ discard """
output: ''' output: '''
true
true
true
true
true
true
true
true
true
true
true
true
true
true
true
true
3 3
2 2
12 12
Event { name: 'click: test' } Event { name: 'click: test' }
Event { name: 'reloaded: test' } Event { name: 'reloaded: test' }
Event { name: 'updates: test' } Event { name: 'updates: test' }
true
true
true
true
true
true
true
''' '''
""" """
import jsffi, jsconsole import jsffi, jsconsole
# Tests for JsObject # Tests for JsObject
# Test JsObject []= and [] block: # Test JsObject []= and []
block: let obj = newJsObject()
proc test(): bool = obj["a"] = 11
let obj = newJsObject() obj["b"] = "test"
var working = true obj["c"] = "test".cstring
obj["a"] = 11 doAssert obj["a"].to(int) == 11
obj["b"] = "test" doAssert obj["c"].to(cstring) == "test".cstring
obj["c"] = "test".cstring
working = working and obj["a"].to(int) == 11
working = working and obj["c"].to(cstring) == "test".cstring
working
echo test()
# Test JsObject .= and . block: # Test JsObject .= and .
block: let obj = newJsObject()
proc test(): bool = obj.a = 11
let obj = newJsObject() obj.b = "test"
var working = true obj.c = "test".cstring
obj.a = 11 obj.`$!&` = 42
obj.b = "test" obj.`while` = 99
obj.c = "test".cstring doAssert obj.a.to(int) == 11
obj.`$!&` = 42 doAssert obj.b.to(string) == "test"
obj.`while` = 99 doAssert obj.c.to(cstring) == "test".cstring
working = working and obj.a.to(int) == 11 doAssert obj.`$!&`.to(int) == 42
working = working and obj.b.to(string) == "test" doAssert obj.`while`.to(int) == 99
working = working and obj.c.to(cstring) == "test".cstring
working = working and obj.`$!&`.to(int) == 42
working = working and obj.`while`.to(int) == 99
working
echo test()
# Test JsObject .() block: # Test JsObject .()
block: let obj = newJsObject()
proc test(): bool = obj.`?!$` = proc(x, y, z: int, t: cstring): cstring = t & $(x + y + z)
let obj = newJsObject() doAssert obj.`?!$`(1, 2, 3, "Result is: ").to(cstring) == cstring"Result is: 6"
obj.`?!$` = proc(x, y, z: int, t: cstring): cstring = t & $(x + y + z)
obj.`?!$`(1, 2, 3, "Result is: ").to(cstring) == cstring"Result is: 6"
echo test()
# Test JsObject []() block: # Test JsObject []()
block: let obj = newJsObject()
proc test(): bool = obj.a = proc(x, y, z: int, t: string): string = t & $(x + y + z)
let obj = newJsObject() let call = obj["a"].to(proc(x, y, z: int, t: string): string)
obj.a = proc(x, y, z: int, t: string): string = t & $(x + y + z) doAssert call(1, 2, 3, "Result is: ") == "Result is: 6"
let call = obj["a"].to(proc(x, y, z: int, t: string): string)
call(1, 2, 3, "Result is: ") == "Result is: 6"
echo test()
# Test JsObject Iterators # Test JsObject Iterators
block: block: # testPairs
proc testPairs(): bool = let obj = newJsObject()
let obj = newJsObject() obj.a = 10
var working = true obj.b = 20
obj.a = 10 obj.c = 30
obj.b = 20 for k, v in obj.pairs:
obj.c = 30 case $k
for k, v in obj.pairs: of "a":
case $k doAssert v.to(int) == 10
of "a": of "b":
working = working and v.to(int) == 10 doAssert v.to(int) == 20
of "b": of "c":
working = working and v.to(int) == 20 doAssert v.to(int) == 30
of "c": else:
working = working and v.to(int) == 30 doAssert false
else: block: # testItems
return false let obj = newJsObject()
working obj.a = 10
proc testItems(): bool = obj.b = 20
let obj = newJsObject() obj.c = 30
var working = true for v in obj.items:
obj.a = 10 doAssert v.to(int) in [10, 20, 30]
obj.b = 20 block: # testKeys
obj.c = 30 let obj = newJsObject()
for v in obj.items: obj.a = 10
working = working and v.to(int) in [10, 20, 30] obj.b = 20
working obj.c = 30
proc testKeys(): bool = for v in obj.keys:
let obj = newJsObject() doAssert $v in ["a", "b", "c"]
var working = true
obj.a = 10
obj.b = 20
obj.c = 30
for v in obj.keys:
working = working and $v in ["a", "b", "c"]
working
proc test(): bool = testPairs() and testItems() and testKeys()
echo test()
# Test JsObject equality block: # Test JsObject equality
block: {. emit: "var comparison = {a: 22, b: 'test'};" .}
proc test(): bool = var comparison {. importjs, nodecl .}: JsObject
{. emit: "var comparison = {a: 22, b: 'test'};" .} let obj = newJsObject()
var comparison {. importjs, nodecl .}: JsObject obj.a = 22
let obj = newJsObject() obj.b = "test".cstring
obj.a = 22 doAssert obj.a == comparison.a and obj.b == comparison.b
obj.b = "test".cstring
obj.a == comparison.a and obj.b == comparison.b
echo test()
# Test JsObject literal block: # Test JsObject literal
block: {. emit: "var comparison = {a: 22, b: 'test'};" .}
proc test(): bool = var comparison {. importjs, nodecl .}: JsObject
{. emit: "var comparison = {a: 22, b: 'test'};" .} let obj = JsObject{ a: 22, b: "test".cstring }
var comparison {. importjs, nodecl .}: JsObject doAssert obj.a == comparison.a and obj.b == comparison.b
let obj = JsObject{ a: 22, b: "test".cstring }
obj.a == comparison.a and obj.b == comparison.b
echo test()
# Tests for JsAssoc # Tests for JsAssoc
# Test JsAssoc []= and [] block: # Test JsAssoc []= and []
block: let obj = newJsAssoc[int, int]()
proc test(): bool = obj[1] = 11
let obj = newJsAssoc[int, int]() doAssert not compiles(obj["a"] = 11)
var working = true doAssert not compiles(obj["a"])
obj[1] = 11 doAssert not compiles(obj[2] = "test")
working = working and not compiles(obj["a"] = 11) doAssert not compiles(obj[3] = "test".cstring)
working = working and not compiles(obj["a"]) doAssert obj[1] == 11
working = working and not compiles(obj[2] = "test")
working = working and not compiles(obj[3] = "test".cstring)
working = working and obj[1] == 11
working
echo test()
# Test JsAssoc .= and . block: # Test JsAssoc .= and .
block: let obj = newJsAssoc[cstring, int]()
proc test(): bool = var working = true
let obj = newJsAssoc[cstring, int]() obj.a = 11
var working = true obj.`$!&` = 42
obj.a = 11 doAssert not compiles(obj.b = "test")
obj.`$!&` = 42 doAssert not compiles(obj.c = "test".cstring)
working = working and not compiles(obj.b = "test") doAssert obj.a == 11
working = working and not compiles(obj.c = "test".cstring) doAssert obj.`$!&` == 42
working = working and obj.a == 11
working = working and obj.`$!&` == 42
working
echo test()
# Test JsAssoc .() block: # Test JsAssoc .()
block: let obj = newJsAssoc[cstring, proc(e: int): int]()
proc test(): bool = obj.a = proc(e: int): int = e * e
let obj = newJsAssoc[cstring, proc(e: int): int]() doAssert obj.a(10) == 100
obj.a = proc(e: int): int = e * e
obj.a(10) == 100
echo test()
# Test JsAssoc []() block: # Test JsAssoc []()
block: let obj = newJsAssoc[cstring, proc(e: int): int]()
proc test(): bool = obj.a = proc(e: int): int = e * e
let obj = newJsAssoc[cstring, proc(e: int): int]() let call = obj["a"]
obj.a = proc(e: int): int = e * e doAssert call(10) == 100
let call = obj["a"]
call(10) == 100
echo test()
# Test JsAssoc Iterators # Test JsAssoc Iterators
block: block: # testPairs
proc testPairs(): bool = let obj = newJsAssoc[cstring, int]()
let obj = newJsAssoc[cstring, int]() obj.a = 10
var working = true obj.b = 20
obj.a = 10 obj.c = 30
obj.b = 20 for k, v in obj.pairs:
obj.c = 30 case $k
for k, v in obj.pairs: of "a":
case $k doAssert v == 10
of "a": of "b":
working = working and v == 10 doAssert v == 20
of "b": of "c":
working = working and v == 20 doAssert v == 30
of "c": else:
working = working and v == 30 doAssert false
else: block: # testItems
return false let obj = newJsAssoc[cstring, int]()
working obj.a = 10
proc testItems(): bool = obj.b = 20
let obj = newJsAssoc[cstring, int]() obj.c = 30
var working = true for v in obj.items:
obj.a = 10 doAssert v in [10, 20, 30]
obj.b = 20 block: # testKeys
obj.c = 30 let obj = newJsAssoc[cstring, int]()
for v in obj.items: obj.a = 10
working = working and v in [10, 20, 30] obj.b = 20
working obj.c = 30
proc testKeys(): bool = for v in obj.keys:
let obj = newJsAssoc[cstring, int]() doAssert v in [cstring"a", cstring"b", cstring"c"]
var working = true
obj.a = 10
obj.b = 20
obj.c = 30
for v in obj.keys:
working = working and v in [cstring"a", cstring"b", cstring"c"]
working
proc test(): bool = testPairs() and testItems() and testKeys()
echo test()
# Test JsAssoc equality block: # Test JsAssoc equality
block: {. emit: "var comparison = {a: 22, b: 55};" .}
proc test(): bool = var comparison {. importjs, nodecl .}: JsAssoc[cstring, int]
{. emit: "var comparison = {a: 22, b: 55};" .} let obj = newJsAssoc[cstring, int]()
var comparison {. importjs, nodecl .}: JsAssoc[cstring, int] obj.a = 22
let obj = newJsAssoc[cstring, int]() obj.b = 55
obj.a = 22 doAssert obj.a == comparison.a and obj.b == comparison.b
obj.b = 55
obj.a == comparison.a and obj.b == comparison.b
echo test()
# Test JsAssoc literal block: # Test JsAssoc literal
block: {. emit: "var comparison = {a: 22, b: 55};" .}
proc test(): bool = var comparison {. importjs, nodecl .}: JsAssoc[cstring, int]
{. emit: "var comparison = {a: 22, b: 55};" .} let obj = JsAssoc[cstring, int]{ a: 22, b: 55 }
var comparison {. importjs, nodecl .}: JsAssoc[cstring, int] doAssert compiles(JsAssoc[int, int]{ 1: 22, 2: 55 })
let obj = JsAssoc[cstring, int]{ a: 22, b: 55 } doAssert comparison.a == obj.a and comparison.b == obj.b
var working = true doAssert not compiles(JsAssoc[cstring, int]{ a: "test" })
working = working and
compiles(JsAssoc[int, int]{ 1: 22, 2: 55 })
working = working and
comparison.a == obj.a and comparison.b == obj.b
working = working and
not compiles(JsAssoc[cstring, int]{ a: "test" })
working
echo test()
# Tests for macros on non-JsRoot objects # Tests for macros on non-JsRoot objects
# Test lit block: # Test lit
block:
type TestObject = object type TestObject = object
a: int a: int
b: cstring b: cstring
proc test(): bool = {. emit: "var comparison = {a: 1};" .}
{. emit: "var comparison = {a: 1};" .} var comparison {. importjs, nodecl .}: TestObject
var comparison {. importjs, nodecl .}: TestObject let obj = TestObject{ a: 1 }
let obj = TestObject{ a: 1 } doAssert obj == comparison
obj == comparison
echo test()
# Test bindMethod block: # Test bindMethod
block:
type TestObject = object type TestObject = object
a: int a: int
onWhatever: proc(e: int): int onWhatever: proc(e: int): int
proc handleWhatever(this: TestObject, e: int): int = proc handleWhatever(this: TestObject, e: int): int =
e + this.a e + this.a
proc test(): bool = block:
let obj = TestObject(a: 9, onWhatever: bindMethod(handleWhatever)) let obj = TestObject(a: 9, onWhatever: bindMethod(handleWhatever))
obj.onWhatever(1) == 10 doAssert obj.onWhatever(1) == 10
echo test()
block: block:
{.emit: "function jsProc(n) { return n; }" .} {.emit: "function jsProc(n) { return n; }" .}
proc jsProc(x: int32): JsObject {.importjs: "jsProc(#)".} proc jsProc(x: int32): JsObject {.importjs: "jsProc(#)".}
block:
proc test() =
var x = jsProc(1) var x = jsProc(1)
var y = jsProc(2) var y = jsProc(2)
console.log x + y console.log x + y
@ -294,8 +199,6 @@ block:
x += jsProc(10) x += jsProc(10)
console.log x console.log x
test()
block: block:
{.emit: {.emit:
""" """
@ -323,13 +226,13 @@ block:
console.log jsarguments[0] console.log jsarguments[0]
block: block:
echo jsUndefined == jsNull doAssert jsUndefined == jsNull
echo jsUndefined == nil doAssert jsUndefined == nil
echo jsNull == nil doAssert jsNull == nil
echo jsUndefined.isNil doAssert jsUndefined.isNil
echo jsNull.isNil doAssert jsNull.isNil
echo jsNull.isNull doAssert jsNull.isNull
echo jsUndefined.isUndefined doAssert jsUndefined.isUndefined
block: # test ** block: # test **
var a = toJs(0) var a = toJs(0)
@ -362,4 +265,3 @@ block: # test **
doAssert to(`**`(a + a, b), int) == 2 doAssert to(`**`(a + a, b), int) == 2
doAssert to(`**`(toJs(1) + toJs(1), toJs(2)), int) == 4 doAssert to(`**`(toJs(1) + toJs(1), toJs(2)), int) == 4

View file

@ -35,6 +35,9 @@ true
## same as tjsffi, but this test uses the old names: importc and ## same as tjsffi, but this test uses the old names: importc and
## importcpp. This test is for backwards compatibility. ## importcpp. This test is for backwards compatibility.
# xxx instead of maintaining this near-duplicate test file, just have tests
# that check that importc, importcpp, importjs work and remove this file.
import jsffi, jsconsole import jsffi, jsconsole
# Tests for JsObject # Tests for JsObject

View file

@ -36,3 +36,9 @@ for i in big"0" ..< big"5":
doAssert i is JsBigInt doAssert i is JsBigInt
list.add i list.add i
doAssert list == @[big"0", big"1", big"2", big"3", big"4"] doAssert list == @[big"0", big"1", big"2", big"3", big"4"]
block:
let b = big"2"
doAssert -b ** big"3" == big"-8"
doAssert -b ** big"2" == big"4" # not -4 because of precedence
doAssert -big"3" == big"-3"