~repos /gromer

#golang#htmx#ssr

git clone https://pyrossh.dev/repos/gromer.git

gromer is a framework and cli to build multipage web apps in golang using htmx and alpinejs.


b327ed96 pyros2097

5 years ago
remove filterUI elements
Files changed (10) hide show
  1. app_nowasm.go +1 -2
  2. attributes.go +2 -2
  3. attributes_test.go +1 -1
  4. component.go +1 -3
  5. element.go +2 -3
  6. html.go +87 -2
  7. node.go +0 -32
  8. node_test.go +0 -13
  9. selectors.go +0 -109
  10. selectors_test.go +0 -263
app_nowasm.go CHANGED
@@ -75,7 +75,6 @@ func createPage(ui UI) *bytes.Buffer {
75
75
  isLambda := os.Getenv("_LAMBDA_SERVER_PORT") != ""
76
76
  page := bytes.NewBuffer(nil)
77
77
  page.WriteString("<!DOCTYPE html>\n")
78
- elems := FilterUIElems(ui)
79
78
  basePath := "/assets/"
80
79
  if isLambda {
81
80
  basePath = "https://go-app-bucket-111.s3.amazonaws.com/"
@@ -92,7 +91,7 @@ func createPage(ui UI) *bytes.Buffer {
92
91
  Link("stylesheet", basePath+"styles.css"),
93
92
  Script(`const enosys = () => { const a = new Error("not implemented"); return a.code = "ENOSYS", a }; let outputBuf = ""; window.fs = { constants: { O_WRONLY: -1, O_RDWR: -1, O_CREAT: -1, O_TRUNC: -1, O_APPEND: -1, O_EXCL: -1 }, writeSync(a, b) { outputBuf += decoder.decode(b); const c = outputBuf.lastIndexOf("\n"); return -1 != c && (console.log(outputBuf.substr(0, c)), outputBuf = outputBuf.substr(c + 1)), b.length }, write(a, b, c, d, e, f) { if (0 !== c || d !== b.length || null !== e) return void f(enosys()); const g = this.writeSync(a, b); f(null, g) } }; const encoder = new TextEncoder("utf-8"), decoder = new TextDecoder("utf-8"); class Go { constructor() { this.argv = ["js"], this.env = {}, this.exit = a => { 0 !== a && console.warn("exit code:", a) }, this._exitPromise = new Promise(a => { this._resolveExitPromise = a }), this._pendingEvent = null, this._scheduledTimeouts = new Map, this._nextCallbackTimeoutID = 1; const a = (a, b) => { this.mem.setUint32(a + 0, b, !0), this.mem.setUint32(a + 4, Math.floor(b / 4294967296), !0) }, b = a => { const b = this.mem.getUint32(a + 0, !0), c = this.mem.getInt32(a + 4, !0); return b + 4294967296 * c }, c = a => { const b = this.mem.getFloat64(a, !0); if (0 !== b) { if (!isNaN(b)) return b; const c = this.mem.getUint32(a, !0); return this._values[c] } }, d = (a, b) => { const c = 2146959360; if ("number" == typeof b) return isNaN(b) ? (this.mem.setUint32(a + 4, 2146959360, !0), void this.mem.setUint32(a, 0, !0)) : 0 === b ? (this.mem.setUint32(a + 4, 2146959360, !0), void this.mem.setUint32(a, 1, !0)) : void this.mem.setFloat64(a, b, !0); switch (b) { case void 0: return void this.mem.setFloat64(a, 0, !0); case null: return this.mem.setUint32(a + 4, c, !0), void this.mem.setUint32(a, 2, !0); case !0: return this.mem.setUint32(a + 4, c, !0), void this.mem.setUint32(a, 3, !0); case !1: return this.mem.setUint32(a + 4, c, !0), void this.mem.setUint32(a, 4, !0); }let d = this._ids.get(b); d === void 0 && (d = this._idPool.pop(), d === void 0 && (d = this._values.length), this._values[d] = b, this._goRefCounts[d] = 0, this._ids.set(b, d)), this._goRefCounts[d]++; let e = 1; switch (typeof b) { case "string": e = 2; break; case "symbol": e = 3; break; case "function": e = 4; }this.mem.setUint32(a + 4, 2146959360 | e, !0), this.mem.setUint32(a, d, !0) }, e = a => { const c = b(a + 0), d = b(a + 8); return new Uint8Array(this._inst.exports.mem.buffer, c, d) }, f = d => { const e = b(d + 0), f = b(d + 8), g = Array(f); for (let a = 0; a < f; a++)g[a] = c(e + 8 * a); return g }, g = a => { const c = b(a + 0), d = b(a + 8); return decoder.decode(new DataView(this._inst.exports.mem.buffer, c, d)) }, h = Date.now() - performance.now(); this.importObject = { go: { "runtime.wasmExit": a => { const b = this.mem.getInt32(a + 8, !0); this.exited = !0, delete this._inst, delete this._values, delete this._goRefCounts, delete this._ids, delete this._idPool, this.exit(b) }, "runtime.wasmWrite": a => { const c = b(a + 8), d = b(a + 16), e = this.mem.getInt32(a + 24, !0); fs.writeSync(c, new Uint8Array(this._inst.exports.mem.buffer, d, e)) }, "runtime.resetMemoryDataView": () => { this.mem = new DataView(this._inst.exports.mem.buffer) }, "runtime.nanotime1": b => { a(b + 8, 1e6 * (h + performance.now())) }, "runtime.walltime1": b => { const c = new Date().getTime(); a(b + 8, c / 1e3), this.mem.setInt32(b + 16, 1e6 * (c % 1e3), !0) }, "runtime.scheduleTimeoutEvent": a => { const c = this._nextCallbackTimeoutID; this._nextCallbackTimeoutID++, this._scheduledTimeouts.set(c, setTimeout(() => { for (this._resume(); this._scheduledTimeouts.has(c);)console.warn("scheduleTimeoutEvent: missed timeout event"), this._resume() }, b(a + 8) + 1)), this.mem.setInt32(a + 16, c, !0) }, "runtime.clearTimeoutEvent": a => { const b = this.mem.getInt32(a + 8, !0); clearTimeout(this._scheduledTimeouts.get(b)), this._scheduledTimeouts.delete(b) }, "runtime.getRandomData": a => { crypto.getRandomValues(e(a + 8)) }, "syscall/js.finalizeRef": a => { const b = this.mem.getUint32(a + 8, !0); if (this._goRefCounts[b]--, 0 === this._goRefCounts[b]) { const a = this._values[b]; this._values[b] = null, this._ids.delete(a), this._idPool.push(b) } }, "syscall/js.stringVal": a => { d(a + 24, g(a + 8)) }, "syscall/js.valueGet": a => { const b = Reflect.get(c(a + 8), g(a + 16)); a = this._inst.exports.getsp(), d(a + 32, b) }, "syscall/js.valueSet": a => { Reflect.set(c(a + 8), g(a + 16), c(a + 32)) }, "syscall/js.valueDelete": a => { Reflect.deleteProperty(c(a + 8), g(a + 16)) }, "syscall/js.valueIndex": a => { d(a + 24, Reflect.get(c(a + 8), b(a + 16))) }, "syscall/js.valueSetIndex": a => { Reflect.set(c(a + 8), b(a + 16), c(a + 24)) }, "syscall/js.valueCall": a => { try { const b = c(a + 8), e = Reflect.get(b, g(a + 16)), h = f(a + 32), i = Reflect.apply(e, b, h); a = this._inst.exports.getsp(), d(a + 56, i), this.mem.setUint8(a + 64, 1) } catch (b) { d(a + 56, b), this.mem.setUint8(a + 64, 0) } }, "syscall/js.valueInvoke": a => { try { const b = c(a + 8), e = f(a + 16), g = Reflect.apply(b, void 0, e); a = this._inst.exports.getsp(), d(a + 40, g), this.mem.setUint8(a + 48, 1) } catch (b) { d(a + 40, b), this.mem.setUint8(a + 48, 0) } }, "syscall/js.valueNew": a => { try { const b = c(a + 8), e = f(a + 16), g = Reflect.construct(b, e); a = this._inst.exports.getsp(), d(a + 40, g), this.mem.setUint8(a + 48, 1) } catch (b) { d(a + 40, b), this.mem.setUint8(a + 48, 0) } }, "syscall/js.valueLength": b => { a(b + 16, parseInt(c(b + 8).length)) }, "syscall/js.valuePrepareString": b => { const e = encoder.encode(c(b + 8) + ""); d(b + 16, e), a(b + 24, e.length) }, "syscall/js.valueLoadString": a => { const b = c(a + 8); e(a + 16).set(b) }, "syscall/js.valueInstanceOf": a => { this.mem.setUint8(a + 24, c(a + 8) instanceof c(a + 16)) }, "syscall/js.copyBytesToGo": b => { const d = e(b + 8), f = c(b + 32); if (!(f instanceof Uint8Array)) return void this.mem.setUint8(b + 48, 0); const g = f.subarray(0, d.length); d.set(g), a(b + 40, g.length), this.mem.setUint8(b + 48, 1) }, "syscall/js.copyBytesToJS": b => { const d = c(b + 8), f = e(b + 16); if (!(d instanceof Uint8Array)) return void this.mem.setUint8(b + 48, 0); const g = f.subarray(0, d.length); d.set(g), a(b + 40, g.length), this.mem.setUint8(b + 48, 1) }, debug: a => { console.log(a) } } } } async run(a) { this._inst = a, this.mem = new DataView(this._inst.exports.mem.buffer), this._values = [NaN, 0, null, !0, !1, window, this], this._goRefCounts = [], this._ids = new Map, this._idPool = [], this.exited = !1; let b = 4096; const c = a => { const c = b, d = encoder.encode(a + "\0"); return new Uint8Array(this.mem.buffer, b, d.length).set(d), b += d.length, 0 != b % 8 && (b += 8 - b % 8), c }, d = this.argv.length, e = []; this.argv.forEach(a => { e.push(c(a)) }), e.push(0); const f = Object.keys(this.env).sort(); f.forEach(a => { e.push(c(a + "=" + this.env[a])) }), e.push(0); const g = b; e.forEach(a => { this.mem.setUint32(b, a, !0), this.mem.setUint32(b + 4, 0, !0), b += 8 }), this._inst.exports.run(d, g), this.exited && this._resolveExitPromise(), await this._exitPromise } _resume() { if (this.exited) throw new Error("Go program has already exited"); this._inst.exports.resume(), this.exited && this._resolveExitPromise() } _makeFuncWrapper(a) { const b = this; return function () { const c = { id: a, this: this, args: arguments }; return b._pendingEvent = c, b._resume(), c.result } } } const go = new Go; WebAssembly.instantiateStreaming(fetch("`+basePath+`main.wasm`+`"), go.importObject).then(a => go.run(a.instance)).catch(a => console.error("could not load wasm", a));`),
94
93
  ),
95
- Body(elems[0]),
94
+ Body(ui),
96
95
  ).Html(page)
97
96
  return page
98
97
  }
