flutterflutter-webflutter-testflutter-web-browserflutter-js

Mock JS object in tests on browser platform


I have this simplified dart file using dart:js:

(dataLayer is used for Google tags, if that's any help)

@JS()
import 'package:js/js.dart';

@JS('dataLayer.push')
external void _push(data);

class Manager {
  void pushEvent(String event) {
    _push(event);
  }
}

On the web, it runs correctly and the dataLayer object is being created in a script in the web/index.html file.


I am trying to write a test about it. I would like to verify dataLayer.push is being called with the correct parameters.

I run my test with the command

flutter test --platform chrome

But I get this error:

TypeError: Cannot read properties of undefined (reading 'push')

Is it possible to create a dummy dataLayer variable (and maybe have the hand on it to record the calls to the method .push())? If yes, how?

Here is my attempt:

@TestOn('browser')

import 'package:flutter_test/flutter_test.dart';
import 'package:js/js.dart';
import 'my_project/my_file.dart';

class _DataLayer {
  void push(dynamic data) {}
}

@JS('dataLayer')
final dataLayer = _DataLayer();

void main() {
  test('It should push the event', () {
    Manager().pushEvent('myEvent');
  });
}

Solution

  • A way to do it would be to load and use a custom HTML file during the tests where you can include a script to create the js variables you need.

    Follow the instructions of the package test.

    If your test file name is folder/my_test.dart, then you can create a html file named (folder/my_test.html):

    <!doctype html>
    <html>
    
    <head>
      <title>Custom HTML file title</title>
      <link rel="x-dart-test" href="my_test.dart">
      <script src="packages/test/dart.js"></script>
      <script>
        window['dataLayer'] = [];
      </script>
    </head>
    
    </html>
    

    See this StackOverflow answer and this StackOverflow question.

    and then you can run

    dart test --platform chrome
    

    However, this is only supported with dart test and not flutter test, see this issue. In it, they recommend writing an integration test instead.