Dart/Flutter Web unit testing errors: Error: Not found: 'dart:html'
Asked Answered
R

10

49

I'm working on a Flutter web app and I'm having trouble running a test.

Flutter 1.7.8+hotfix.4 • channel stable • [email protected]:flutter/flutter.git
Framework • revision 20e59316b8 (9 weeks ago) • 2019-07-18 20:04:33 -0700
Engine • revision fee001c93f
Tools • Dart 2.4.0

This is the pubspec.yaml:

name: web_flutter
description: An app built using Flutter for web

environment:
  # You must be using Flutter >=1.5.0 or Dart >=2.3.0
  sdk: '>=2.3.0-dev.0.1 <3.0.0'

dependencies:
  flutter_web: any
  flutter_web_ui: any
  provider: any
  rxdart: ^0.22.0
  http: ^0.12.0+2
  json_annotation: ^2.4.0
  intl: 0.15.8


dev_dependencies:
  build_runner: ^1.4.0
  build_web_compilers: ^2.0.0
  pedantic: ^1.0.0
  json_serializable: ^3.0.0
  test: any

flutter:
  uses-material-design: true

dependency_overrides:
  flutter_web:
    git:
      url: https://github.com/flutter/flutter_web
      path: packages/flutter_web
  flutter_web_ui:
    git:
      url: https://github.com/flutter/flutter_web
      path: packages/flutter_web_ui
  provider:
    git:
      url: https://github.com/kevmoo/provider
      ref: flutter_web

I wrote a couple of tests that are passing when I run pub run test in either the IDE's terminal (VS Code) or in terminal app.

The test I'm having trouble with requires some package imports from the project. With this test in place I get errors and the other two tests don't run. I haven't found anything that points to a solution.

This is the error message:

