github.com/vugu/vugu@v0.3.5/wasm-test-suite/wasm-suite_test.go (about)

     1  package main
     2  
     3  import (
     4  	"context"
     5  	"io/ioutil"
     6  	"log"
     7  	"os"
     8  	"path/filepath"
     9  	"regexp"
    10  	"strings"
    11  	"testing"
    12  	"time"
    13  
    14  	"github.com/chromedp/cdproto/cdp"
    15  	"github.com/chromedp/chromedp"
    16  	"github.com/chromedp/chromedp/kb"
    17  	"github.com/stretchr/testify/assert"
    18  )
    19  
    20  // TO ADD A TEST:
    21  // - make a folder of the same pattern test-NNN-description
    22  // - copy .gitignore, go.mod and create a root.vugu, plus whatever else
    23  // - write a TestNNNDescription method to drive it
    24  // - to manually view the page from a test log the URL passed to chromedp.Navigate and view it in your browser
    25  //   (if you suspect you are getting console errors that you can't see, this is a simple way to check)
    26  
    27  func Test001Simple(t *testing.T) {
    28  
    29  	dir, origDir := mustUseDir("test-001-simple")
    30  	defer os.Chdir(origDir)
    31  
    32  	tf := func(t *testing.T, pathSuffix string) {
    33  
    34  		ctx, cancel := mustChromeCtx()
    35  		defer cancel()
    36  
    37  		cases := []struct {
    38  			id       string
    39  			expected string
    40  		}{
    41  			{"t0", "t0text"},
    42  			{"t1", "t1text"},
    43  			{"t2", "t2text"},
    44  			{"t3", "&"},
    45  			{"t4", "&"},
    46  			{"t5", "false"},
    47  			{"t6", "10"},
    48  			{"t7", "20.000000"},
    49  			{"t8", ""},
    50  			{"t9", "S-HERE:blah"},
    51  		}
    52  
    53  		tout := make([]string, len(cases))
    54  
    55  		log.Printf("URL: http://localhost:8846%s", pathSuffix)
    56  		actions := []chromedp.Action{chromedp.Navigate("http://localhost:8846" + pathSuffix)}
    57  		for i, c := range cases {
    58  			actions = append(actions, chromedp.InnerHTML("#"+c.id, &tout[i]))
    59  		}
    60  
    61  		must(chromedp.Run(ctx, actions...))
    62  
    63  		for i, c := range cases {
    64  			i, c := i, c
    65  			t.Run(c.id, func(t *testing.T) {
    66  				assert := assert.New(t)
    67  				assert.Equal(c.expected, tout[i])
    68  			})
    69  		}
    70  
    71  	}
    72  
    73  	t.Run("go", func(t *testing.T) { tf(t, mustGenBuildAndLoad(dir)) })
    74  	t.Run("tinygo/NoDocker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, false)) })
    75  	t.Run("tinygo/Docker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, true)) })
    76  
    77  }
    78  
    79  func Test002Click(t *testing.T) {
    80  
    81  	dir, origDir := mustUseDir("test-002-click")
    82  	defer os.Chdir(origDir)
    83  
    84  	tf := func(t *testing.T, pathSuffix string) {
    85  
    86  		assert := assert.New(t)
    87  
    88  		ctx, cancel := mustChromeCtx()
    89  		defer cancel()
    90  		// log.Printf("pathSuffix = %s", pathSuffix)
    91  
    92  		var text string
    93  		must(chromedp.Run(ctx,
    94  			chromedp.Navigate("http://localhost:8846"+pathSuffix),
    95  			chromedp.WaitVisible("#testdiv"),
    96  			chromedp.WaitNotPresent("#success"),
    97  			chromedp.Click("#run1"),
    98  			chromedp.InnerHTML("#success", &text),
    99  			chromedp.Click("#run1"),
   100  			chromedp.WaitNotPresent("#success"),
   101  		))
   102  
   103  		assert.Equal("success", text)
   104  
   105  	}
   106  
   107  	t.Run("go", func(t *testing.T) { tf(t, mustGenBuildAndLoad(dir)) })
   108  	t.Run("tinygo/NoDocker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, false)) })
   109  	t.Run("tinygo/Docker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, true)) })
   110  
   111  }
   112  
   113  func Test003Prop(t *testing.T) {
   114  
   115  	dir, origDir := mustUseDir("test-003-prop")
   116  	defer os.Chdir(origDir)
   117  
   118  	tf := func(t *testing.T, pathSuffix string) {
   119  
   120  		ctx, cancel := mustChromeCtx()
   121  		defer cancel()
   122  		// log.Printf("pathSuffix = %s", pathSuffix)
   123  
   124  		must(chromedp.Run(ctx,
   125  			chromedp.Navigate("http://localhost:8846"+pathSuffix),
   126  			chromedp.WaitVisible("#email"),
   127  			chromedp.SendKeys("#email", "joey@example.com"),
   128  			chromedp.Blur("#email"),
   129  			WaitInnerTextTrimEq("#emailout", "joey@example.com"),
   130  			chromedp.Click("#resetbtn"),
   131  			WaitInnerTextTrimEq("#emailout", "default@example.com"),
   132  		))
   133  
   134  	}
   135  
   136  	t.Run("go", func(t *testing.T) { tf(t, mustGenBuildAndLoad(dir)) })
   137  	t.Run("tinygo/NoDocker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, false)) })
   138  	t.Run("tinygo/Docker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, true)) })
   139  }
   140  
   141  func Test004Component(t *testing.T) {
   142  
   143  	dir, origDir := mustUseDir("test-004-component")
   144  	defer os.Chdir(origDir)
   145  
   146  	tf := func(t *testing.T, pathSuffix string) {
   147  
   148  		ctx, cancel := mustChromeCtx()
   149  		defer cancel()
   150  		// log.Printf("pathSuffix = %s", pathSuffix)
   151  
   152  		must(chromedp.Run(ctx,
   153  			chromedp.Navigate("http://localhost:8846"+pathSuffix),
   154  			chromedp.WaitVisible("#testdiv"),
   155  			WaitInnerTextTrimEq("ul", "0 a line is here\n1 a line is here\n2 a line is here"),
   156  			chromedp.Click("#addbtn"),
   157  			WaitInnerTextTrimEq("ul", "0 a line is here\n1 a line is here\n2 a line is here\n3 a line is here"),
   158  		))
   159  
   160  	}
   161  
   162  	t.Run("go", func(t *testing.T) { tf(t, mustGenBuildAndLoad(dir)) })
   163  	t.Run("tinygo/NoDocker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, false)) })
   164  	t.Run("tinygo/Docker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, true)) })
   165  }
   166  
   167  func Test005Issue80(t *testing.T) {
   168  
   169  	dir, origDir := mustUseDir("test-005-issue-80")
   170  	defer os.Chdir(origDir)
   171  
   172  	tf := func(t *testing.T, pathSuffix string) {
   173  
   174  		ctx, cancel := mustChromeCtx()
   175  		defer cancel()
   176  		// log.Printf("pathSuffix = %s", pathSuffix)
   177  
   178  		must(chromedp.Run(ctx,
   179  			chromedp.Navigate("http://localhost:8846"+pathSuffix),
   180  			chromedp.WaitVisible("#items"),
   181  			WaitInnerTextTrimEq("#items", "abcd"),
   182  		))
   183  
   184  	}
   185  
   186  	t.Run("go", func(t *testing.T) { tf(t, mustGenBuildAndLoad(dir)) })
   187  	t.Run("tinygo/NoDocker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, false)) })
   188  	t.Run("tinygo/Docker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, true)) })
   189  }
   190  
   191  // TODO Rename it to Test006HtmlAttr ?
   192  func Test006Issue81(t *testing.T) {
   193  
   194  	dir, origDir := mustUseDir("test-006-issue-81")
   195  	defer os.Chdir(origDir)
   196  
   197  	tf := func(t *testing.T, pathSuffix string) {
   198  
   199  		assert := assert.New(t)
   200  
   201  		ctx, cancel := mustChromeCtx()
   202  		defer cancel()
   203  		log.Printf("URL: %s", "http://localhost:8846"+pathSuffix)
   204  
   205  		must(chromedp.Run(ctx,
   206  			chromedp.Navigate("http://localhost:8846"+pathSuffix),
   207  			chromedp.WaitVisible("#content"),
   208  			queryNode("html", func(n *cdp.Node) {
   209  				assert.Equal(
   210  					[]string{"class", "html-class", "lang", "en"},
   211  					n.Attributes,
   212  					"wrong html attributes",
   213  				)
   214  			}),
   215  			queryNode("head", func(n *cdp.Node) {
   216  				assert.Equal(
   217  					[]string{"class", "head-class"},
   218  					n.Attributes,
   219  					"wrong head attributes",
   220  				)
   221  			}),
   222  			queryNode("body", func(n *cdp.Node) {
   223  				assert.Equal(
   224  					[]string{"class", "body-class"},
   225  					n.Attributes,
   226  					"wrong body attributes",
   227  				)
   228  			}),
   229  		))
   230  
   231  	}
   232  
   233  	t.Run("go", func(t *testing.T) { tf(t, mustGenBuildAndLoad(dir)) })
   234  	t.Run("tinygo/NoDocker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, false)) })
   235  	t.Run("tinygo/Docker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, true)) })
   236  }
   237  
   238  func Test007Issue85(t *testing.T) {
   239  	dir, origDir := mustUseDir("test-007-issue-85")
   240  	defer os.Chdir(origDir)
   241  
   242  	tf := func(t *testing.T, pathSuffix string) {
   243  
   244  		ctx, cancel := mustChromeCtx()
   245  		defer cancel()
   246  
   247  		must(chromedp.Run(ctx,
   248  			chromedp.Navigate("http://localhost:8846"+pathSuffix),
   249  			chromedp.WaitVisible("#content"),
   250  		))
   251  
   252  	}
   253  
   254  	t.Run("go", func(t *testing.T) { tf(t, mustGenBuildAndLoad(dir)) })
   255  	t.Run("tinygo/NoDocker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, false)) })
   256  	t.Run("tinygo/Docker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, true)) })
   257  }
   258  
   259  func Test008For(t *testing.T) {
   260  
   261  	tests := []struct {
   262  		name            string
   263  		dir             string
   264  		expectedText    string
   265  		expectedClicked string
   266  	}{
   267  		{
   268  			name:            "for i",
   269  			dir:             "test-008-for-i",
   270  			expectedText:    "01234",
   271  			expectedClicked: "0 clicked!",
   272  		},
   273  		{
   274  			name:            "for no iteration vars",
   275  			dir:             "test-008-for-keyvalue",
   276  			expectedText:    "0-a1-b2-c3-d4-e",
   277  			expectedClicked: "0-a clicked!",
   278  		},
   279  		{
   280  			name:            "for with iteration vars",
   281  			dir:             "test-008-for-kv",
   282  			expectedText:    "0-a1-b2-c3-d4-e",
   283  			expectedClicked: "0-a clicked!",
   284  		},
   285  		{
   286  			name:            "for no iteration vars noshadow",
   287  			dir:             "test-008-for-keyvalue-noshadow",
   288  			expectedText:    "0-a1-b2-c3-d4-e",
   289  			expectedClicked: "4-e clicked!",
   290  		},
   291  	}
   292  	for _, tt := range tests {
   293  		t.Run(tt.name, func(t *testing.T) {
   294  			dir, origDir := mustUseDir(tt.dir)
   295  			defer os.Chdir(origDir)
   296  
   297  			tf := func(t *testing.T, pathSuffix string) {
   298  
   299  				ctx, cancel := mustChromeCtx()
   300  				defer cancel()
   301  				// log.Printf("pathSuffix = %s", pathSuffix)
   302  
   303  				var clicked string
   304  				must(chromedp.Run(ctx,
   305  					chromedp.Navigate("http://localhost:8846"+pathSuffix),
   306  					chromedp.WaitVisible("#content"),
   307  					WaitInnerTextTrimEq("#content", tt.expectedText),
   308  					chromedp.Click("#id0"),
   309  					chromedp.WaitVisible("#clicked"),
   310  					chromedp.InnerHTML("#clicked", &clicked),
   311  				))
   312  				assert.Equal(t, tt.expectedClicked, clicked)
   313  
   314  			}
   315  
   316  			t.Run("go", func(t *testing.T) { tf(t, mustGenBuildAndLoad(dir)) })
   317  			t.Run("tinygo/NoDocker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, false)) })
   318  			t.Run("tinygo/Docker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, true)) })
   319  		})
   320  	}
   321  }
   322  
   323  func Test009TrimUnused(t *testing.T) {
   324  	dir, origDir := mustUseDir("test-009-trim-unused")
   325  	defer os.Chdir(origDir)
   326  
   327  	tf := func(t *testing.T, pathSuffix string) {
   328  
   329  		ctx, cancel := mustChromeCtx()
   330  		defer cancel()
   331  
   332  		// log.Printf("URL: %s", "http://localhost:8846"+pathSuffix)
   333  
   334  		must(chromedp.Run(ctx,
   335  			chromedp.Navigate("http://localhost:8846"+pathSuffix),
   336  			chromedp.WaitVisible("#content"),
   337  			chromedp.Click("#make2"),
   338  			chromedp.WaitVisible("#n2of2"),
   339  			chromedp.Click("#make6"),
   340  			chromedp.WaitVisible("#n2of6"),
   341  			chromedp.WaitVisible("#n6of6"),
   342  			chromedp.Click("#make2"),
   343  			chromedp.WaitNotPresent("#n6of6"),
   344  			chromedp.WaitVisible("#n2of2"),
   345  		))
   346  
   347  	}
   348  
   349  	t.Run("go", func(t *testing.T) { tf(t, mustGenBuildAndLoad(dir)) })
   350  	t.Run("tinygo/NoDocker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, false)) })
   351  	t.Run("tinygo/Docker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, true)) })
   352  }
   353  
   354  func Test010ListenerReadd(t *testing.T) {
   355  	dir, origDir := mustUseDir("test-010-listener-readd")
   356  	defer os.Chdir(origDir)
   357  
   358  	tf := func(t *testing.T, pathSuffix string) {
   359  
   360  		ctx, cancel := mustChromeCtx()
   361  		defer cancel()
   362  
   363  		// log.Printf("URL: %s", "http://localhost:8846"+pathSuffix)
   364  
   365  		must(chromedp.Run(ctx,
   366  			chromedp.Navigate("http://localhost:8846"+pathSuffix),
   367  			// toggle back and forth a few times and make sure it continues to work
   368  			chromedp.WaitVisible("#view1"),
   369  			chromedp.Click("#switch_btn"),
   370  			chromedp.WaitVisible("#view2"),
   371  			chromedp.Click("#switch_btn"),
   372  			chromedp.WaitVisible("#view1"),
   373  			chromedp.Click("#switch_btn"),
   374  			chromedp.WaitVisible("#view2"),
   375  			chromedp.Click("#switch_btn"),
   376  			chromedp.WaitVisible("#view1"),
   377  		))
   378  
   379  	}
   380  
   381  	t.Run("go", func(t *testing.T) { tf(t, mustGenBuildAndLoad(dir)) })
   382  	t.Run("tinygo/NoDocker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, false)) })
   383  	t.Run("tinygo/Docker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, true)) })
   384  
   385  }
   386  
   387  func Test011Wire(t *testing.T) {
   388  
   389  	dir, origDir := mustUseDir("test-011-wire")
   390  	defer os.Chdir(origDir)
   391  
   392  	tf := func(t *testing.T, pathSuffix string) {
   393  
   394  		ctx, cancel := mustChromeCtx()
   395  		defer cancel()
   396  
   397  		log.Printf("URL: %s", "http://localhost:8846"+pathSuffix)
   398  
   399  		must(chromedp.Run(ctx,
   400  			chromedp.Navigate("http://localhost:8846"+pathSuffix),
   401  			WaitInnerTextTrimEq(".demo-comp1-c", "1"),
   402  			WaitInnerTextTrimEq(".demo-comp2-c", "2"),
   403  		))
   404  
   405  	}
   406  
   407  	t.Run("go", func(t *testing.T) { tf(t, mustGenBuildAndLoad(dir)) })
   408  	t.Run("tinygo/NoDocker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, false)) })
   409  	t.Run("tinygo/Docker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, true)) })
   410  }
   411  
   412  func Test012Router(t *testing.T) {
   413  
   414  	dir, origDir := mustUseDir("test-012-router")
   415  	defer os.Chdir(origDir)
   416  
   417  	tf := func(t *testing.T, pathSuffix string) {
   418  
   419  		ctx, cancel := mustChromeCtx()
   420  		defer cancel()
   421  
   422  		log.Printf("URL: %s", "http://localhost:8846"+pathSuffix)
   423  
   424  		// rack the forward/back history stuff and replace option vs not and make sure that all works right
   425  		// with fragment mode and without
   426  		var tmpres []byte
   427  
   428  		// regular version
   429  		must(chromedp.Run(ctx,
   430  			chromedp.Navigate("http://localhost:8846"+pathSuffix),
   431  			chromedp.WaitVisible("#page1"),                         // make sure page1 showed initially
   432  			chromedp.Click("#page2_link"),                          // regular a href link
   433  			chromedp.WaitVisible("#page2"),                         // make sure it loads
   434  			chromedp.Click("#page1_button"),                        // button goes to page1 without a reload
   435  			chromedp.WaitVisible("#page1"),                         // make sure it renders
   436  			chromedp.Click("#page2_button_repl"),                   // go to page2 without adding to history
   437  			chromedp.WaitVisible("#page2"),                         // make sure it renders
   438  			chromedp.Evaluate("window.history.back()", &tmpres),    // go back one
   439  			chromedp.WaitVisible("#page2"),                         // should still be on page2 because of replace
   440  			chromedp.Evaluate("window.history.back()", &tmpres),    // go back one more
   441  			chromedp.WaitVisible("#page1"),                         // now should be on page1
   442  			chromedp.Evaluate("window.history.forward()", &tmpres), // forward one
   443  			chromedp.WaitVisible("#page2"),
   444  		))
   445  
   446  		// fragment version
   447  		must(chromedp.Run(ctx,
   448  			chromedp.Navigate("http://localhost:8846"+pathSuffix+"#/"), // the test has detection code that sees the fragment here and puts it into fragment mode
   449  			chromedp.WaitVisible("#page1"),                             // make sure page1 showed initially
   450  			chromedp.Evaluate("window.location='#/page2'", &tmpres),    // browse to page2 via fragment
   451  			chromedp.WaitVisible("#page2"),                             // make sure it renders
   452  			chromedp.Click("#page1_button"),                            // button goes to page1 without a reload
   453  			chromedp.WaitVisible("#page1"),                             // make sure it renders
   454  			chromedp.Click("#page2_button_repl"),                       // go to page2 without adding to history
   455  			chromedp.WaitVisible("#page2"),                             // make sure it renders
   456  			chromedp.Evaluate("window.history.back()", &tmpres),        // go back one
   457  			chromedp.WaitVisible("#page2"),                             // should still be on page2 because of replace
   458  			chromedp.Evaluate("window.history.back()", &tmpres),        // go back one more
   459  			chromedp.WaitVisible("#page1"),                             // now should be on page1
   460  			chromedp.Evaluate("window.history.forward()", &tmpres),     // forward one
   461  			chromedp.WaitVisible("#page2"),
   462  		))
   463  
   464  	}
   465  
   466  	t.Run("go", func(t *testing.T) { tf(t, mustGenBuildAndLoad(dir)) })
   467  	t.Run("tinygo/NoDocker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, false)) })
   468  	t.Run("tinygo/Docker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, true)) })
   469  }
   470  
   471  func Test013Issue117(t *testing.T) {
   472  
   473  	dir, origDir := mustUseDir("test-013-issue-117")
   474  	defer os.Chdir(origDir)
   475  
   476  	tf := func(t *testing.T, pathSuffix string) {
   477  
   478  		ctx, cancel := mustChromeCtx()
   479  		defer cancel()
   480  
   481  		log.Printf("URL: %s", "http://localhost:8846"+pathSuffix)
   482  
   483  		must(chromedp.Run(ctx,
   484  			chromedp.Navigate("http://localhost:8846"+pathSuffix),
   485  			chromedp.WaitVisible("#create_button"), // make sure page1 showed initially
   486  			chromedp.Click("#create_button"),       // regular a href link
   487  			chromedp.WaitVisible("#myform"),        // make sure it loads
   488  			chromedp.WaitNotPresent("#mytable"),
   489  		))
   490  
   491  	}
   492  
   493  	t.Run("go", func(t *testing.T) { tf(t, mustGenBuildAndLoad(dir)) })
   494  	t.Run("tinygo/NoDocker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, false)) })
   495  	t.Run("tinygo/Docker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, true)) })
   496  }
   497  
   498  func Test014AttrIntf(t *testing.T) {
   499  
   500  	dir, origDir := mustUseDir("test-014-attrintf")
   501  	defer os.Chdir(origDir)
   502  
   503  	tf := func(t *testing.T, pathSuffix string) {
   504  
   505  		assert := assert.New(t)
   506  
   507  		ctx, cancel := mustChromeCtx()
   508  		defer cancel()
   509  
   510  		log.Printf("URL: %s", "http://localhost:8846"+pathSuffix)
   511  
   512  		attributeEq := func(ref, val string) chromedp.QueryAction {
   513  			return queryAttributes(ref, func(attributes map[string]string) {
   514  				assert.Contains(attributes, "attr", "attribute on '%s' is missing", ref)
   515  				assert.Equal(val, attributes["attr"], "attribute value on '%s' is invalid", ref)
   516  			})
   517  		}
   518  
   519  		noAttribute := func(ref string) chromedp.QueryAction {
   520  			return queryAttributes(ref, func(attributes map[string]string) {
   521  				assert.NotContains(attributes, "attr", "attribute on '%s' exists, but shouldn't", ref)
   522  			})
   523  		}
   524  
   525  		must(chromedp.Run(ctx,
   526  			chromedp.Navigate("http://localhost:8846"+pathSuffix),
   527  			chromedp.WaitVisible("#testing"), // wait until render
   528  			attributeEq("#plain_string", "string"),
   529  			attributeEq("#string_var", "aString"),
   530  			attributeEq("#string_ptr", "aString"),
   531  			attributeEq("#int_var", "42"),
   532  			attributeEq("#int_ptr", "42"),
   533  			attributeEq("#true_var", "attr"),
   534  			noAttribute("#false_var"),
   535  			attributeEq("#true_ptr", "attr"),
   536  			noAttribute("#false_ptr"),
   537  			noAttribute("#string_nil_ptr"),
   538  			attributeEq("#stringer", "myString"),
   539  			noAttribute("#stringer_nil_ptr"),
   540  		))
   541  
   542  	}
   543  
   544  	t.Run("go", func(t *testing.T) { tf(t, mustGenBuildAndLoad(dir)) })
   545  	t.Run("tinygo/NoDocker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, false)) })
   546  	t.Run("tinygo/Docker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, true)) })
   547  
   548  }
   549  
   550  func Test015AttrList(t *testing.T) {
   551  
   552  	dir, origDir := mustUseDir("test-015-attribute-lister")
   553  	defer os.Chdir(origDir)
   554  
   555  	tf := func(t *testing.T, pathSuffix string) {
   556  		assert := assert.New(t)
   557  
   558  		ctx, cancel := mustChromeCtx()
   559  		defer cancel()
   560  
   561  		log.Printf("URL: %s", "http://localhost:8846"+pathSuffix)
   562  
   563  		must(chromedp.Run(ctx,
   564  			chromedp.Navigate("http://localhost:8846"+pathSuffix),
   565  			chromedp.WaitVisible("#testing"), // wait until render
   566  			queryAttributes("#testing", func(attributes map[string]string) {
   567  				assert.Contains(attributes, "class", "attribute is missing")
   568  				assert.Equal("widget", attributes["class"], "attribute value is invalid")
   569  			}),
   570  			queryAttributes("#testing", func(attributes map[string]string) {
   571  				assert.Contains(attributes, "data-test", "attribute is missing")
   572  				assert.Equal("test", attributes["data-test"], "attribute value is invalid")
   573  			}),
   574  			queryAttributes("#functest", func(attributes map[string]string) {
   575  				assert.Contains(attributes, "class", "attribute is missing")
   576  				assert.Equal("funcwidget", attributes["class"], "attribute value is invalid")
   577  			}),
   578  			queryAttributes("#functest", func(attributes map[string]string) {
   579  				assert.Contains(attributes, "data-test", "attribute is missing")
   580  				assert.Equal("functest", attributes["data-test"], "attribute value is invalid")
   581  			}),
   582  			queryAttributes("#functest2", func(attributes map[string]string) { // check with vg-attr syntax
   583  				assert.Contains(attributes, "class", "attribute is missing")
   584  				assert.Equal("funcwidget", attributes["class"], "attribute value is invalid")
   585  				assert.Contains(attributes, "data-test", "attribute is missing")
   586  				assert.Equal("functest", attributes["data-test"], "attribute value is invalid")
   587  			}),
   588  		))
   589  
   590  	}
   591  
   592  	t.Run("go", func(t *testing.T) { tf(t, mustGenBuildAndLoad(dir)) })
   593  	t.Run("tinygo/NoDocker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, false)) })
   594  	t.Run("tinygo/Docker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, true)) })
   595  
   596  }
   597  
   598  func Test016SVG(t *testing.T) {
   599  
   600  	dir, origDir := mustUseDir("test-016-svg")
   601  	defer os.Chdir(origDir)
   602  
   603  	tf := func(t *testing.T, pathSuffix string) {
   604  		assert := assert.New(t)
   605  		ctx, cancel := mustChromeCtx()
   606  		defer cancel()
   607  
   608  		log.Printf("URL: %s", "http://localhost:8846"+pathSuffix)
   609  
   610  		must(chromedp.Run(ctx,
   611  			chromedp.Navigate("http://localhost:8846"+pathSuffix),
   612  			chromedp.WaitVisible("#icon"),          // wait for the icon to show up
   613  			chromedp.WaitVisible("#icon polyline"), // make sure that the svg element is complete
   614  			chromedp.QueryAfter("#icon", func(ctx context.Context, node ...*cdp.Node) error {
   615  				// checking if the element is recognized as SVG by chrome should be enough
   616  				assert.True(node[0].IsSVG)
   617  				return nil
   618  			}),
   619  		))
   620  
   621  	}
   622  
   623  	t.Run("go", func(t *testing.T) { tf(t, mustGenBuildAndLoad(dir)) })
   624  	t.Run("tinygo/NoDocker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, false)) })
   625  	t.Run("tinygo/Docker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, true)) })
   626  
   627  }
   628  
   629  func Test017Nesting(t *testing.T) {
   630  
   631  	dir, origDir := mustUseDir("test-017-nesting")
   632  	defer os.Chdir(origDir)
   633  
   634  	tf := func(t *testing.T, pathSuffix string) {
   635  
   636  		ctx, cancel := mustChromeCtx()
   637  		defer cancel()
   638  
   639  		log.Printf("URL: %s", "http://localhost:8846"+pathSuffix)
   640  
   641  		must(chromedp.Run(ctx,
   642  			chromedp.Navigate("http://localhost:8846"+pathSuffix),
   643  			chromedp.WaitVisible("#final1"), // make sure things showed up
   644  			chromedp.WaitVisible("#final2"), // make sure things showed up
   645  
   646  			chromedp.Click("#final1 .clicker"),            // click top one
   647  			chromedp.WaitVisible("#final1 .clicked-true"), // should get clicked on #1
   648  			chromedp.WaitNotPresent("#final1 .clicked-false"),
   649  			chromedp.WaitNotPresent("#final2 .clicked-true"), // but not on #2
   650  			chromedp.WaitVisible("#final2 .clicked-false"),
   651  
   652  			// now check the reverse
   653  
   654  			chromedp.Navigate("http://localhost:8846"+pathSuffix),
   655  			chromedp.WaitVisible("#final1"), // make sure things showed up
   656  			chromedp.WaitVisible("#final2"), // make sure things showed up
   657  
   658  			chromedp.Click("#final2 .clicker"),            // click bottom one
   659  			chromedp.WaitVisible("#final2 .clicked-true"), // should get clicked on #2
   660  			chromedp.WaitNotPresent("#final2 .clicked-false"),
   661  			chromedp.WaitNotPresent("#final1 .clicked-true"), // but not on #1
   662  			chromedp.WaitVisible("#final1 .clicked-false"),
   663  		))
   664  
   665  	}
   666  
   667  	t.Run("go", func(t *testing.T) { tf(t, mustGenBuildAndLoad(dir)) })
   668  	t.Run("tinygo/NoDocker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, false)) })
   669  	t.Run("tinygo/Docker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, true)) })
   670  
   671  }
   672  
   673  func Test018CompEvents(t *testing.T) {
   674  
   675  	dir, origDir := mustUseDir("test-018-comp-events")
   676  	defer os.Chdir(origDir)
   677  
   678  	tf := func(t *testing.T, pathSuffix string) {
   679  
   680  		assert := assert.New(t)
   681  
   682  		ctx, cancel := mustChromeCtx()
   683  		defer cancel()
   684  
   685  		log.Printf("URL: %s", "http://localhost:8846"+pathSuffix)
   686  
   687  		var showText string
   688  		must(chromedp.Run(ctx,
   689  			chromedp.Navigate("http://localhost:8846"+pathSuffix),
   690  			chromedp.WaitVisible("#top"),  // make sure things showed up
   691  			chromedp.Click("#the_button"), // click the button inside the component
   692  
   693  			chromedp.WaitVisible("#show_text"), // wait for it to dump event out
   694  			chromedp.InnerHTML("#show_text", &showText),
   695  		))
   696  		//t.Logf("showText=%s", showText)
   697  		assert.Contains(showText, "ClickEvent")
   698  
   699  	}
   700  
   701  	t.Run("go", func(t *testing.T) { tf(t, mustGenBuildAndLoad(dir)) })
   702  	t.Run("tinygo/NoDocker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, false)) })
   703  	t.Run("tinygo/Docker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, true)) })
   704  
   705  }
   706  
   707  func Test019JSCreatePopulate(t *testing.T) {
   708  
   709  	dir, origDir := mustUseDir("test-019-js-create-populate")
   710  	defer os.Chdir(origDir)
   711  
   712  	tf := func(t *testing.T, pathSuffix string) {
   713  
   714  		assert := assert.New(t)
   715  		ctx, cancel := mustChromeCtx()
   716  		defer cancel()
   717  
   718  		log.Printf("URL: %s", "http://localhost:8846"+pathSuffix)
   719  
   720  		var logText string
   721  		must(chromedp.Run(ctx,
   722  			chromedp.Navigate("http://localhost:8846"+pathSuffix),
   723  			chromedp.WaitVisible("#the_button"), // make sure things showed up
   724  			chromedp.Click("#the_button"),       // click the button
   725  			chromedp.WaitVisible("#log"),        // wait for the log to show up
   726  			chromedp.Click("#the_button"),       // click the button again
   727  			chromedp.WaitVisible("#log_7"),      // wait for all of the log entries to show
   728  			chromedp.Text(`#log`, &logText, chromedp.NodeVisible, chromedp.ByID),
   729  		))
   730  		// t.Logf("logText=%s", logText)
   731  		logLines := strings.Split(logText, "\n")
   732  
   733  		// vg-js-create first pass
   734  		assert.Equal("vg-js-create className thing", strings.TrimSpace(logLines[0]))
   735  		assert.Equal("vg-js-create firstElementChild <null>", strings.TrimSpace(logLines[1]))
   736  
   737  		// vg-js-populate first pass
   738  		assert.Equal("vg-js-populate className thing", strings.TrimSpace(logLines[2]))
   739  		assert.Equal("vg-js-populate firstElementChild <object>", strings.TrimSpace(logLines[3]))
   740  
   741  		// vg-js-create second pass
   742  		assert.Equal("vg-js-create className thing", strings.TrimSpace(logLines[4]))
   743  		assert.Equal("vg-js-create firstElementChild <object>", strings.TrimSpace(logLines[5]))
   744  
   745  		// vg-js-populate second pass
   746  		assert.Equal("vg-js-populate className thing", strings.TrimSpace(logLines[6]))
   747  		assert.Equal("vg-js-populate firstElementChild <object>", strings.TrimSpace(logLines[7]))
   748  
   749  	}
   750  
   751  	t.Run("go", func(t *testing.T) { tf(t, mustGenBuildAndLoad(dir)) })
   752  	// FIXME: this fails with tinygo 0.22.0 in the UI with: syscall/js.finalizeRef not implemented; panic: JavaScript error: unreachable;
   753  	// t.Run("tinygo", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, nil)) })
   754  
   755  }
   756  
   757  func Test020VGForm(t *testing.T) {
   758  
   759  	dir, origDir := mustUseDir("test-020-vgform")
   760  	defer os.Chdir(origDir)
   761  
   762  	tf := func(t *testing.T, pathSuffix string) {
   763  
   764  		ctx, cancel := mustChromeCtx()
   765  		defer cancel()
   766  
   767  		log.Printf("URL: %s", "http://localhost:8846"+pathSuffix)
   768  
   769  		must(chromedp.Run(ctx,
   770  			chromedp.Navigate("http://localhost:8846"+pathSuffix),
   771  			chromedp.WaitVisible("#food_group_value"), // make sure things showed up
   772  			chromedp.SendKeys(`#food_group`, "Butterfinger Group"),
   773  			WaitInnerTextTrimEq("#food_group_value", "butterfinger_group"),
   774  		))
   775  
   776  	}
   777  
   778  	t.Run("go", func(t *testing.T) { tf(t, mustGenBuildAndLoad(dir)) })
   779  	t.Run("tinygo/NoDocker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, false)) })
   780  	t.Run("tinygo/Docker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, true)) })
   781  }
   782  
   783  func Test021Slots(t *testing.T) {
   784  
   785  	dir, origDir := mustUseDir("test-021-slots")
   786  	defer os.Chdir(origDir)
   787  
   788  	tf := func(t *testing.T, pathSuffix string) {
   789  
   790  		ctx, cancel := mustChromeCtx()
   791  		defer cancel()
   792  
   793  		log.Printf("URL: %s", "http://localhost:8846"+pathSuffix)
   794  
   795  		var tmplparentInnerHTML string
   796  		must(chromedp.Run(ctx,
   797  			chromedp.Navigate("http://localhost:8846"+pathSuffix),
   798  			chromedp.WaitVisible("#tmplparent"), // make sure things showed up
   799  			chromedp.InnerHTML("#tmplparent", &tmplparentInnerHTML),
   800  			WaitInnerTextTrimEq("#table2 #another_slot", "another slot"),
   801  			WaitInnerTextTrimEq("#table2 #mapidx_slot", "mapidx slot"),
   802  		))
   803  
   804  		if tmplparentInnerHTML != "simple template test" {
   805  			t.Errorf("tmplparent did not have expected innerHTML, instead got: %s", tmplparentInnerHTML)
   806  		}
   807  
   808  		rootvgengo, err := ioutil.ReadFile(filepath.Join(dir, "root_vgen.go"))
   809  		must(err)
   810  		if !regexp.MustCompile(`var mydt `).Match(rootvgengo) {
   811  			t.Errorf("missing vg-var reference in root_vgen.go")
   812  		}
   813  
   814  	}
   815  
   816  	t.Run("go", func(t *testing.T) { tf(t, mustGenBuildAndLoad(dir)) })
   817  	t.Run("tinygo/NoDocker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, false)) })
   818  	t.Run("tinygo/Docker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, true)) })
   819  
   820  }
   821  
   822  func Test022EventListener(t *testing.T) {
   823  
   824  	dir, origDir := mustUseDir("test-022-event-listener")
   825  	defer os.Chdir(origDir)
   826  
   827  	tf := func(t *testing.T, pathSuffix string) {
   828  
   829  		assert := assert.New(t)
   830  
   831  		ctx, cancel := mustChromeCtx()
   832  		defer cancel()
   833  		// log.Printf("pathSuffix = %s", pathSuffix)
   834  
   835  		var text string
   836  		must(chromedp.Run(ctx,
   837  			chromedp.Navigate("http://localhost:8846"+pathSuffix),
   838  			chromedp.WaitVisible("#top"),
   839  			chromedp.Click("#switch"),
   840  			chromedp.WaitVisible("#noclick"),
   841  			chromedp.Click("#noclick"),
   842  			chromedp.Click("#switch"),
   843  			chromedp.WaitNotPresent("#noclick"),
   844  			chromedp.Click("#click"),
   845  			chromedp.Click("#switch"),
   846  			chromedp.WaitVisible("#text"),
   847  			chromedp.InnerHTML("#text", &text),
   848  		))
   849  
   850  		assert.Equal("click", text)
   851  
   852  	}
   853  
   854  	t.Run("go", func(t *testing.T) { tf(t, mustGenBuildAndLoad(dir)) })
   855  	t.Run("tinygo/NoDocker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, false)) })
   856  	t.Run("tinygo/Docker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, true)) })
   857  }
   858  
   859  func Test023LifecycleCallbacks(t *testing.T) {
   860  
   861  	dir, origDir := mustUseDir("test-023-lifecycle-callbacks")
   862  	defer os.Chdir(origDir)
   863  
   864  	tf := func(t *testing.T, pathSuffix string) {
   865  
   866  		assert := assert.New(t)
   867  		_ = assert
   868  
   869  		ctx, cancel := mustChromeCtx()
   870  		defer cancel()
   871  		log.Printf("URL: %s", "http://localhost:8846"+pathSuffix)
   872  
   873  		var logTextContent string
   874  		must(chromedp.Run(ctx,
   875  			chromedp.Navigate("http://localhost:8846"+pathSuffix),
   876  			chromedp.WaitVisible("#top"),
   877  			chromedp.Click("#togglec1"),
   878  			chromedp.WaitNotPresent("#c1"),
   879  			chromedp.Click("#togglec2"),
   880  			chromedp.WaitNotPresent("#c2"),
   881  			chromedp.Click("#refresh"),
   882  			chromedp.Click("#togglec1"),
   883  			chromedp.WaitVisible("#c1"),
   884  			chromedp.Click("#togglec2"),
   885  			chromedp.WaitVisible("#c2"),
   886  			chromedp.Evaluate("window.logTextContent", &logTextContent),
   887  		))
   888  
   889  		assert.Equal(logTextContent, `got C1.Init(ctx)
   890  got C1.Compute(ctx)
   891  got C2.Init()
   892  got C2.Compute()
   893  got C1.Rendered(ctx)[first=true]
   894  got C2.Rendered()
   895  got C2.Compute()
   896  got C1.Destroy(ctx)
   897  got C2.Rendered()
   898  got C2.Destroy()
   899  got C1.Init(ctx)
   900  got C1.Compute(ctx)
   901  got C1.Rendered(ctx)[first=true]
   902  got C1.Compute(ctx)
   903  got C2.Init()
   904  got C2.Compute()
   905  got C1.Rendered(ctx)[first=false]
   906  got C2.Rendered()
   907  `)
   908  		// log.Printf("logTextContext: %s", logTextContent)
   909  
   910  	}
   911  
   912  	t.Run("go", func(t *testing.T) { tf(t, mustGenBuildAndLoad(dir)) })
   913  	t.Run("tinygo/NoDocker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, false)) })
   914  	t.Run("tinygo/Docker", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, true)) })
   915  }
   916  
   917  func Test024EventBufferSize(t *testing.T) {
   918  
   919  	dir, origDir := mustUseDir("test-024-event-buffer-size")
   920  	defer os.Chdir(origDir)
   921  
   922  	tf := func(t *testing.T, pathSuffix string) {
   923  
   924  		ctx, cancel := mustChromeCtx()
   925  		ctx, cancel = context.WithTimeout(ctx, 60*time.Second)
   926  		defer cancel()
   927  		var val string
   928  		must(chromedp.Run(ctx,
   929  			chromedp.Navigate("http://localhost:8846"+pathSuffix),
   930  			chromedp.WaitVisible("#top"),
   931  			// trigger the change event
   932  			chromedp.SendKeys("select", kb.ArrowDown+kb.ArrowDown),
   933  			chromedp.Value(`select`, &val),
   934  		))
   935  		log.Println(val)
   936  	}
   937  	t.Run("go", func(t *testing.T) { tf(t, mustGenBuildAndLoad(dir)) })
   938  	t.Run("go", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, true)) })
   939  	t.Run("go", func(t *testing.T) { tf(t, mustTGGenBuildAndLoad(dir, false)) })
   940  }