attributes.go CHANGED
@@ -42,7 +42,7 @@ type HelmetAuthor string
42
42
  type HelmetKeywords string
43
43
 
44
44
  func mergeAttributes(parent *elem, uis ...interface{}) {
45
- elems := []interface{}{}
45
+ elems := []UI{}
46
46
  for _, v := range uis {
47
47
  switch c := v.(type) {
48
48
  case CssAttribute:
@@ -73,5 +73,5 @@ func mergeAttributes(parent *elem, uis ...interface{}) {
73
73
  panic("unknown type in render")
74
74
  }
75
75
  }
76
- parent.setBody(elems...)
76
+ parent.setBody(elems)
77
77
  }
attributes_test.go CHANGED
@@ -44,5 +44,5 @@ func TestCreatePage(t *testing.T) {
44
44
  ),
45
45
  Body(HomeRoute(NewRenderContext())),
46
46
  ).Html(page)
47
- assert.Equal(t, "<!DOCTYPE html>\n<html>\n <head>\n <meta charset=\"UTF-8\">\n <meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\">\n <meta http-equiv=\"encoding\" content=\"utf-8\">\n <title>\n Title\n </title>\n </head>\n <body>\n <div>\n <div></div>\n <div class=\"flex flex-col justify-center align-items-center\">\n <div class=\"flex flex-row justify-center align-items-center yellow\">\n Counter\n </div>\n <div class=\"flex flex-row justify-center align-items-center\">\n <div>\n -\n </div>\n <div>\n 0\n </div>\n <div>\n +\n </div>\n </div>\n </div>\n </div>\n </body>\n</html>", page.String())
47
+ assert.Equal(t, "<!DOCTYPE html>\n<html>\n <head>\n <meta charset=\"UTF-8\">\n <meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\">\n <meta http-equiv=\"encoding\" content=\"utf-8\">\n <title>\n Title\n </title>\n </head>\n <body>\n <div>\n <div></div>\n <div class=\"flex flex-col justify-center items-center\">\n <div class=\"flex flex-row justify-center items-center yellow\">\n Counter\n </div>\n <div class=\"flex flex-row justify-center items-center\">\n <div>\n -\n </div>\n <div>\n 0\n </div>\n <div>\n +\n </div>\n </div>\n </div>\n </div>\n </body>\n</html>", page.String())
48
48
  }
