Tests various widgets in package github.com/janpfeifer/gonb/gonbui/widgets
.
%goflags --cover --covermode=set
%goflags=["--cover" "--covermode=set"]
!if [[ "${GONB_GIT_ROOT}" == "" ]] ; then \
echo "Please set GONB_GIT_ROOT before runnig this notebook!" 1>&2 ; \
else \
echo "ok" ; \
fi
ok
!*rm -f go.work && go work init && go work use . "${GONB_GIT_ROOT}"
%goworkfix
- Added replace rule for module "github.com/janpfeifer/gonb" to local directory "/home/janpf/Projects/gonb".
Create a button and induce a click on it using Javacript. It should print out "ok" if the button was clicked or "error" if it times out.
Notice to avoid the race condition of the button being clicked before we start listening to it, we add a buffer of 1 to the channel.
We also create a transient div, and append the button there -- making the button not appear after it is saved.
No real need for that, other than to also test the AppendTo
method.
import (
"github.com/janpfeifer/gonb/gonbui"
"github.com/janpfeifer/gonb/gonbui/dom"
"github.com/janpfeifer/gonb/gonbui/widgets"
)
%%
// Setting these 3 values below are not needed, we just do it to test they work.
htmlId := "gonb_widget_test_" + gonbui.UniqueId()
rootId := dom.CreateTransientDiv()
address := "widget/" + gonbui.UniqueId()
w := widgets.Button("Ok").
WithAddress(address).WithHtmlId(htmlId).AppendTo(rootId).Done()
wChan := w.Listen().WithBuffer(1)
if w.HtmlId() != htmlId {
fmt.Println("error: wrong htmlId")
return
}
if w.Address() != address {
fmt.Println("error: wrong address")
return
}
// Click on button with Javascript after 100ms.
go func() {
time.Sleep(100 * time.Millisecond);
dom.TransientJavascript(fmt.Sprintf(`
(() => {
let button = document.getElementById("%s");
button.click();
console.log("Clicked!");
})();
`, w.HtmlId()))
}()
// Wait for button click or timeout.
select {
case <-wChan.C:
fmt.Println("clicked")
case <-time.After(500 * time.Millisecond):
fmt.Println("error")
}
wChan.Close()
clicked
We create a slider, and then interact with it with Javascript and test we get the correct reading.
%%
const answer = 42
// Setting these 3 values below are not needed, we just do it to test they work.
htmlId := "gonb_widget_test_" + gonbui.UniqueId()
rootId := dom.CreateTransientDiv()
address := "widget/" + gonbui.UniqueId()
w := widgets.Slider(0, 100, 50).
WithAddress(address).WithHtmlId(htmlId).AppendTo(rootId).Done()
wChan := w.Listen().WithBuffer(1)
if w.HtmlId() != htmlId {
fmt.Println("error: wrong htmlId")
return
}
if w.Address() != address {
fmt.Println("error: wrong address")
return
}
go func() {
time.Sleep(100 * time.Millisecond);
dom.TransientJavascript(fmt.Sprintf(`
(() => {
let el = document.getElementById("%s");
const answer = %d;
el.value = answer; // Doesn't trigger "change" event, unfortunately.
el.dispatchEvent(new Event("change"));
console.log("Select set to "+answer);
})();
`, w.HtmlId(), answer))
}()
// Wait for slider change or timeout.
select {
case newValue := <-wChan.C:
time.Sleep(100 * time.Millisecond) // Make sure slider also received the update.
// Checks we receive the new value, and that the slider object also recorded it.
if newValue != answer || w.Value() != answer {
fmt.Printf("error: received %d, widget registered %d", newValue, w.Value())
return
}
case <-time.After(500 * time.Millisecond):
fmt.Println("error: change timedout")
return
}
// SetValue and get it reflected back.
w.SetValue(answer+1)
time.Sleep(100 * time.Millisecond)
dom.TransientJavascript(fmt.Sprintf(`
(() => {
let el = document.getElementById("%s");
let gonb_comm = globalThis.gonb_comm;
gonb_comm.send("%s", el.value)
})();
`, w.HtmlId(), w.Address()))
time.Sleep(100 * time.Millisecond)
select {
case newValue := <-wChan.C:
if newValue != answer+1 || w.Value() != answer+1 {
fmt.Printf("error with SetValue: received %d, widget registered %d", newValue, w.Value())
return
}
case <-time.After(5000 * time.Millisecond):
fmt.Println("error: SetValue timedout")
return
}
fmt.Println("widget tested ok")
wChan.Close()
widget tested ok
We create a <select>
element, and then interact with it with Javascript and test we get the correct reading.
%%
const answer = 3
// Setting these 3 values below are not needed, we just do it to test they work.
htmlId := "gonb_widget_test_" + gonbui.UniqueId()
rootId := dom.CreateTransientDiv()
address := "widget/" + gonbui.UniqueId()
options := []string{"ab", "cd", "ef", "xy", "z"}
w := widgets.Select(options).
WithAddress(address).WithHtmlId(htmlId).AppendTo(rootId).Done()
wChan := w.Listen().WithBuffer(1)
if w.HtmlId() != htmlId {
fmt.Println("error: wrong htmlId")
return
}
if w.Address() != address {
fmt.Println("error: wrong address")
return
}
go func() {
time.Sleep(100 * time.Millisecond);
dom.TransientJavascript(fmt.Sprintf(`
(() => {
let el = document.getElementById("%s");
const answer = %d;
el.value = answer; // Doesn't trigger "change" event, unfortunately.
el.dispatchEvent(new Event("change"));
console.log("Select set to "+answer);
})();
`, w.HtmlId(), answer))
}()
// Wait for slider change or timeout.
select {
case newValue := <-wChan.C:
time.Sleep(100 * time.Millisecond) // Make sure slider also received the update.
// Checks we receive the new value, and that the slider object also recorded it.
if newValue != answer || w.Value() != answer {
fmt.Printf("error: received %d, widget registered %d", newValue, w.Value())
return
}
case <-time.After(500 * time.Millisecond):
fmt.Println("error: change timedout")
return
}
// SetValue and get it reflected back.
w.SetValue(answer+1)
time.Sleep(100 * time.Millisecond)
dom.TransientJavascript(fmt.Sprintf(`
(() => {
let el = document.getElementById("%s");
let gonb_comm = globalThis.gonb_comm;
gonb_comm.send("%s", el.value)
})();
`, w.HtmlId(), w.Address()))
time.Sleep(100 * time.Millisecond)
select {
case newValue := <-wChan.C:
if newValue != answer+1 || w.Value() != answer+1 {
fmt.Printf("error with SetValue: received %d, widget registered %d", newValue, w.Value())
return
}
case <-time.After(5000 * time.Millisecond):
fmt.Println("error: SetValue timedout")
return
}
fmt.Println("widget tested ok")
wChan.Close()
widget tested ok