From e2552a79ed87721a81c246b9cfd053701d665f25 Mon Sep 17 00:00:00 2001 From: "majorseitan@blockfreie.org" Date: Sun, 15 Apr 2018 16:20:31 -0400 Subject: Handling of JSON escape characters 1. Handle the escape character \\ --- lib/ur/json.ur | 2 ++ tests/jsonTest.ur | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/ur/json.ur b/lib/ur/json.ur index 1e3e3f39..7ebb010f 100644 --- a/lib/ur/json.ur +++ b/lib/ur/json.ur @@ -52,6 +52,7 @@ fun escape s = | #"\t" => "\\t" | #"\"" => "\\\"" | #"\'" => "\\\'" + | #"\\" => "\\\\" | x => String.str ch ) ^ esc (String.suffix s 1) end @@ -100,6 +101,7 @@ fun unescape s = | #"t" => "\t" | #"\"" => "\"" | #"\'" => "\'" + | #"\\" => "\\" | x => error JSON unescape: Bad escape char: {[x]}) ^ unesc (i+2) diff --git a/tests/jsonTest.ur b/tests/jsonTest.ur index 1be6e7b5..071cf34b 100644 --- a/tests/jsonTest.ur +++ b/tests/jsonTest.ur @@ -1,7 +1,7 @@ open Json fun main () : transaction page = return -
{[ fromJson "\"line 1\\nline 2\"" : string ]}

+
{[ fromJson "\"\\\\line 1\\nline 2\"" : string ]}

{[fromJson "[1, 2, 3]" : list int]}
{[toJson ("hi" :: "bye\"" :: "hehe" :: [])]}
-- cgit v1.2.3 From f993a516913883eda783bbe7cae80dfd42e2b428 Mon Sep 17 00:00:00 2001 From: "majorseitan@blockfreie.org" Date: Sat, 26 May 2018 12:46:56 -0400 Subject: Handling of JSON escape characters 1. Handle the escape character \/ --- lib/ur/json.ur | 2 ++ tests/jsonTest.ur | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/ur/json.ur b/lib/ur/json.ur index 7ebb010f..817ec16e 100644 --- a/lib/ur/json.ur +++ b/lib/ur/json.ur @@ -53,6 +53,7 @@ fun escape s = | #"\"" => "\\\"" | #"\'" => "\\\'" | #"\\" => "\\\\" + | #"/" => "\\/" | x => String.str ch ) ^ esc (String.suffix s 1) end @@ -102,6 +103,7 @@ fun unescape s = | #"\"" => "\"" | #"\'" => "\'" | #"\\" => "\\" + | #"/" => "/" | x => error JSON unescape: Bad escape char: {[x]}) ^ unesc (i+2) diff --git a/tests/jsonTest.ur b/tests/jsonTest.ur index 071cf34b..715e225d 100644 --- a/tests/jsonTest.ur +++ b/tests/jsonTest.ur @@ -1,7 +1,7 @@ open Json fun main () : transaction page = return -
{[ fromJson "\"\\\\line 1\\nline 2\"" : string ]}

+
{[ fromJson "\"\\\\line \/ 1\\nline 2\"" : string ]}

{[fromJson "[1, 2, 3]" : list int]}
{[toJson ("hi" :: "bye\"" :: "hehe" :: [])]}
-- cgit v1.2.3 From b4ffc6c4837e06c48a1a15ea662c25aa92566bf6 Mon Sep 17 00:00:00 2001 From: "majorseitan@blockfreie.org" Date: Sat, 26 May 2018 13:29:12 -0400 Subject: resolve merge conflict on test --- tests/jsonTest.ur | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/jsonTest.ur b/tests/jsonTest.ur index 715e225d..bce269bd 100644 --- a/tests/jsonTest.ur +++ b/tests/jsonTest.ur @@ -2,6 +2,6 @@ open Json fun main () : transaction page = return
{[ fromJson "\"\\\\line \/ 1\\nline 2\"" : string ]}

- {[fromJson "[1, 2, 3]" : list int]}
- {[toJson ("hi" :: "bye\"" :: "hehe" :: [])]} +
{[fromJson "[1, 2, 3]" : list int]}

