Search code examples
htmlwebdarttdd

How to test (TDD) an `HtmlDocument` in Dart?


1. The Problem

I'm trying to create a browser extension in Dart. Currently, I'm using the webext package, which basically emulates the typical JS environment in Dart.

In the main() function of content.dart file, I wish to manipulate the DOM. The document variable is available and is of type HtmlDocument, which comes from dart:html. This is all well and good, but how would you create a testing harness with that, considering HtmlDocument doesn't have a public constructor?

2. What I've tried so far

I've tried to use the parent of HtmlDocument, i.e., Document. Something like this for a custom HTML tag:

import 'dart:html';

void main() {
  final Document document = Document();
  document.registerElement(CustomElement.tag, CustomElement);
  document.createElement(CustomElement.tag);
}

class CustomElement extends HtmlElement {
  static const String tag = 'custom-tag';

  factory CustomElement.created() => null;
}

But the Document class doesn't have the necessary API and registering custom tags is not supported apparently — the supportsRegisterElement getter gives me back false, which might be related to Chrome or Dartium, I'm not sure.


Solution

  • I still don't know why creating a custom HtmlElement isn't working in this case, but there's a good enough way around the overall problem: DomParser.

    You can use the parseFromString method to parse an HTML string into a Document and use it as a simplified way to test your code. The DomParser's behavior emulates the its JS counterpart: DOMParser.

    An example:

    import 'dart:html' show Document, DomParser, Element;
    
    import 'package:test/test.dart' show expect, test;
    
    void main() {
      const String htmlAsString = '<p>A paragraph</p>';
      
      final Document document = DomParser().parseFromString(htmlAsString, 'text/html');
      
      test('Checking the text inside the paragraph', () {
        final Element paragraph = document.querySelector('p');
      
        expect(paragraph.text, 'A paragraph');
      });
    }
    

    Note that using dart:io to open the HTML fixtures/fakes/mocks won't be possible because most of its functionalities aren't supported by the browser.

    Custom tags can also be used in the stringed HTML above, they won't have custom classes, they will all be of runtime type HtmlElement, which is a subclass of Element. The parser will be able to handle them by changing/initializing their tagNames in the background — it actually basically seems to do this for all tags.