diff options
author | major seitan <majorseitan@users.noreply.github.com> | 2018-06-02 14:58:45 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-06-02 14:58:45 -0400 |
commit | 87c86c5d2066a8805c7e72e3279ae8d5822f0c90 (patch) | |
tree | 02fa912c9b44ee07c0fcfe2bad0e2b686d0103b3 | |
parent | b4ffc6c4837e06c48a1a15ea662c25aa92566bf6 (diff) | |
parent | 1c493e9ec47f4754dd7237078e8c4f3300925ce3 (diff) |
Merge branch 'master' into master
51 files changed, 494 insertions, 49 deletions
@@ -76,3 +76,8 @@ libtool include/urweb/config.h include/urweb/config.h.in include/urweb/stamp-h1 + +# python files +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] diff --git a/include/urweb/urweb_cpp.h b/include/urweb/urweb_cpp.h index 0d5f5e0e..2c60a781 100644 --- a/include/urweb/urweb_cpp.h +++ b/include/urweb/urweb_cpp.h @@ -358,8 +358,6 @@ uw_Basis_string uw_Basis_timef(struct uw_context *, const char *fmt, uw_Basis_ti uw_Basis_time uw_Basis_stringToTimef(struct uw_context *, const char *fmt, uw_Basis_string); uw_Basis_time uw_Basis_stringToTimef_error(struct uw_context *, const char *fmt, uw_Basis_string); -uw_Basis_string uw_Basis_crypt(struct uw_context *, uw_Basis_string key, uw_Basis_string salt); - uw_Basis_bool uw_Basis_eq_time(struct uw_context *, uw_Basis_time, uw_Basis_time); uw_Basis_bool uw_Basis_lt_time(struct uw_context *, uw_Basis_time, uw_Basis_time); uw_Basis_bool uw_Basis_le_time(struct uw_context *, uw_Basis_time, uw_Basis_time); diff --git a/lib/ur/basis.urs b/lib/ur/basis.urs index c354d784..dc1b9b76 100644 --- a/lib/ur/basis.urs +++ b/lib/ur/basis.urs @@ -192,11 +192,6 @@ val datetimeSecond : time -> int val datetimeDayOfWeek : time -> int -(** * Encryption *) - -val crypt : string -> string -> string - - (** HTTP operations *) con http_cookie :: Type -> Type diff --git a/src/c/urweb.c b/src/c/urweb.c index 504597ef..283efcdd 100644 --- a/src/c/urweb.c +++ b/src/c/urweb.c @@ -4490,11 +4490,6 @@ failure_kind uw_runCallback(uw_context ctx, void (*callback)(uw_context)) { return r; } -uw_Basis_string uw_Basis_crypt(uw_context ctx, uw_Basis_string key, uw_Basis_string salt) { - char buf[14]; - return uw_strdup(ctx, DES_fcrypt(key, salt, buf)); -} - uw_Basis_bool uw_Basis_eq_time(uw_context ctx, uw_Basis_time t1, uw_Basis_time t2) { (void)ctx; return !!(t1.seconds == t2.seconds && t1.microseconds == t2.microseconds); diff --git a/src/cjr_print.sml b/src/cjr_print.sml index 1fdb45d9..43265fb8 100644 --- a/src/cjr_print.sml +++ b/src/cjr_print.sml @@ -659,7 +659,10 @@ fun unurlify fromClient env (t, loc) = doEm rest, string ")"] in - doEm xncs + box [string "(request[0] == '/' ? ++request : request,", + newline, + doEm xncs, + string ")"] end | TDatatype (Option, i, xncs) => diff --git a/src/elaborate.sml b/src/elaborate.sml index 4a04d4bf..51d00bd8 100644 --- a/src/elaborate.sml +++ b/src/elaborate.sml @@ -4046,7 +4046,8 @@ and elabDecl (dAll as (d, loc), (env, denv, gs)) = | L.PAnnot (p', _) => singleVar p' | _ => NONE in - unifyCons env loc et pt; + (unifyCons env loc et pt + handle CUnify (c1, c2, env', err) => expError env (Unify (e', c1, c2, env', err))); (case exhaustive (env, et, [p'], loc) of NONE => () diff --git a/tests/DynChannel.py b/tests/DynChannel.py new file mode 100644 index 00000000..7af5ea78 --- /dev/null +++ b/tests/DynChannel.py @@ -0,0 +1,20 @@ +import unittest +import base + +class Suite(base.Base): + def test_1(self): + """Test case 1""" + self.start('DynChannel/main') + + # initial state: only Register is visible + reg = self.xpath('button') + reg.click() + # and we get two another state: either Register or Send visible + send = self.xpath('span/button') + send.click() + alert = self.driver.switch_to.alert + self.assertEqual("Got something from the channel", alert.text) + alert.accept() + # we got the message back + span = self.xpath('span/span') + self.assertEqual("blabla", span.text) diff --git a/tests/Makefile b/tests/Makefile index 5313d12d..ecf5557b 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -2,3 +2,29 @@ all: test.o test.o: test.c gcc -c test.c -o test.o +### + +simple:: + ./driver.sh aborter2 + ./driver.sh aborter + ./driver.sh activeBlock + ./driver.sh activeFocus + ./driver.sh active + ./driver.sh agg + ./driver.sh ahead + ./driver.sh alert + ./driver.sh align + ./driver.sh appjs + ./driver.sh ascdesc + echo ./driver.sh attrMangle + ./driver.sh attrs_escape + echo ./driver.sh attrs + ./driver.sh autocomp + ./driver.sh babySpawn + ./driver.sh bindpat + ./driver.sh DynChannel + ./driver.sh jsonTest + ./driver.sh entities + ./driver.sh fact + ./driver.sh filter + ./driver.sh jsbspace diff --git a/tests/aborter.py b/tests/aborter.py new file mode 100644 index 00000000..8379c656 --- /dev/null +++ b/tests/aborter.py @@ -0,0 +1,11 @@ +import unittest +import base + +class Suite(base.Base): + def test_1(self): + """Test case 1""" + self.start('Aborter/main') + self.assertEqual("Fatal Error", self.driver.title) + txt = self.body_text() + self.assertEqual("Fatal error: :0:0-0:0: No way, Jose!", txt) + diff --git a/tests/aborter.urp b/tests/aborter.urp index fc1925ae..8c971440 100644 --- a/tests/aborter.urp +++ b/tests/aborter.urp @@ -1,4 +1,5 @@ database dbname=aborter sql aborter.sql +safeGet Aborter/main aborter diff --git a/tests/aborter2.py b/tests/aborter2.py new file mode 100644 index 00000000..c3f1e10e --- /dev/null +++ b/tests/aborter2.py @@ -0,0 +1,11 @@ +import unittest +import base + +class Suite(base.Base): + def test_1(self): + """Test case 1""" + self.start('Aborter2/main') + self.assertEqual("", self.driver.title) + txt = self.body_text() + self.assertEqual("Result: 0", txt) + diff --git a/tests/active.py b/tests/active.py new file mode 100644 index 00000000..08846ac5 --- /dev/null +++ b/tests/active.py @@ -0,0 +1,14 @@ +import unittest +import base + +class Suite(base.Base): + def test_1(self): + """Test case 1""" + self.start() + b1 = self.xpath('span[1]/button') + b2 = self.xpath('span[2]/button') + for _ in range(3): + b1.click() + for _ in range(5): + b2.click() + self.assertEqual("3\n5", self.body_text()) diff --git a/tests/activeBlock.py b/tests/activeBlock.py new file mode 100644 index 00000000..d0e43fdb --- /dev/null +++ b/tests/activeBlock.py @@ -0,0 +1,20 @@ +import unittest +import base +import time + +class Suite(base.Base): + def test_1(self): + """Test case 1""" + self.start() + alert = self.driver.switch_to.alert + self.assertEqual("Error: May not 'sleep' in main thread of 'code' for <active>", alert.text) + alert.accept() + time.sleep(0.1) + alert = self.driver.switch_to.alert + self.assertEqual("Hi!", alert.text) + alert.accept() + button = self.xpath('span[1]/button') + button.click() + txt = self.body_text() + self.assertEqual("Hi! Click me! Success", txt) + diff --git a/tests/activeBlock.ur b/tests/activeBlock.ur index 5560edda..bced4af3 100644 --- a/tests/activeBlock.ur +++ b/tests/activeBlock.ur @@ -1,7 +1,7 @@ fun main () : transaction page = return <xml><body> <active code={s <- source ""; return <xml> <dyn signal={s <- signal s; return (txt s)}/> - <button onclick={fn _ => set s "Hi!"}/> + <button onclick={fn _ => set s "Hi!"}>Click me!</button> </xml>}/> <active code={sleep 1; return <xml>Hi!</xml>}/> diff --git a/tests/activeEmpty.py b/tests/activeEmpty.py new file mode 100644 index 00000000..8872833a --- /dev/null +++ b/tests/activeEmpty.py @@ -0,0 +1,12 @@ +import unittest +import base + +class Suite(base.Base): + def test_1(self): + """Test case 1""" + self.start() + alert = self.driver.switch_to.alert + self.assertEqual("Howdy, neighbor!", alert.text) + alert.accept() + txt = self.body_text() + self.assertEqual("This one ain't empty.", txt) diff --git a/tests/activeFocus.py b/tests/activeFocus.py new file mode 100644 index 00000000..47b9a921 --- /dev/null +++ b/tests/activeFocus.py @@ -0,0 +1,18 @@ +import unittest +import base + +class Suite(base.Base): + def test_1(self): + """Test case 1""" + self.start() + uw0 = self.xpath('input[2]') + active = self.driver.switch_to.active_element + self.assertEqual(uw0, active) + def test_2(self): + """Test case 2""" + self.start('dynamic') + btn = self.xpath('button') + btn.click() + uw1 = self.xpath('span/input[2]') + active = self.driver.switch_to.active_element + self.assertEqual(uw1, active) diff --git a/tests/activeFocus.ur b/tests/activeFocus.ur index 94d465e9..82d2c0c9 100644 --- a/tests/activeFocus.ur +++ b/tests/activeFocus.ur @@ -14,5 +14,5 @@ fun dynamic () : transaction page = <ctextbox/> <ctextbox id={i}/> <active code={giveFocus i; return <xml>Done</xml>}/> - </xml>}/> + </xml>}>Click</button> </body></xml> diff --git a/tests/agg.py b/tests/agg.py new file mode 100644 index 00000000..0b421d37 --- /dev/null +++ b/tests/agg.py @@ -0,0 +1,8 @@ +import unittest +import base + +class Suite(base.Base): + def test_1(self): + """Test case 1""" + self.start('Agg/main') + self.assertEqual("0;1;2;\na, 50;", self.body_text()) diff --git a/tests/agg.ur b/tests/agg.ur index 19a8644b..2d8eed43 100644 --- a/tests/agg.ur +++ b/tests/agg.ur @@ -1,13 +1,23 @@ table t1 : {A : int, B : string, C : float} table t2 : {A : float, D : int, E : option string} -val q1 : sql_query [] _ _ = (SELECT COUNT( * ) FROM t1) -val q2 : sql_query [] _ _ = (SELECT AVG(t1.A) FROM t1) -val q3 : sql_query [] _ _ = (SELECT SUM(t1.C) FROM t1) -val q4 : sql_query [] _ _ = (SELECT MIN(t1.B), MAX(t1.A) FROM t1) -val q5 : sql_query [] _ _ = (SELECT SUM(t1.A) FROM t1 GROUP BY t1.B) +val q1 : sql_query [] [] _ _ = (SELECT COUNT( * ) FROM t1) +val q2 : sql_query [] [] _ _ = (SELECT AVG(t1.A) FROM t1) +val q3 : sql_query [] [] _ _ = (SELECT SUM(t1.C) FROM t1) +val q4 : sql_query [] [] _ _ = (SELECT MIN(t1.B), MAX(t1.A) FROM t1) +val q5 : sql_query [] [] _ _ = (SELECT SUM(t1.A) FROM t1 GROUP BY t1.B) val q6 = (SELECT COUNT(t2.E) FROM t2 GROUP BY t2.D) +task initialize = fn () => + dml (INSERT INTO t1 (A, B, C) VALUES (1, 'a', 1.0)); + dml (INSERT INTO t1 (A, B, C) VALUES (2, 'b', 2.0)); + dml (INSERT INTO t1 (A, B, C) VALUES (50, 'c', 99.0)); + dml (INSERT INTO t2 (A, D, E) VALUES (1.0, 1, NULL)); + dml (INSERT INTO t2 (A, D, E) VALUES (1.0, 2, {[Some "a"]})); + dml (INSERT INTO t2 (A, D, E) VALUES (1.0, 3, NULL)); + dml (INSERT INTO t2 (A, D, E) VALUES (1.0, 3, {[Some "b"]})); + dml (INSERT INTO t2 (A, D, E) VALUES (1.0, 3, {[Some "c"]})) + fun main () : transaction page = xml <- queryX q6 (fn r => <xml>{[r.1]};</xml>); xml2 <- queryX q4 (fn r => <xml>{[r.1]}, {[r.2]};</xml>); diff --git a/tests/ahead.py b/tests/ahead.py new file mode 100644 index 00000000..6e767948 --- /dev/null +++ b/tests/ahead.py @@ -0,0 +1,15 @@ +import unittest +import base +import time + +class Suite(base.Base): + def test_1(self): + """Test case 1""" + self.start() + alert = self.driver.switch_to.alert + self.assertEqual("Hi!", alert.text) + alert.accept() + time.sleep(0.1) + alert = self.driver.switch_to.alert + self.assertEqual("Bye!", alert.text) + alert.accept() diff --git a/tests/alert.py b/tests/alert.py new file mode 100644 index 00000000..4b783d50 --- /dev/null +++ b/tests/alert.py @@ -0,0 +1,11 @@ +import unittest +import base + +class Suite(base.Base): + def test_1(self): + """Test case 1""" + self.start() + el = self.xpath('a') + el.click() + alert = self.driver.switch_to.alert + self.assertEqual("You clicked it! That's some fancy shooting!", alert.text) diff --git a/tests/alert.ur b/tests/alert.ur index 3fe68d75..7a290921 100644 --- a/tests/alert.ur +++ b/tests/alert.ur @@ -1,3 +1,3 @@ fun main () : transaction page = return <xml><body> - <a onclick={alert "You clicked it! That's some fancy shooting!"}>Click Me!</a> + <a onclick={fn _ => alert "You clicked it! That's some fancy shooting!"}>Click Me!</a> </body></xml> diff --git a/tests/alert.urp b/tests/alert.urp deleted file mode 100644 index 3976e9b0..00000000 --- a/tests/alert.urp +++ /dev/null @@ -1,3 +0,0 @@ -debug - -alert diff --git a/tests/align.py b/tests/align.py new file mode 100644 index 00000000..525ab4e6 --- /dev/null +++ b/tests/align.py @@ -0,0 +1,11 @@ +import unittest +import base + +class Suite(base.Base): + def test_1(self): + """Test case 1""" + self.start() + el = self.xpath('p[@align="left"]') + self.assertEqual("Left", el.text) + el = self.xpath('p[@align="right"]') + self.assertEqual("Right", el.text) diff --git a/tests/appjs.py b/tests/appjs.py new file mode 100644 index 00000000..02ac2193 --- /dev/null +++ b/tests/appjs.py @@ -0,0 +1,11 @@ +import unittest +import base + +class Suite(base.Base): + def test_1(self): + """Test case 1""" + self.start() + el = self.xpath('button') + el.click() + alert = self.driver.switch_to.alert + self.assertEqual("3", alert.text) diff --git a/tests/appjs.ur b/tests/appjs.ur index 01e9f345..403b0b4e 100644 --- a/tests/appjs.ur +++ b/tests/appjs.ur @@ -1,5 +1,5 @@ fun id n = if n = 0 then 0 else 1 + id (n - 1) fun main () : transaction page = return <xml><body> - <button onclick={alert (show (id 3))}/> + <button onclick={fn _ => alert (show (id 3))}/> </body></xml> diff --git a/tests/ascdesc.py b/tests/ascdesc.py new file mode 100644 index 00000000..6b514f4e --- /dev/null +++ b/tests/ascdesc.py @@ -0,0 +1,11 @@ +import unittest +import base + +class Suite(base.Base): + def test_1(self): + """Test case 1""" + self.start('Ascdesc/main') + el = self.xpath('p[1]') + self.assertEqual("1; 2; 3;", el.text) + el = self.xpath('p[2]') + self.assertEqual("3; 2; 1;", el.text) diff --git a/tests/ascdesc.ur b/tests/ascdesc.ur index 59dd0169..fadac27d 100644 --- a/tests/ascdesc.ur +++ b/tests/ascdesc.ur @@ -4,7 +4,15 @@ fun sortEm b = queryX1 (SELECT * FROM t ORDER BY t.A {if b then sql_asc else sql_desc}) (fn r => <xml>{[r.A]}; </xml>) -fun main () : transaction page = return <xml><body> - <a link={sortEm True}>Ascending</a><br/> - <a link={sortEm False}>Descending</a> +task initialize = fn () => + dml (INSERT INTO t (A) VALUES (1)); + dml (INSERT INTO t (A) VALUES (2)); + dml (INSERT INTO t (A) VALUES (3)) + +fun main () : transaction page = + p1 <- sortEm True; + p2 <- sortEm False; + return <xml><body> + <p>{p1}</p> + <p>{p2}</p> </body></xml> diff --git a/tests/ascdesc.urp b/tests/ascdesc.urp index 3e0b075d..a1c4124e 100644 --- a/tests/ascdesc.urp +++ b/tests/ascdesc.urp @@ -1,4 +1,3 @@ -database dbname=test -sql ascdesc.sql +database dbname=ascdesc ascdesc
\ No newline at end of file diff --git a/tests/attrMangle.py b/tests/attrMangle.py new file mode 100644 index 00000000..d3b24244 --- /dev/null +++ b/tests/attrMangle.py @@ -0,0 +1,11 @@ +import unittest +import base + +class Suite(base.Base): + def test_1(self): + """Test case 1""" + self.start() + el = self.xpath('goofy[@name eq "beppo" and @data-role eq "excellence"]') + el.click() + alert = self.driver.switch_to.alert + self.assertEqual("You clicked it! That's some fancy shooting!", alert.text) diff --git a/tests/attrs_escape.py b/tests/attrs_escape.py new file mode 100644 index 00000000..fc9f91b5 --- /dev/null +++ b/tests/attrs_escape.py @@ -0,0 +1,10 @@ +import unittest +import base + +class Suite(base.Base): + def test_1(self): + """Test case 1""" + self.start() + el = self.xpath('form/input') + val = el.get_attribute('value') + self.assertEqual("\"Well hey\"\nWow", val) diff --git a/tests/attrs_escape.ur b/tests/attrs_escape.ur index 12de101e..87d554fe 100644 --- a/tests/attrs_escape.ur +++ b/tests/attrs_escape.ur @@ -1,4 +1,6 @@ -val main = fn () => <html><body> - <font face="\"Well hey\" -Wow">Welcome</font> -</body></html> +fun main () : transaction page = return <xml><body> +<form> + <submit value="\"Well hey\" +Wow"/> +</form> +</body></xml> diff --git a/tests/autocomp.py b/tests/autocomp.py new file mode 100644 index 00000000..28c3b7d2 --- /dev/null +++ b/tests/autocomp.py @@ -0,0 +1,15 @@ +import unittest +import base + +class Suite(base.Base): + def test_1(self): + """Test case 1""" + self.start() + txt = self.xpath('div') + self.assertEqual('/', txt.text) + inp = self.xpath('/input') + inp.send_keys('hello there') + self.assertEqual('hello there /', txt.text) + btn = self.xpath('button') + btn.click() + self.assertEqual("hello there / hello there", txt.text) diff --git a/tests/autocomp.ur b/tests/autocomp.ur index d4e6a287..753318f7 100644 --- a/tests/autocomp.ur +++ b/tests/autocomp.ur @@ -2,10 +2,10 @@ fun main () : transaction page = a <- source ""; b <- source ""; return <xml><body> - <form> - <textbox{#A} source={a}/> - <button onclick={x <- get a; set b x}/> + <ctextbox source={a}/> + <button onclick={fn _ => x <- get a; set b x}>click me</button> + <div> <dyn signal={v <- signal a; return <xml>{[v]}</xml>}/> / <dyn signal={v <- signal b; return <xml>{[v]}</xml>}/> - </form> + </div> </body></xml> diff --git a/tests/babySpawn.py b/tests/babySpawn.py new file mode 100644 index 00000000..6693e969 --- /dev/null +++ b/tests/babySpawn.py @@ -0,0 +1,12 @@ +import unittest +import base +import time + +class Suite(base.Base): + def test_1(self): + """Test case 1""" + self.start() + btn = self.xpath('button') + btn.click() + alert = self.driver.switch_to.alert + self.assertEqual("Hi", alert.text) diff --git a/tests/base.py b/tests/base.py new file mode 100644 index 00000000..b9a026f2 --- /dev/null +++ b/tests/base.py @@ -0,0 +1,29 @@ +# use pip install selenium first +# ensure you have both chome driver & chrome installed + +import unittest +from selenium import webdriver +from selenium.common.exceptions import NoSuchElementException + +class Base(unittest.TestCase): + """Include test cases on a given url""" + + def start(self, path='main'): + self.driver.get('http://localhost:8080/' + path) + def xpath(self, path): + return self.driver.find_element_by_xpath('/html/body/'+path) + def body_text(self): + return self.driver.find_element_by_xpath('/html/body').text + + def setUp(self): + """Start web driver""" + chrome_options = webdriver.ChromeOptions() + chrome_options.add_argument('--no-sandbox') + chrome_options.add_argument('--headless') + chrome_options.add_argument('--disable-gpu') + self.driver = webdriver.Chrome(options=chrome_options) + self.driver.implicitly_wait(10) + + def tearDown(self): + """Stop web driver""" + self.driver.quit() diff --git a/tests/bindpat.py b/tests/bindpat.py new file mode 100644 index 00000000..6c33f52f --- /dev/null +++ b/tests/bindpat.py @@ -0,0 +1,9 @@ +import unittest +import base + +class Suite(base.Base): + def test_1(self): + """Test case 1""" + self.driver.get('http://localhost:8080/main') + el = self.driver.find_element_by_xpath('/html/body') + self.assertEqual("1, 2, hi, 2.34, 8, 9", el.text) diff --git a/tests/bindpat.ur b/tests/bindpat.ur index bca4bd41..8fd6eb39 100644 --- a/tests/bindpat.ur +++ b/tests/bindpat.ur @@ -1,6 +1,9 @@ fun main () : transaction page = (a, b) <- return (1, 2); {C = c, ...} <- return {C = "hi", D = False}; - d <- return 2.34; - {1 = e, 2 = f} <- return (8, 9); + let + val d = 2.34 + val {1 = e, 2 = f} = (8, 9) + in return <xml>{[a]}, {[b]}, {[c]}, {[d]}, {[e]}, {[f]}</xml> + end
\ No newline at end of file diff --git a/tests/driver.sh b/tests/driver.sh new file mode 100755 index 00000000..cc62644b --- /dev/null +++ b/tests/driver.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +if [[ $# -eq 0 ]] ; then + echo 'Supply at least one argument' + exit 1 +fi + +TESTDB=/tmp/$1.db +TESTSQL=/tmp/$1.sql +TESTPID=/tmp/$1.pid +TESTSRV=./$1.exe + +rm -f $TESTDB $TESTSQL $TESTPID $TESTSRV +../bin/urweb -debug -boot -noEmacs -dbms sqlite -db $TESTDB -sql $TESTSQL "$1" || exit 1 + +if [ -e $TESTSQL ] +then + sqlite3 $TESTDB < $TESTSQL +fi + +$TESTSRV -q -a 127.0.0.1 & +echo $! >> $TESTPID +sleep 1 +python -m unittest $1.py +kill `cat $TESTPID` diff --git a/tests/entities.py b/tests/entities.py new file mode 100644 index 00000000..d9087cbf --- /dev/null +++ b/tests/entities.py @@ -0,0 +1,14 @@ +import unittest +import base + +class Suite(base.Base): + def test_1(self): + """Test case 1""" + self.start() + p = self.xpath('p[1]') + self.assertEqual('Hello world! & so on, © me today (8 €)', p.text) + p = self.xpath('p[2]') + self.assertEqual('♠ ♣ ♥ ♦', p.text) + p = self.xpath('p[3]') + self.assertEqual('† DANGER †', p.text) + diff --git a/tests/entities.ur b/tests/entities.ur index 8b78edbc..1f45520d 100644 --- a/tests/entities.ur +++ b/tests/entities.ur @@ -1,5 +1,5 @@ fun main () : transaction page = return <xml><body> - Hello world! & so on, © me today (8 €)<br/> - ♠ ♣ ♥ ♦<br/> - † DANGER † + <p>Hello world! & so on, © me today (8 €)</p> + <p>♠ ♣ ♥ ♦</p> + <p>† DANGER †</p> </body></xml> diff --git a/tests/fact.py b/tests/fact.py new file mode 100644 index 00000000..3dcd6f71 --- /dev/null +++ b/tests/fact.py @@ -0,0 +1,10 @@ +import unittest +import base + +class Suite(base.Base): + def test_1(self): + """Test case 1""" + self.start() + b = self.driver.find_element_by_xpath('/html/body') + self.assertEqual('3628800, 3628800', b.text) + diff --git a/tests/filter.py b/tests/filter.py new file mode 100644 index 00000000..f68f8f88 --- /dev/null +++ b/tests/filter.py @@ -0,0 +1,9 @@ +import unittest +import base + +class Suite(base.Base): + def test_1(self): + """Test case 1""" + self.start('Filter/main') + tx = self.body_text() + self.assertEqual("4, 4; 44, 4.4;", tx) diff --git a/tests/filter.ur b/tests/filter.ur index efd326c3..2691a939 100644 --- a/tests/filter.ur +++ b/tests/filter.ur @@ -1,9 +1,16 @@ -fun filter [fs ::: {Type}] [ks] (t : sql_table fs ks) (p : sql_exp [T = fs] [] [] bool) - : sql_query [T = fs] [] = +fun filter [fs ::: {Type}] [ks] (t : sql_table fs ks) (p : sql_exp [T = fs] [] [] bool) = (SELECT * FROM t WHERE {p}) table t : { A : int, B : float } -fun main () = - queryX (filter t (WHERE t.A > 3)) - (fn r => <xml>{[r.T.A]}, {[r.T.B]}</xml>) +task initialize = fn () => + dml (INSERT INTO t (A, B) VALUES (1, 2.0)); + dml (INSERT INTO t (A, B) VALUES (2, 1.0)); + dml (INSERT INTO t (A, B) VALUES (3, 3.0)); + dml (INSERT INTO t (A, B) VALUES (4, 4.0)); + dml (INSERT INTO t (A, B) VALUES (44, 4.4)) + +fun main () : transaction page = + r <- queryX (filter t (WHERE t.A > 3)) + (fn r => <xml>{[r.T.A]}, {[r.T.B]}; </xml>); + return <xml><body>{r}</body></xml> diff --git a/tests/jsbspace.py b/tests/jsbspace.py new file mode 100644 index 00000000..b29d44b9 --- /dev/null +++ b/tests/jsbspace.py @@ -0,0 +1,11 @@ +import unittest +import base + +class Suite(base.Base): + def test_1(self): + """Test case 1""" + self.start() + el = self.xpath('button') + el.click() + alert = self.driver.switch_to.alert + self.assertEqual('Some \btext', alert.text) diff --git a/tests/jsbspace.ur b/tests/jsbspace.ur new file mode 100644 index 00000000..bf4b824f --- /dev/null +++ b/tests/jsbspace.ur @@ -0,0 +1,12 @@ +fun main () : transaction page = +let + fun onclick (): transaction unit = + (* this function runs on the client *) + alert "Some \btext" +in +return <xml> + <body> + <button onclick={fn _ => onclick()}>Click me!</button> + </body> +</xml> +end
\ No newline at end of file diff --git a/tests/jsonTest.py b/tests/jsonTest.py new file mode 100644 index 00000000..d9147511 --- /dev/null +++ b/tests/jsonTest.py @@ -0,0 +1,16 @@ +import unittest +import base + +class Suite(base.Base): + def test_1(self): + """Test case 1""" + self.start() + + pre = self.xpath('pre[1]') + self.assertEqual('line 1\nline 2', pre.text) + + pre = self.xpath('pre[2]') + self.assertEqual('1 :: 2 :: 3 :: []', pre.text) + + pre = self.xpath('pre[3]') + self.assertEqual('["hi","bye\\"","hehe"]', pre.text) diff --git a/tests/listGroupBy.ur b/tests/listGroupBy.ur new file mode 100644 index 00000000..c2419ce1 --- /dev/null +++ b/tests/listGroupBy.ur @@ -0,0 +1,13 @@ +fun lister () = List.tabulateM (fn _ => n <- rand; return (n % 100)) 8 + +fun main () : transaction page = + inp <- source []; + return <xml><body> + <button value="Compute" onclick={fn _ => + ls <- rpc (lister ()); + set inp ls}/> + + <dyn signal={inp <- signal inp; return (txt inp)}/> + -> + <dyn signal={inp <- signal inp; return (txt (List.groupBy (fn n m => n % 2 = m % 2) inp))}/> + </body></xml> diff --git a/tests/listGroupBy.urp b/tests/listGroupBy.urp new file mode 100644 index 00000000..1a63a89d --- /dev/null +++ b/tests/listGroupBy.urp @@ -0,0 +1,4 @@ +rewrite all ListGroupBy/* + +$/list +listGroupBy
\ No newline at end of file diff --git a/tests/pairUnify.ur b/tests/pairUnify.ur new file mode 100644 index 00000000..1c9f9759 --- /dev/null +++ b/tests/pairUnify.ur @@ -0,0 +1,6 @@ +datatype a = A +datatype b = B + +val x : a * b = (A, B) + +val y : b = x diff --git a/tests/unurlify2.ur b/tests/unurlify2.ur new file mode 100644 index 00000000..2e82928d --- /dev/null +++ b/tests/unurlify2.ur @@ -0,0 +1,16 @@ +datatype bugged = Nothing | Something of int +datatype myDt = One | Two +type myRecord = {Bugged: bugged + , MyDt : myDt} + +fun rpcTarget (t: myRecord) = return () + +val good = {Bugged = Something 4, MyDt = One} +val bad = {Bugged = Nothing, MyDt = One} + +fun main () : transaction page = return <xml> + <body> + <button onclick={fn _ => rpc (rpcTarget good)}>rpc with good</button> + <button onclick={fn _ => rpc (rpcTarget bad)}>rpc with bad</button> + </body> +</xml> |