component.go CHANGED
@@ -32,8 +32,7 @@ func (r RenderFunc) Render() UI {
32
32
  c.index = 0
33
33
  c.eindex = 0
34
34
  println("render")
35
- elems := FilterUIElems(r(c))
36
- return elems[0]
35
+ return r(c)
37
36
  }
38
37
 
39
38
  func (r RenderFunc) Update() {
@@ -42,7 +41,6 @@ func (r RenderFunc) Update() {
42
41
  return
43
42
  }
44
43
  println("update")
45
-
46
44
  if err := r.updateRoot(); err != nil {
47
45
  panic(err)
48
46
  }
element.go CHANGED
@@ -318,12 +318,11 @@ func (e *elem) delJsEventHandler(k string, h js.EventHandler) {
318
318
  delete(e.events, k)
319
319
  }
320
320
 
321
- func (e *elem) setBody(body ...interface{}) {
321
+ func (e *elem) setBody(body []UI) {
322
322
  if e.selfClosing {
323
323
  panic("setting html element body failed: self closing element can't have children" + e.name())
324
324
  }
325
-
326
- e.body = FilterUIElems(body...)
325
+ e.body = body
327
326
  }
328
327
 
329
328
  func (e *elem) Html(w io.Writer) {
html.go CHANGED
@@ -1,5 +1,7 @@
1
1
  package app
2
2
 
3
+ import "reflect"
4
+
3
5
  func Html(elems ...UI) *elem {
4
6
  return &elem{tag: "html", body: elems}
5
7
  }
@@ -55,9 +57,92 @@ func Div(uis ...interface{}) *elem {
55
57
  }
56
58
 
57
59
  func Row(uis ...interface{}) UI {
58
- return Div(append([]interface{}{Css("flex flex-row justify-center align-items-center")}, uis...)...)
60
+ return Div(append([]interface{}{Css("flex flex-row justify-center items-center")}, uis...)...)
59
61
  }
60
62
 
61
63
  func Col(uis ...interface{}) UI {
62
- return Div(append([]interface{}{Css("flex flex-col justify-center align-items-center")}, uis...)...)
64
+ return Div(append([]interface{}{Css("flex flex-col justify-center items-center")}, uis...)...)
65
+ }
66
+
67
+ func If(expr bool, a UI, b UI) UI {
68
+ if expr {
69
+ return a
70
+ }
71
+ return nil
72
+ }
73
+
74
+ func IfElse(expr bool, a UI, b UI) UI {
75
+ if expr {
76
+ return a
77
+ }
78
+ return b
79
+ }
80
+
81
+ func Map(source interface{}, f func(i int) UI) []UI {
82
+ src := reflect.ValueOf(source)
83
+ if src.Kind() != reflect.Slice {
84
+ panic("range loop source is not a slice: " + src.Type().String())
85
+ }
86
+ body := make([]UI, 0, src.Len())
87
+ for i := 0; i < src.Len(); i++ {
88
+ body = append(body, f(i))
89
+ }
90
+ return body
91
+ }
92
+
93
+ func Map2(source interface{}, f func(v interface{}, i int) UI) []UI {
94
+ src := reflect.ValueOf(source)
95
+ if src.Kind() != reflect.Slice {
96
+ panic("range loop source is not a slice: " + src.Type().String())
97
+ }
98
+ body := make([]UI, 0, src.Len())
99
+ for i := 0; i < src.Len(); i++ {
100
+ body = append(body, f(src.Index(i), i))
101
+ }
102
+ return body
63
103
  }
104
+
105
+ // func (r RangeLoop) Slice(f func(int) UI) RangeLoop {
106
+ // src := reflect.ValueOf(r.source)
107
+ // if src.Kind() != reflect.Slice && src.Kind() != reflect.Array {
108
+ // panic("range loop source is not a slice or array: " + src.Type().String())
109
+ // }
110
+
111
+ // body := make([]UI, 0, src.Len())
112
+ // for i := 0; i < src.Len(); i++ {
113
+ // body = append(body, FilterUIElems(f(i))...)
114
+ // }
115
+
116
+ // r.body = body
117
+ // return r
118
+ // }
119
+
120
+ // // Map sets the loop content by repeating the given function for the number
121
+ // // of elements in the source. Elements are ordered by keys.
122
+ // //
123
+ // // It panics if the range source is not a map or if map keys are not strings.
124
+ // func (r RangeLoop) Map(f func(string) UI) RangeLoop {
125
+ // src := reflect.ValueOf(r.source)
126
+ // if src.Kind() != reflect.Map {
127
+ // panic("range loop source is not a map: " + src.Type().String())
128
+ // }
129
+
130
+ // if keyType := src.Type().Key(); keyType.Kind() != reflect.String {
131
+ // panic("range loop source keys are not strings: " + src.Type().String() + keyType.String())
132
+ // }
133
+
134
+ // body := make([]UI, 0, src.Len())
135
+ // keys := make([]string, 0, src.Len())
136
+
137
+ // for _, k := range src.MapKeys() {
138
+ // keys = append(keys, k.String())
139
+ // }
140
+ // sort.Strings(keys)
141
+
142
+ // for _, k := range keys {
143
+ // body = append(body, FilterUIElems(f(k))...)
144
+ // }
145
+
146
+ // r.body = body
147
+ // return r
148
+ // }
node.go CHANGED
@@ -2,7 +2,6 @@ package app
2
2
 
3
3
  import (
4
4
  "io"
5
- "reflect"
6
5
 
7
6
  "github.com/pyros2097/wapp/errors"
8
7
  "github.com/pyros2097/wapp/js"
@@ -30,37 +29,6 @@ type UI interface {
30
29
  update(UI) error
31
30
  }
32
31
 
33
- // FilterUIElems returns a filtered version of the given UI elements where
34
- // selector elements such as If and Range are interpreted and removed. It also
35
- // remove nil elements.
36
- //
37
- // It should be used only when implementing components that can accept content
38
- // with variadic arguments like HTML elements Body method.
39
- func FilterUIElems(uis ...interface{}) []UI {
40
- if len(uis) == 0 {
41
- return nil
42
- }
43
-
44
- elems := make([]UI, 0, len(uis))
45
-
46
- for _, n := range uis {
47
- if v := reflect.ValueOf(n); n == nil ||
48
- v.Kind() == reflect.Ptr && v.IsNil() {
49
- continue
50
- }
51
- switch c := n.(type) {
52
- case RangeLoop:
53
- elems = append(elems, c.body...)
54
- case Condition:
55
- elems = append(elems, c.body...)
56
- default:
57
- elems = append(elems, c.(UI))
58
- }
59
- }
60
-
61
- return elems
62
- }
63
-
64
32
  func trackMousePosition(e js.Event) {
65
33
  x := e.Get("clientX")
66
34
  if !x.Truthy() {
node_test.go CHANGED
@@ -8,19 +8,6 @@ import (
8
8
  "github.com/stretchr/testify/require"
9
9
  )
10
10
 
11
- func TestFilterUIElems(t *testing.T) {
12
- var nilText *text
13
-
14
- simpleText := Text("hello")
15
-
16
- expectedResult := []UI{
17
- simpleText,
18
- }
19
-
20
- res := FilterUIElems(nil, nilText, simpleText)
21
- require.Equal(t, expectedResult, res)
22
- }
23
-
24
11
  func TestIsErrReplace(t *testing.T) {
25
12
  utests := []struct {
26
13
  scenario string
selectors.go DELETED
@@ -1,109 +0,0 @@
1
- package app
2
-
3
- import (
4
- "reflect"
5
- "sort"
6
- )
7
-
8
- // Range returns a range loop that iterates within the given source. Source must
9
- // be a slice, an array or a map with strings as keys.
10
- func Range(src interface{}) RangeLoop {
11
- return RangeLoop{source: src}
12
- }
13
-
14
- // RangeLoop represents a control structure that iterates within a slice, an
15
- // array or a map.
16
- type RangeLoop struct {
17
- body []UI
18
- source interface{}
19
- }
20
-
21
- // Slice sets the loop content by repeating the given function for the
22
- // number of elements in the source.
23
- //
24
- // It panics if the range source is not a slice or an array.
25
- func (r RangeLoop) Slice(f func(int) UI) RangeLoop {
26
- src := reflect.ValueOf(r.source)
27
- if src.Kind() != reflect.Slice && src.Kind() != reflect.Array {
28
- panic("range loop source is not a slice or array: " + src.Type().String())
29
- }
30
-
31
- body := make([]UI, 0, src.Len())
32
- for i := 0; i < src.Len(); i++ {
33
- body = append(body, FilterUIElems(f(i))...)
34
- }
35
-
36
- r.body = body
37
- return r
38
- }
39
-
40
- // Map sets the loop content by repeating the given function for the number
41
- // of elements in the source. Elements are ordered by keys.
42
- //
43
- // It panics if the range source is not a map or if map keys are not strings.
44
- func (r RangeLoop) Map(f func(string) UI) RangeLoop {
45
- src := reflect.ValueOf(r.source)
46
- if src.Kind() != reflect.Map {
47
- panic("range loop source is not a map: " + src.Type().String())
48
- }
49
-
50
- if keyType := src.Type().Key(); keyType.Kind() != reflect.String {
51
- panic("range loop source keys are not strings: " + src.Type().String() + keyType.String())
52
- }
53
-
54
- body := make([]UI, 0, src.Len())
55
- keys := make([]string, 0, src.Len())
56
-
57
- for _, k := range src.MapKeys() {
58
- keys = append(keys, k.String())
59
- }
60
- sort.Strings(keys)
61
-
62
- for _, k := range keys {
63
- body = append(body, FilterUIElems(f(k))...)
64
- }
65
-
66
- r.body = body
67
- return r
68
- }
69
-
70
- // If returns a condition that filters the given elements according to the given
71
- // expression.
72
- func If(expr bool, elems ...interface{}) Condition {
73
- if !expr {
74
- elems = nil
75
- }
76
-
77
- return Condition{
78
- body: FilterUIElems(elems...),
79
- satisfied: expr,
80
- }
81
- }
82
-
83
- // Condition represents a control structure that displays nodes depending on a
84
- // given expression.
85
- type Condition struct {
86
- body []UI
87
- satisfied bool
88
- }
89
-
90
- // ElseIf sets the condition with the given nodes if previous expressions
91
- // were not met and given expression is true.
92
- func (c Condition) ElseIf(expr bool, elems ...interface{}) Condition {
93
- if c.satisfied {
94
- return c
95
- }
96
-
97
- if expr {
98
- c.body = FilterUIElems(elems...)
99
- c.satisfied = expr
100
- }
101
-
102
- return c
103
- }
104
-
105
- // Else sets the condition with the given UI elements if previous
106
- // expressions were not met.
107
- func (c Condition) Else(elems ...interface{}) Condition {
108
- return c.ElseIf(true, elems...)
109
- }
selectors_test.go DELETED
@@ -1,263 +0,0 @@
1
- package app
2
-
3
- // import "testing"
4
-
5
- // func TestRange(t *testing.T) {
6
- // testUpdate(t, []updateTest{
7
- // {
8
- // scenario: "range slice is updated",
9
- // a: Div().Body(
10
- // Range([]string{"hello", "world"}).Slice(func(i int) UI {
11
- // src := []string{"hello", "world"}
12
- // return Text(src[i])
13
- // }),
14
- // ),
15
- // b: Div().Body(
16
- // Range([]string{"hello", "maxoo"}).Slice(func(i int) UI {
17
- // src := []string{"hello", "maxoo"}
18
- // return Text(src[i])
19
- // }),
20
- // ),
21
- // matches: []TestUIDescriptor{
22
- // {
23
- // Path: TestPath(),
24
- // Expected: Div(),
25
- // },
26
- // {
27
- // Path: TestPath(0),
28
- // Expected: Text("hello"),
29
- // },
30
- // {
31
- // Path: TestPath(1),
32
- // Expected: Text("maxoo"),
33
- // },
34
- // },
35
- // },
36
- // {
37
- // scenario: "range slice is updated to be empty",
38
- // a: Div().Body(
39
- // Range([]string{"hello", "world"}).Slice(func(i int) UI {
40
- // src := []string{"hello", "world"}
41
- // return Text(src[i])
42
- // }),
43
- // ),
44
- // b: Div().Body(
45
- // Range([]string{}).Slice(func(i int) UI {
46
- // src := []string{"hello", "maxoo"}
47
- // return Text(src[i])
48
- // }),
49
- // ),
50
- // matches: []TestUIDescriptor{
51
- // {
52
- // Path: TestPath(),
53
- // Expected: Div(),
54
- // },
55
- // {
56
- // Path: TestPath(0),
57
- // Expected: nil,
58
- // },
59
- // {
60
- // Path: TestPath(1),
61
- // Expected: nil,
62
- // },
63
- // },
64
- // },
65
- // {
66
- // scenario: "range map is updated",
67
- // a: Div().Body(
68
- // Range(map[string]string{"key": "value"}).Map(func(k string) UI {
69
- // src := map[string]string{"key": "value"}
70
- // return Text(src[k])
71
- // }),
72
- // ),
73
- // b: Div().Body(
74
- // Range(map[string]string{"key": "value"}).Map(func(k string) UI {
75
- // src := map[string]string{"key": "maxoo"}
76
- // return Text(src[k])
77
- // }),
78
- // ),
79
- // matches: []TestUIDescriptor{
80
- // {
81
- // Path: TestPath(),
82
- // Expected: Div(),
83
- // },
84
- // {
85
- // Path: TestPath(0),
86
- // Expected: Text("maxoo"),
87
- // },
88
- // },
89
- // },
90
- // })
91
- // }
92
-
93
- // func TestCondition(t *testing.T) {
94
- // testUpdate(t, []updateTest{
95
- // {
96
- // scenario: "if is interpreted",
97
- // a: Div().Body(
98
- // If(false,
99
- // H1(),
100
- // ),
101
- // ),
102
- // b: Div().Body(
103
- // If(true,
104
- // H1(),
105
- // ),
106
- // ),
107
- // matches: []TestUIDescriptor{
108
- // {
109
- // Path: TestPath(),
110
- // Expected: Div(),
111
- // },
112
-
113
- // {
114
- // Path: TestPath(0),
115
- // Expected: H1(),
116
- // },
117
- // },
118
- // },
119
- // {
120
- // scenario: "if is not interpreted",
121
- // a: Div().Body(
122
- // If(true,
123
- // H1(),
124
- // ),
125
- // ),
126
- // b: Div().Body(
127
- // If(false,
128
- // H1(),
129
- // ),
130
- // ),
131
- // matches: []TestUIDescriptor{
132
- // {
133
- // Path: TestPath(),
134
- // Expected: Div(),
135
- // },
136
- // {
137
- // Path: TestPath(0),
138
- // Expected: nil,
139
- // },
140
- // },
141
- // },
142
- // {
143
- // scenario: "else if is interpreted",
144
- // a: Div().Body(
145
- // If(true,
146
- // H1(),
147
- // ).ElseIf(false,
148
- // H2(),
149
- // ),
150
- // ),
151
- // b: Div().Body(
152
- // If(false,
153
- // H1(),
154
- // ).ElseIf(true,
155
- // H2(),
156
- // ),
157
- // ),
158
- // matches: []TestUIDescriptor{
159
- // {
160
- // Path: TestPath(),
161
- // Expected: Div(),
162
- // },
163
-
164
- // {
165
- // Path: TestPath(0),
166
- // Expected: H2(),
167
- // },
168
- // },
169
- // },
170
- // {
171
- // scenario: "else if is not interpreted",
172
- // a: Div().Body(
173
- // If(false,
174
- // H1(),
175
- // ).ElseIf(true,
176
- // H2(),
177
- // ),
178
- // ),
179
- // b: Div().Body(
180
- // If(false,
181
- // H1(),
182
- // ).ElseIf(false,
183
- // H2(),
184
- // ),
185
- // ),
186
- // matches: []TestUIDescriptor{
187
- // {
188
- // Path: TestPath(),
189
- // Expected: Div(),
190
- // },
191
-
192
- // {
193
- // Path: TestPath(0),
194
- // Expected: nil,
195
- // },
196
- // },
197
- // },
198
- // {
199
- // scenario: "else is interpreted",
200
- // a: Div().Body(
201
- // If(false,
202
- // H1(),
203
- // ).ElseIf(true,
204
- // H2(),
205
- // ).Else(
206
- // H3(),
207
- // ),
208
- // ),
209
- // b: Div().Body(
210
- // If(false,
211
- // H1(),
212
- // ).ElseIf(false,
213
- // H2(),
214
- // ).Else(
215
- // H3(),
216
- // ),
217
- // ),
218
- // matches: []TestUIDescriptor{
219
- // {
220
- // Path: TestPath(),
221
- // Expected: Div(),
222
- // },
223
-
224
- // {
225
- // Path: TestPath(0),
226
- // Expected: H3(),
227
- // },
228
- // },
229
- // },
230
- // {
231
- // scenario: "else is not interpreted",
232
- // a: Div().Body(
233
- // If(false,
234
- // H1(),
235
- // ).ElseIf(true,
236
- // H2(),
237
- // ).Else(
238
- // H3(),
239
- // ),
240
- // ),
241
- // b: Div().Body(
242
- // If(true,
243
- // H1(),
244
- // ).ElseIf(false,
245
- // H2(),
246
- // ).Else(
247
- // H3(),
248
- // ),
249
- // ),
250
- // matches: []TestUIDescriptor{
251
- // {
252
- // Path: TestPath(),
253
- // Expected: Div(),
254
- // },
255
-
256
- // {
257
- // Path: TestPath(0),
258
- // Expected: H1(),
259
- // },
260
- // },
261
- // },
262
- // })
263
- // }