content: @TestOn('browser')
  library;
  
  import 'package:js/js.dart';
  import 'package:node_interop/js.dart';
  import 'package:node_interop/util.dart';
  import 'package:sass/src/js/compile_options.dart';
  import 'package:sass/src/js/legacy/render_options.dart';
  import 'package:sass/src/js/legacy/render_result.dart';
  import 'package:test/test.dart';
  import 'ensure_npm_package.dart';
  import 'package:sass/src/js/compile_result.dart';
  
  @JS()
  external Sass get sass;
  
  @JS()
  class Sass {
    external NodeCompileResult compileString(
      String text, [
      CompileStringOptions? options,
    ]);
    external Promise compileStringAsync(
      String text, [
      CompileStringOptions? options,
    ]);
    external NodeCompileResult compile(String path, [CompileOptions? options]);
    external Promise compileAsync(String path, [CompileOptions? options]);
    external void render(
      RenderOptions options,
      void callback(Error error, RenderResult result),
    );
    external RenderResult renderSync(RenderOptions options);
    external String get info;
  }
  
  void main() {
    setUpAll(ensureNpmPackage);
  
    test('compileAsync() is not available', () {
      expect(
        () => sass.compileAsync('index.scss'),
        throwsA(
          predicate((error) {
            expect(error, const TypeMatcher<JsError>());
            expect(
              error.toString(),
              startsWith(
                "Error: The compileAsync() method is only available in Node.js.",
              ),
            );
            return true;
          }),
        ),
      );
    });
  
    test('compile() is not available', () {
      expect(
        () => sass.compile('index.scss'),
        throwsA(
          predicate((error) {
            expect(error, const TypeMatcher<JsError>());
            expect(
              error.toString(),
              startsWith(
                "Error: The compile() method is only available in Node.js.",
              ),
            );
            return true;
          }),
        ),
      );
    });
  
    test('render() is not available', () {
      expect(
        () => sass.render(RenderOptions(), allowInterop((error, result) {})),
        throwsA(
          predicate((error) {
            expect(error, const TypeMatcher<JsError>());
            expect(
              error.toString(),
              startsWith(
                "Error: The render() method is only available in Node.js.",
              ),
            );
            return true;
          }),
        ),
      );
    });
  
    test('renderSync() is not available', () {
      expect(
        () => sass.renderSync(RenderOptions()),
        throwsA(
          predicate((error) {
            expect(error, const TypeMatcher<JsError>());
            expect(
              error.toString(),
              startsWith(
                "Error: The renderSync() method is only available in Node.js.",
              ),
            );
            return true;
          }),
        ),
      );
    });
  
    test('info produces output', () {
      expect(sass.info, startsWith("dart-sass\t"));
    });
  
    test('compileString() produces output', () {
      var result = sass.compileString('foo {bar: baz}');
      expect(result.css, equals('foo {\n  bar: baz;\n}'));
    });
  
    test('compileString() produces a sourceMap', () {
      var opts = jsify({'sourceMap': true}) as CompileStringOptions;
      var result = sass.compileString('foo {bar: baz}', opts);
      expect(result.sourceMap, isA<Object>());
  
      var sourceMap = result.sourceMap!;
  
      expect(getProperty<num>(sourceMap, 'version'), isA<num>());
      expect(getProperty<List<dynamic>>(sourceMap, 'sources'), isList);
      expect(getProperty<List<dynamic>>(sourceMap, 'names'), isList);
      expect(getProperty<String>(sourceMap, 'mappings'), isA<String>());
    });
  
    test('compileString() produces a sourceMap with source content', () {
      var opts = jsify({'sourceMap': true, 'sourceMapIncludeSources': true})
          as CompileStringOptions;
      var result = sass.compileString('foo {bar: baz}', opts);
      expect(result.sourceMap, isA<Object>());
  
      var sourceMap = result.sourceMap!;
  
      expect(getProperty<List<dynamic>>(sourceMap, 'sourcesContent'), isList);
      expect(getProperty<List<dynamic>>(sourceMap, 'sourcesContent'), isNotEmpty);
    });
  
    test('compileStringAsync() produces output', () async {
      var result = sass.compileStringAsync('foo {bar: baz}');
      result = await promiseToFuture(result);
      expect((result as NodeCompileResult).css, equals('foo {\n  bar: baz;\n}'));
    });
  
    test('compileStringAsync() produces a sourceMap', () async {
      var opts = jsify({'sourceMap': true}) as CompileStringOptions;
      var result = sass.compileStringAsync('foo {bar: baz}', opts);
      result = await promiseToFuture(result);
      var sourceMap = (result as NodeCompileResult).sourceMap;
  
      expect(sourceMap, isA<Object>());
  
      sourceMap = sourceMap!;
  
      expect(getProperty<num>(sourceMap, 'version'), isA<num>());
      expect(getProperty<List<dynamic>>(sourceMap, 'sources'), isList);
      expect(getProperty<List<dynamic>>(sourceMap, 'names'), isList);
      expect(getProperty<String>(sourceMap, 'mappings'), isA<String>());
    });
  
    test(
      'compileStringAsync() produces a sourceMap with source content',
      () async {
        var opts = jsify({'sourceMap': true, 'sourceMapIncludeSources': true})
            as CompileStringOptions;
        var result = sass.compileStringAsync('foo {bar: baz}', opts);
        result = await promiseToFuture(result);
        var sourceMap = (result as NodeCompileResult).sourceMap;
  
        expect(sourceMap, isA<Object>());
  
        sourceMap = sourceMap!;
  
        expect(getProperty<List<dynamic>>(sourceMap, 'sourcesContent'), isList);
        expect(
          getProperty<List<dynamic>>(sourceMap, 'sourcesContent'),
          isNotEmpty,
        );
      },
    );
  
    test('compileString() throws error if importing without custom importer', () {
      expect(
        () => sass.compileString("@use 'other';"),
        throwsA(
          predicate((error) {
            expect(error, const TypeMatcher<JsError>());
            expect(
              error.toString(),
              startsWith(
                "Custom importers are required to load stylesheets when compiling in the browser.",
              ),
            );
            return true;
          }),
        ),
      );
    });
  
    test(
      'compileStringAsync() throws error if importing without custom importer',
      () async {
        var result = sass.compileStringAsync("@use 'other';");
        expect(
          () async => await promiseToFuture<NodeCompileResult>(result),
          throwsA(
            predicate((error) {
              expect(error, const TypeMatcher<JsError>());
              expect(
                error.toString(),
                startsWith(
                  "Custom importers are required to load stylesheets when compiling in the browser.",
                ),
              );
              return true;
            }),
          ),
        );
      },
    );
  }
  