pub run test                                                                                         MyMac@MyMac
00:06 +0 -1: loading test/service_test.dart [E]                                                                                                                          
  Failed to load "test/service_test.dart":
  Unable to spawn isolate: file:///Users/MyMac/.pub-cache/git/flutter_web-c04fb502b842859de07e36954a9390465a5426c0/packages/flutter_web_ui/lib/ui.dart:12:8: Error: Not found: 'dart:html'
  import 'dart:html' as html;
         ^
  file:///Users/MyMac/.pub-cache/git/flutter_web-c04fb502b842859de07e36954a9390465a5426c0/packages/flutter_web_ui/lib/src/engine.dart:11:8: Error: Not found: 'dart:html'
  import 'dart:html' as html;
         ^
  file:///Users/MyMac/.pub-cache/git/flutter_web-c04fb502b842859de07e36954a9390465a5426c0/packages/flutter_web/lib/src/services/asset_bundle.dart:7:8: Error: Not found: 'dart:html'
  import 'dart:html' show HttpRequest;
         ^
  file:///Users/MyMac/.pub-cache/git/flutter_web-c04fb502b842859de07e36954a9390465a5426c0/packages/flutter_web_ui/lib/src/engine.dart:12:8: Error: Not found: 'dart:js'
  import 'dart:js' as js;
         ^
  file:///Users/MyMac/.pub-cache/git/flutter_web-c04fb502b842859de07e36954a9390465a5426c0/packages/flutter_web_ui/lib/src/engine.dart:13:8: Error: Not found: 'dart:js_util'
  import 'dart:js_util' as js_util;
         ^
  file:///Users/MyMac/.pub-cache/git/flutter_web-c04fb502b842859de07e36954a9390465a5426c0/packages/flutter_web_ui/lib/src/ui/compositing.dart:20:9: Error: Type 'html.Element' not found.
    final html.Element webOnlyRootElement;
          ^^^^^^^^^^^^
  file:///Users/MyMac/.pub-cache/git/flutter_web-c04fb502b842859de07e36954a9390465a5426c0/packages/flutter_web_ui/lib/src/engine.dart:177:37: Error: Type 'html.NodeTreeSanitizer' not found.
  class _NullTreeSanitizer implements html.NodeTreeSanitizer {
                                      ^^^^^^^^^^^^^^^^^^^^^^
  file:///Users/MyMac/.pub-cache/git/flutter_web-c04fb502b842859de07e36954a9390465a5426c0/packages/flutter_web_ui/lib/src/engine.dart:179:21: Error: Type 'html.Node' not found.
    void sanitizeTree(html.Node node) {}
                      ^^^^^^^^^
  file:///Users/MyMac/.pub-cache/git/flutter_web-c04fb502b842859de07e36954a9390465a5426c0/packages/flutter_web_ui/lib/src/engine/bitmap_canvas.dart:26:9: Error: Type 'html.Element' not found.
    final html.Element rootElement = html.Element.tag('flt-canvas');
          ^^^^^^^^^^^^
  file:///Users/MyMac/.pub-cache/git/flutter_web-c04fb502b842859de07e36954a9390465a5426c0/packages/flutter_web_ui/lib/src/engine/bitmap_canvas.dart:28:3: Error: Type 'html.CanvasElement' not found.
    html.CanvasElement _canvas;
    ^^^^^^^^^^^^^^^^^^
00:06 +0 -1: Some tests failed.

If I comment out this new test, the errors persist. If I comment out the test and the related imports the remaining two tests run and pass.

This is the test file (I left the offending code commented out so it's easier for you to see - I hope).

import 'package:test/test.dart';
import 'package:http/http.dart';
import 'package:http/testing.dart';
import 'dart:convert';
import 'package:web_flutter/services/service.dart';
// These are the package imports that cause errors:
import 'package:web_flutter/model/model.dart';
import 'package:web_flutter/data/tenant_view_model.dart';

void main(){

  test("getSubmission returns ResponseData{}", () async {
    // Arrange: setup the test
    final _service = Service();

    _service.httpClient = MockClient((request) async {
      final responseData = {
        "id": "some_id",
        "state": "processed",
        "test": true,
        "editable": false,
        "expires_at": "2019-09-19T03:40:22Z",
        "processed_at": "2019-09-12T03:40:22Z",
        "batch_id": "",
        "download_url": "downloadURl.com",
        "permanent_download_url": "permanentdownloadURL.com"
      };
      return Response(json.encode(responseData),200);
    });

    // Act
    final response = await _service.getSubmission("submissionID");

    // Assert
    expect(response.download_url, "downloadURL.com");
  });
  test("generateForm returns SubmissionResponse{}", () async {
    // Arrange: setup the test
    final _service = Service();

    _service.httpClient = MockClient((request) async {
      final submissionResponse = {
        "status": "success",
        "submission": {
          "id": "some_id",
          "state": "pending",
          "test": false,
          "editable": false,
          "expired": false,
          "expires_at": null,
          "metadata": {
            "foo": 123,
            "bar": "baz"
          },
          "processed_at": null,
          "batch_id": null,
          "data_requests": [],
          "download_url": null,
          "permanent_download_url": null
        }
      };
      return Response(json.encode(submissionResponse),200);
    });

    // Act
    final response = await _service.generateForm(42, "templateID");

    // Assert
    expect(response.submission.id, "some_id");
  });

  test('Tenant View Model generateForm returns tenantVM.submission.submission.id', () async {
    // Arrange
    final _service = Service();
    Tenant tenant;
    tenant.id = 42;

    _service.httpClient = MockClient((request) async {
      final submissionResponse = {
        "status": "success",
        "submission": {
          "id": "some_id",
          "state": "pending",
          "test": false,
          "editable": false,
          "expired": false,
          "expires_at": null,
          "metadata": {
            "foo": 123,
            "bar": "baz"
          },
          "processed_at": null,
          "batch_id": null,
          "data_requests": [],
          "download_url": null,
          "permanent_download_url": null
        }
      };
      return Response(json.encode(submissionResponse),200);
    });
    TenantViewModel tenantVM = TenantViewModel(tenant, _service);

    // Act
    await tenantVM.generateForm("templateID");

    // Assert
    expect(tenantVM.submission.submission.id, "some_id");
  });
}

This is the class that has the method I'm trying to test (generateForm()).

import 'package:flutter_web/cupertino.dart';
import 'package:web_flutter/model/model.dart';
import 'package:web_flutter/services/service.dart';

class TenantViewModel with ChangeNotifier {
  Tenant _tenant;
  Property _property;
  Service _service;
  SubmissionResponse _submission;
  ResponseData _responseData;

  TenantViewModel(this._tenant, this._service);

  bool get isNew => _tenant.id == null;

  set tenant(Tenant tenant) {
    if (_tenant != tenant) {
      _tenant = tenant;
      notifyListeners();
    }
  }

  Tenant get tenant => _tenant;

  set property(Property property) {
    _tenant.propertyId = property.id;
    notifyListeners();
  }

  Property get property => _property;

  set submission(SubmissionResponse submission) {
    if (_submission != submission) {
      _submission = submission;
      notifyListeners();
    }
  }

  SubmissionResponse get submission => _submission;

  set responseData(ResponseData responseData) {
    if (_responseData != responseData) {
      _responseData = responseData;
      notifyListeners();
    }
  }

  ResponseData get responseData => _responseData;

  Future generateForm(String templateID) async {
    SubmissionResponse submission;

    submission = await _service.generateForm(_tenant.id, templateID);
    this.submission = submission;

    notifyListeners();
  }

  Future getSubmission(String submissionID) async {
    ResponseData responseData;

    responseData = await _service.getSubmission(submissionID);
    this.responseData = responseData;

    notifyListeners();
  }

  Future save() async {
    Tenant updatedTenant;
    if (tenant.isNew) {
      updatedTenant = await _service.createTenant(_tenant);
      this.tenant = updatedTenant;
    } else {
      updatedTenant = await _service.updateTenant(tenant);
      this.tenant = updatedTenant;
    }
    notifyListeners();
  }

  Future refresh() async {
    if (isNew) {
      return;
    }
    var updatedTenant = await _service.getTenant(_tenant.id);
    if (_tenant.propertyId != null) {
      _property = await _service.getProperty(_tenant.propertyId);
    }
    _tenant = updatedTenant;
    notifyListeners();
  }
}

I have tried: import 'package:flutter_test/flutter_test.dart'; in the test file and adding this to the pubspec.yaml:

  flutter_test:
    sdk: flutter

These cause their own varieties of errors, because I'm using Flutter Web, not Flutter. Can anyone see where I'm going wrong?

I am aware that the test I'm working on is probably wrong as it is, but I can't even get to the point of having it run and fail.

Referent answered 17/9, 2019 at 21:50 Comment(3)
unit tests do not have access to dart:html Unless you run them in the browserReferent
From pub.dev/packages/test: "By default, tests are run in the Dart VM, but you can run them in the browser as well by passing pub run test -p chrome path/to/test.dart. test will take care of starting the browser and loading the tests, and all the results will be reported on the command line just like for VM tests. In fact, you can even run tests on both platforms with a single command: pub run test -p "chrome,vm" path/to/test.dart"Referent
any way to run them on a browser for web integration tests, where I'm running a command like this: flutter drive --target=test_driver/file_storage.dart -v --use-existing-app=/localhost:53201Spinal
C
99

I had a similar issue while developing for a mobile app, but it turned out that I imported the package dart.html accidentally. I just removed it and I was able to run the program.

Choochoo answered 30/7, 2020 at 15:51 Comment(6)
thanks, this is exactly what happened to me as well!Windowshop
I've done this exact mistake several times now. It's always when I try to import @required I thinkYadirayaeger
or you may have added some other package by mistake which you are not supposed addSyracuse
I think this is not accidental, cause I also have this error but didn't import dart.htmlBelloir
what if we need dart.html ???Aim
Thanks, This was my issue.Johnsen
F
27

Since you are running flutter tests for web that use the dart:html package you must target the correct platform.

flutter test --platform chrome

Fredrika answered 12/12, 2019 at 15:23 Comment(0)
A
17

It can happen when you try to import something like @required. Then flutter will accidentally put import dart.html above the code. Just remove that from the code and then you will fix your issue.

Araby answered 28/4, 2021 at 13:18 Comment(0)
V
4

Change import 'dart:html'; to import 'package:http/http.dart' as http;

and then change pubspec.yaml files dependencies to

dependencies:
flutter:
sdk: flutter
http:

and click pub get

Verruca answered 28/10, 2020 at 13:2 Comment(1)
Thanks champ you the bestStraub
P
4

In which file you had added import 'dart:html' just remove this and then execute the code again. I think the problem will be solved. Following this i had solved my problem.

Provincial answered 23/12, 2021 at 15:54 Comment(0)
R
3

The problem comes because, as my tech lead pointed out, "Unit tests do not have access to dart:html. Unless you run them in the browser."

From pub.dev/packages/test:

"By default, tests are run in the Dart VM [virtual machine], but you can run them in the browser as well by passing pub run test -p chrome path/to/test.dart. test will take care of starting the browser and loading the tests, and all the results will be reported on the command line just like for VM tests. In fact, you can even run tests on both platforms with a single command: pub run test -p "chrome,vm" path/to/test.dart"

To solve my particular problem I ran the tests using pub run test test/print_reports_card_test.dart -p chrome.

Referent answered 19/9, 2019 at 17:19 Comment(2)
This answer needs improvement in that it does not address why the previous tests passed, but the new test did not. The question is when and where is dart:html being imported? I had imported it in another file, but removing the import did not solve the problem so it is being imported by some dependency, I think.Referent
-p did not work in IntelliJ but --platform did. Was complaining "invalid parameter".Delius
C
3

removing import 'dart:html';

from the file worked for me also changing platform to chrome works

Chromatic answered 29/10, 2022 at 8:39 Comment(0)
I
3

You need to do some conditional import and implement the components you accessed in "dart:html" to your own file

Here's an example in a case where I am making use of dart:html's window.open

window_service.dart

Window window = Window();

class Window {
  void open(String url, String name, [String? options]) {}
}

with the above you can do:

import "window_service.dart" if (kIsWeb) "dart:html" as html;
...
html.window.open(url, name, options);

Do the same for every dart:html calls you made by implementing them with similar/same structure in the dummy file (window_service.dart). Then you may now run your tests without error.

Illiberal answered 25/1, 2023 at 15:56 Comment(3)
Its a clever answer but actually did not solve the problem. It will still not being able to run the app in Android/IOS because the methods will need the html package.Auntie
I realised this just a while ago.. it's true this one doesn't work.. unfortunately. I hope there is a similar solution like this thoughIlliberal
I found a "solution" that is working for me. I keep all methods that need html package (most upload to firebase storage) in a single file. Whenever I am working in web mode, I use it. When I switch back to work on apps I comment it.Auntie
K
1

Another solution in case you have tests for both web and mobile is to add @TestOn('browser') at the top of your test file.
Here's the full doc

Kilter answered 19/8, 2020 at 9:14 Comment(0)
G
1

enter image description here

This error sometimes occurs when the language mode is out of place. Ensure that the "select language mode" (The yellow circle in the image) is on the right mode. For this instance it should be Dart

Ginsberg answered 28/4, 2021 at 11:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.