+
{[toJson ("hi" :: "bye\"" :: "hehe" :: [])]}
-- cgit v1.2.3 From 7f6f6045c0c1cc9bd8323e3e7de905e0e46fe82d Mon Sep 17 00:00:00 2001 From: Artyom Shalkhakov Date: Mon, 28 May 2018 21:34:07 +0600 Subject: Adding: cradio (support for client-side radio box). --- lib/js/urweb.js | 13 +++++++++++++ lib/ur/basis.urs | 5 ++++- src/css.sml | 1 + src/monoize.sml | 4 +++- tests/cradio.py | 27 +++++++++++++++++++++++++++ tests/cradio.ur | 13 +++++++++++++ tests/cradio.urp | 3 +++ tests/cradio.urs | 1 + 8 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 tests/cradio.py create mode 100644 tests/cradio.ur create mode 100644 tests/cradio.urp create mode 100644 tests/cradio.urs diff --git a/lib/js/urweb.js b/lib/js/urweb.js index d8198ed0..99b45ec9 100644 --- a/lib/js/urweb.js +++ b/lib/js/urweb.js @@ -1205,6 +1205,19 @@ function time(s, name) { return inpt("time", s, name); } +function crad(s) { + if (suspendScripts) + return; + + var x = input(document.createElement("input"), s, + function(x) { return function(v) { x.checked = (x.value === v); }; }, "radio"); + x.onclick = x.onkeyup = x.oninput = x.onchange = x.onpropertychange = function() { sv(s, x.value) }; + setTimeout(function() { + x.defaultChecked = x.checked = (s.data === x.value); + }, 10); + + return x; +} function selectValue(x) { if (x.options.length == 0) diff --git a/lib/ur/basis.urs b/lib/ur/basis.urs index c354d784..6d71d00a 100644 --- a/lib/ur/basis.urs +++ b/lib/ur/basis.urs @@ -1086,10 +1086,13 @@ val button : cformTag ([Value = string, Disabled = bool] ++ boxAttrs) [] val ccheckbox : cformTag ([Size = int, Source = source bool] ++ boxAttrs ++ inputAttrs') [] +val cradio : cformTag ([Source = source (option string), Value = string] ++ boxAttrs ++ inputAttrs') [] + val cselect : cformTag ([Source = source string] ++ boxAttrs ++ inputAttrs') [Cselect] val coption : unit -> tag [Value = string, Selected = bool] [Cselect, Body] [] [] [] -val ctextarea : cformTag ([Rows = int, Cols = int, Placeholder = string, Source = source string] ++ boxAttrs ++ inputAttrs) [] +val ctextarea : cformTag ([Rows = int, Cols = int, Placeholder = string, Source = source string, + Ontext = transaction unit] ++ boxAttrs ++ inputAttrs) [] (*** Tables *) diff --git a/src/css.sml b/src/css.sml index 9e50686f..5bf4ea7b 100644 --- a/src/css.sml +++ b/src/css.sml @@ -104,6 +104,7 @@ val tags = [("span", inline), ("cpassword", replaced), ("button", replaced), ("ccheckbox", replaced), + ("cradio", replaced), ("cselect", replaced), ("ctextarea", replaced), ("tabl", table), diff --git a/src/monoize.sml b/src/monoize.sml index 85a66e87..11c6ea31 100644 --- a/src/monoize.sml +++ b/src/monoize.sml @@ -3070,7 +3070,7 @@ fun monoExp (env, st, fm) (all as (e, loc)) = | _ => (attrs, NONE) - val dynamics = ["dyn", "ctextbox", "cpassword", "ccheckbox", "cselect", "coption", "ctextarea", "active", "script", "cemail", "csearch", "curl", "ctel", "ccolor"] + val dynamics = ["dyn", "ctextbox", "cpassword", "ccheckbox", "cradio", "cselect", "coption", "ctextarea", "active", "script", "cemail", "csearch", "curl", "ctel", "ccolor"] fun isSome (e, _) = case e of @@ -3560,6 +3560,8 @@ fun monoExp (env, st, fm) (all as (e, loc)) = | "ctime" => cinput ("time", "time") | "ccheckbox" => cinput ("checkbox", "chk") + | "cradio" => cinput ("radio", "crad") + | "cselect" => (case List.find (fn ("Source", _, _) => true | _ => false) attrs of NONE => diff --git a/tests/cradio.py b/tests/cradio.py new file mode 100644 index 00000000..b70b2ef1 --- /dev/null +++ b/tests/cradio.py @@ -0,0 +1,27 @@ +import unittest +import base + +# issue: initialization doesn't quite work + +class Suite(base.Base): +# test case: +# initially the source is EMPTY +# then we pick SECOND variant and check the source +# then we pick the FIRST variant and check the source + def test_1(self): + """Test case 1""" + self.start("Cradio/main") + txt = self.body_text() + self.assertEqual("Wilbur Walbur Hello, I'm B. I'll be your waiter for this evening.", txt) + el1 = self.xpath('label[1]/input') + el2 = self.xpath('label[2]/input') + self.assertEqual(False, el1.is_selected()) + self.assertEqual(True, el2.is_selected()) + el1.click() + alert = self.driver.switch_to.alert + self.assertEqual("Now it's A", alert.text) + alert.accept() + self.assertEqual(True, el1.is_selected()) + self.assertEqual(False, el2.is_selected()) + txt = self.body_text() + self.assertEqual("Wilbur Walbur Hello, I'm A. I'll be your waiter for this evening.", txt) diff --git a/tests/cradio.ur b/tests/cradio.ur new file mode 100644 index 00000000..5b6e9d22 --- /dev/null +++ b/tests/cradio.ur @@ -0,0 +1,13 @@ +fun main () = +s <- source (Some "B"); +let + val onc = v <- get s; alert ("Now it's " ^ show v) +in + return + + + + Hello, I'm {[s]}}/>. + I'll be your waiter for this evening. + +end diff --git a/tests/cradio.urp b/tests/cradio.urp new file mode 100644 index 00000000..0681ab21 --- /dev/null +++ b/tests/cradio.urp @@ -0,0 +1,3 @@ +debug + +cradio diff --git a/tests/cradio.urs b/tests/cradio.urs new file mode 100644 index 00000000..6ac44e0b --- /dev/null +++ b/tests/cradio.urs @@ -0,0 +1 @@ +val main : unit -> transaction page -- cgit v1.2.3 From 6fc9746d0cc8f18cc570647b8e571a34c5aeb0fe Mon Sep 17 00:00:00 2001 From: Artyom Shalkhakov Date: Mon, 28 May 2018 21:39:46 +0600 Subject: Formatting --- src/css.sml | 2 +- tests/cradio.py | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/css.sml b/src/css.sml index 5bf4ea7b..17ec01d5 100644 --- a/src/css.sml +++ b/src/css.sml @@ -104,7 +104,7 @@ val tags = [("span", inline), ("cpassword", replaced), ("button", replaced), ("ccheckbox", replaced), - ("cradio", replaced), + ("cradio", replaced), ("cselect", replaced), ("ctextarea", replaced), ("tabl", table), diff --git a/tests/cradio.py b/tests/cradio.py index b70b2ef1..acc8dc11 100644 --- a/tests/cradio.py +++ b/tests/cradio.py @@ -1,13 +1,7 @@ import unittest import base -# issue: initialization doesn't quite work - class Suite(base.Base): -# test case: -# initially the source is EMPTY -# then we pick SECOND variant and check the source -# then we pick the FIRST variant and check the source def test_1(self): """Test case 1""" self.start("Cradio/main") -- cgit v1.2.3 From 4bf7bfd52e5e822b05665b1872a2cfd31417486d Mon Sep 17 00:00:00 2001 From: Artyom Shalkhakov Date: Wed, 30 May 2018 20:26:06 +0600 Subject: Multi-group test --- tests/cradio.py | 20 ++++++++++++++++---- tests/cradio.ur | 17 +++++++++++++++-- tests/driver.sh | 2 +- 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/tests/cradio.py b/tests/cradio.py index acc8dc11..cc075593 100644 --- a/tests/cradio.py +++ b/tests/cradio.py @@ -5,8 +5,10 @@ class Suite(base.Base): def test_1(self): """Test case 1""" self.start("Cradio/main") - txt = self.body_text() - self.assertEqual("Wilbur Walbur Hello, I'm B. I'll be your waiter for this evening.", txt) + txt = self.xpath('div[1]').text + self.assertEqual("Hello, I'm B. I'll be your waiter for this evening.", txt) + txt2 = self.xpath('div[2]').text + self.assertEqual('Value:', txt2) el1 = self.xpath('label[1]/input') el2 = self.xpath('label[2]/input') self.assertEqual(False, el1.is_selected()) @@ -17,5 +19,15 @@ class Suite(base.Base): alert.accept() self.assertEqual(True, el1.is_selected()) self.assertEqual(False, el2.is_selected()) - txt = self.body_text() - self.assertEqual("Wilbur Walbur Hello, I'm A. I'll be your waiter for this evening.", txt) + txt = self.xpath('div[1]').text + self.assertEqual("Hello, I'm A. I'll be your waiter for this evening.", txt) + txt2 = self.xpath('div[2]').text + self.assertEqual('Value:', txt2) + # now check that the second radio group works as well + el3 = self.xpath('label[4]/input') + el3.click() + alert = self.driver.switch_to.alert + alert.accept() + txt2 = self.xpath('div[2]').text + self.assertEqual('Value: Y', txt2) + self.assertEqual("Hello, I'm A. I'll be your waiter for this evening.", txt) diff --git a/tests/cradio.ur b/tests/cradio.ur index 5b6e9d22..48c04f1e 100644 --- a/tests/cradio.ur +++ b/tests/cradio.ur @@ -1,13 +1,26 @@ fun main () = s <- source (Some "B"); +r <- source None; let val onc = v <- get s; alert ("Now it's " ^ show v) + val onc_r = v <- get r; alert ("Changed to " ^ show v) in return +

First group

+ - Hello, I'm {[s]}
}/>. - I'll be your waiter for this evening. +
+ Hello, I'm {[s]}}/>. I'll be your waiter for this evening. +
+ +

Second group

+ + + + + +
Value: {[r]}}/>
end diff --git a/tests/driver.sh b/tests/driver.sh index cc62644b..879c093d 100755 --- a/tests/driver.sh +++ b/tests/driver.sh @@ -21,5 +21,5 @@ fi $TESTSRV -q -a 127.0.0.1 & echo $! >> $TESTPID sleep 1 -python -m unittest $1.py +python3 -m unittest $1.py kill `cat $TESTPID` -- cgit v1.2.3