14.5 C
New York
Sunday, November 17, 2024

Check Drive HTML Templates


foo

Let’s have a look at methods to do it in phases: We begin with the next check that tries to compile the template. In Go we use the usual html/template package deal.

Go

  func Test_wellFormedHtml(t *testing.T) {
    templ := template.Should(template.ParseFiles("index.tmpl"))
    _ = templ
  }

In Java we use moustache
as a result of it is extremely straightforward to make use of; free marker both
Pace are different widespread choices.

Java

  @Check
  void indexIsSoundHtml() {
      var template = Mustache.compiler().compile(
              new InputStreamReader(
                      getClass().getResourceAsStream("/index.tmpl")));
  }

If we run this check, it should fail, as a result of the index.tmpl the file doesn’t exist. So we create it, with the damaged HTML above. Now the check ought to go.

Then we create a mannequin for the template to make use of. The app manages a to-do listing and we are able to create a minimal mannequin for demonstration functions.

Go

  func Test_wellFormedHtml(t *testing.T) {
    templ := template.Should(template.ParseFiles("index.tmpl"))
    mannequin := todo.NewList()
    _ = templ
    _ = mannequin
  }

Java

  @Check
  void indexIsSoundHtml() {
      var template = Mustache.compiler().compile(
              new InputStreamReader(
                      getClass().getResourceAsStream("/index.tmpl")));
      var mannequin = new TodoList();
  }

Now we render the template, saving the leads to a byte buffer (Go) or as a String (Java).

Go

  func Test_wellFormedHtml(t *testing.T) {
    templ := template.Should(template.ParseFiles("index.tmpl"))
    mannequin := todo.NewList()
    var buf bytes.Buffer
    err := templ.Execute(&buf, mannequin)
    if err != nil {
      panic(err)
    }
  }

Java

  @Check
  void indexIsSoundHtml() {
      var template = Mustache.compiler().compile(
              new InputStreamReader(
                      getClass().getResourceAsStream("/index.tmpl")));
      var mannequin = new TodoList();
  
      var html = template.execute(mannequin);
  }

At this level we would like parse the HTML and we anticipate to see an error, as a result of in our damaged HTML there’s a div component that’s closed by a p component. There may be an HTML parser within the Go commonplace library, nevertheless it’s too forgiving: if we run it on our damaged HTML, we do not get an error. Luckily, the Go commonplace library additionally has an XML parser that may be configured to parse HTML (because of this stack overflow reply)

Go

  func Test_wellFormedHtml(t *testing.T) {
    templ := template.Should(template.ParseFiles("index.tmpl"))
    mannequin := todo.NewList()
    
    // render the template right into a buffer
    var buf bytes.Buffer
    err := templ.Execute(&buf, mannequin)
    if err != nil {
      panic(err)
    }
  
    // test that the template could be parsed as (lenient) XML
    decoder := xml.NewDecoder(bytes.NewReader(buf.Bytes()))
    decoder.Strict = false
    decoder.AutoClose = xml.HTMLAutoClose
    decoder.Entity = xml.HTMLEntity
    for {
      _, err := decoder.Token()
      swap err {
      case io.EOF:
        return // We're carried out, it is legitimate!
      case nil:
        // do nothing
      default:
        t.Fatalf("Error parsing html: %s", err)
      }
    }
  }

fountain

This code configures the HTML parser to have the proper stage of leniency for HTML after which parses the HTML token by token. In actual fact, we see the error message we wished:

--- FAIL: Test_wellFormedHtml (0.00s)
    index_template_test.go:61: Error parsing html: XML syntax error on line 4: sudden finish component 

In Java, a flexible library to make use of is jsoup:

Java

  @Check
  void indexIsSoundHtml() {
      var template = Mustache.compiler().compile(
              new InputStreamReader(
                      getClass().getResourceAsStream("/index.tmpl")));
      var mannequin = new TodoList();
  
      var html = template.execute(mannequin);
  
      var parser = Parser.htmlParser().setTrackErrors(10);
      Jsoup.parse(html, "", parser);
      assertThat(parser.getErrors()).isEmpty();
  }

fountain

And we see it fail:

java.lang.AssertionError: 
Anticipating empty however was:<(<1:13>: Sudden EndTag token () when in state (InBody),

Success! Now if we copy TodoMVC template content material to our index.tmpl file, the check passes.

The proof, nevertheless, is simply too detailed: we extract two auxiliary capabilities to make clear the intent of the proof and acquire

Go

  func Test_wellFormedHtml(t *testing.T) {
    mannequin := todo.NewList()
  
    buf := renderTemplate("index.tmpl", mannequin)
  
    assertWellFormedHtml(t, buf)
  }

fountain

Java

  @Check
  void indexIsSoundHtml() {
      var mannequin = new TodoList();
  
      var html = renderTemplate("/index.tmpl", mannequin);
  
      assertSoundHtml(html);
  }

fountain

Stage 2: Check the HTML construction

What else ought to we strive?

We all know that finally solely a human can check the look of a web page and see the way it renders in a browser. Nevertheless, there may be typically logic in templates and we would like to have the ability to check that logic.

One is likely to be tempted to strive rendered HTML with string equality, however this system fails in follow, as a result of templates comprise many particulars that make string equality assertions impractical. The claims develop into very detailed and when studying them it’s obscure what we try to show.

What we’d like is a method to claim that some components of the rendered HTML correspond to what we anticipate, since ignore all the small print that do not matter to us. A method to do that is by operating queries with the CSS selector language: is a strong language that enables us to pick the weather that curiosity us from the complete HTML doc. As soon as we’ve chosen these parts, we (1) depend that the variety of parts returned is what we anticipate and (2) that they comprise the textual content or different content material we anticipate.

The UI we’re speculated to generate appears like this:

There are a number of particulars which are rendered dynamically:

  1. The variety of parts and their textual content material change, clearly.
  2. The fashion of the duty merchandise adjustments when it’s accomplished (for instance, the second)
  3. The “2 objects left” textual content will change based mostly on the variety of uncompleted objects
  4. One of many three buttons “All”, “Lively”, “Accomplished” shall be highlighted, relying on the present URL; for instance, if we determine that the URL that shows solely “lively” objects is /livelythen when the present url is /livelythe “Lively” button ought to be surrounded by a skinny purple rectangle
  5. The “Clear Accomplished” button ought to solely be seen if any merchandise is accomplished

Every of those considerations could be examined with the assistance of CSS selectors.

This can be a snippet of the TodoMVC template (barely simplified). I have not added the dynamic bits but, so what we see right here is static content material, supplied for instance:

index.tmpl

  

fountain

Related Articles

Latest Articles