content: // Copyright 2024 Google Inc. Use of this source code is governed by an
  // MIT-style license that can be found in the LICENSE file or at
  // https://opensource.org/licenses/MIT.
  
  import 'package:test/test.dart';
  import 'package:test_descriptor/test_descriptor.dart' as d;
  import 'package:test_process/test_process.dart';
  
  /// Defines test that are shared between the Dart and Node.js CLI test suites.
  void sharedTests(Future<TestProcess> runSass(Iterable<String> arguments)) {
    // Test complaining about invalid deprecations, combinations, etc
  
    group("--silence-deprecation", () {
      group("prints a warning", () {
        setUp(() => d.file("test.scss", "").create());
  
        test("for user-authored", () async {
          var sass = await runSass([
            "--silence-deprecation=user-authored",
            "test.scss",
          ]);
          expect(sass.stderr, emits(contains("User-authored deprecations")));
          await sass.shouldExit(0);
        });
  
        test("for an obsolete deprecation", () async {
          var sass = await runSass([
            "--silence-deprecation=mixed-decls",
            "test.scss",
          ]);
          expect(sass.stderr,
              emits(contains("mixed-decls deprecation is obsolete")));
          await sass.shouldExit(0);
        });
  
        test("for an inactive future deprecation", () async {
          var sass = await runSass(["--silence-deprecation=import", "test.scss"]);
          expect(sass.stderr, emits(contains("Future import deprecation")));
          await sass.shouldExit(0);
        }, skip: true);
  
        test("for an active future deprecation", () async {
          var sass = await runSass([
            "--future-deprecation=import",
            "--silence-deprecation=import",
            "test.scss",
          ]);
          expect(sass.stderr, emits(contains("Conflicting options for future")));
          await sass.shouldExit(0);
        }, skip: true);
  
        test("in watch mode", () async {
          var sass = await runSass([
            "--watch",
            "--poll",
            "--silence-deprecation=user-authored",
            "test.scss:out.css",
          ]);
          expect(sass.stderr, emits(contains("User-authored deprecations")));
  
          await expectLater(
            sass.stdout,
            emitsThrough(endsWith('Compiled test.scss to out.css.')),
          );
          await sass.kill();
        });
  
        test("in repl mode", () async {
          var sass = await runSass([
            "--interactive",
            "--silence-deprecation=user-authored",
          ]);
          await expectLater(
            sass.stderr,
            emits(contains("User-authored deprecations")),
          );
          await sass.kill();
        });
      });
  
      group("throws an error for an unknown deprecation", () {
        setUp(() => d.file("test.scss", "").create());
  
        test("in immediate mode", () async {
          var sass = await runSass([
            "--silence-deprecation=unknown",
            "test.scss",
          ]);
          expect(sass.stdout, emits(contains('Invalid deprecation "unknown".')));
          await sass.shouldExit(64);
        });
  
        test("in watch mode", () async {
          var sass = await runSass([
            "--watch",
            "--poll",
            "--silence-deprecation=unknown",
            "test.scss:out.css",
          ]);
          expect(sass.stdout, emits(contains('Invalid deprecation "unknown".')));
          await sass.shouldExit(64);
        });
  
        test("in repl mode", () async {
          var sass = await runSass([
            "--interactive",
            "--silence-deprecation=unknown",
          ]);
          expect(sass.stdout, emits(contains('Invalid deprecation "unknown".')));
          await sass.shouldExit(64);
        });
      });
  
      group("silences", () {
        group("a parse-time deprecation", () {
          setUp(
            () => d.file("test.scss", "@if true {} @elseif false {}").create(),
          );
  
          test("in immediate mode", () async {
            var sass = await runSass([
              "--silence-deprecation=elseif",
              "test.scss",
            ]);
            expect(sass.stderr, emitsDone);
            await sass.shouldExit(0);
          });
  
          test("in watch mode", () async {
            var sass = await runSass([
              "--watch",
              "--poll",
              "--silence-deprecation=elseif",
              "test.scss:out.css",
            ]);
            expect(sass.stderr, emitsDone);
  
            await expectLater(
              sass.stdout,
              emitsThrough(endsWith('Compiled test.scss to out.css.')),
            );
            await sass.kill();
          });
  
          test("in repl mode", () async {
            var sass = await runSass([
              "--interactive",
              "--silence-deprecation=strict-unary",
            ]);
            expect(sass.stderr, emitsDone);
            sass.stdin.writeln("4 -(5)");
            await expectLater(sass.stdout, emitsInOrder([">> 4 -(5)", "-1"]));
            await sass.kill();
          });
        });
  
        group("an evaluation-time deprecation", () {
          setUp(
            () => d.file("test.scss", """
              @use 'sass:math';
              a {b: math.random(1px)}
            """).create(),
          );
  
          test("in immediate mode", () async {
            var sass = await runSass([
              "--silence-deprecation=function-units",
              "test.scss",
            ]);
            expect(sass.stderr, emitsDone);
            await sass.shouldExit(0);
          });
  
          test("in watch mode", () async {
            var sass = await runSass([
              "--watch",
              "--poll",
              "--silence-deprecation=function-units",
              "test.scss:out.css",
            ]);
            expect(sass.stderr, emitsDone);
  
            await expectLater(
              sass.stdout,
              emitsThrough(endsWith('Compiled test.scss to out.css.')),
            );
            await sass.kill();
          });
  
          test("in repl mode", () async {
            var sass = await runSass([
              "--interactive",
              "--silence-deprecation=function-units",
            ]);
            expect(sass.stderr, emitsDone);
            sass.stdin.writeln("@use 'sass:math'");
            await expectLater(sass.stdout, emits(">> @use 'sass:math'"));
            sass.stdin.writeln("math.random(1px)");
            await expectLater(
              sass.stdout,
              emitsInOrder([">> math.random(1px)", "1"]),
            );
            await sass.kill();
          });
        });
      });
    });
  
    group("--fatal-deprecation", () {
      group("prints a warning", () {
        setUp(() => d.file("test.scss", "").create());
  
        test("for an obsolete deprecation", () async {
          var sass = await runSass([
            "--fatal-deprecation=mixed-decls",
            "test.scss",
          ]);
          expect(sass.stderr,
              emits(contains("mixed-decls deprecation is obsolete")));
          await sass.shouldExit(0);
        });
  
        test("for an inactive future deprecation", () async {
          var sass = await runSass(["--fatal-deprecation=import", "test.scss"]);
          expect(sass.stderr, emits(contains("Future import deprecation")));
          await sass.shouldExit(0);
        }, skip: true);
  
        test("for a silent deprecation", () async {
          var sass = await runSass([
            "--fatal-deprecation=elseif",
            "--silence-deprecation=elseif",
            "test.scss",
          ]);
          expect(sass.stderr, emits(contains("Ignoring setting to silence")));
          await sass.shouldExit(0);
        });
  
        test("in watch mode", () async {
          var sass = await runSass([
            "--watch",
            "--poll",
            "--fatal-deprecation=elseif",
            "--silence-deprecation=elseif",
            "test.scss:out.css",
          ]);
          expect(sass.stderr, emits(contains("Ignoring setting to silence")));
  
          await expectLater(
            sass.stdout,
            emitsThrough(endsWith('Compiled test.scss to out.css.')),
          );
          await sass.kill();
        });
  
        test("in repl mode", () async {
          var sass = await runSass([
            "--interactive",
            "--fatal-deprecation=elseif",
            "--silence-deprecation=elseif",
          ]);
          await expectLater(
            sass.stderr,
            emits(contains("Ignoring setting to silence")),
          );
          await sass.kill();
        });
      });
  
      group("throws an error for", () {
        group("an unknown deprecation", () {
          setUp(() => d.file("test.scss", "").create());
  
          test("in immediate mode", () async {
            var sass = await runSass([
              "--fatal-deprecation=unknown",
              "test.scss",
            ]);
            expect(
              sass.stdout,
              emits(contains('Invalid deprecation "unknown".')),
            );
            await sass.shouldExit(64);
          });
  
          test("in watch mode", () async {
            var sass = await runSass([
              "--watch",
              "--poll",
              "--fatal-deprecation=unknown",
              "test.scss:out.css",
            ]);
            expect(
              sass.stdout,
              emits(contains('Invalid deprecation "unknown".')),
            );
            await sass.shouldExit(64);
          });
  
          test("in repl mode", () async {
            var sass = await runSass([
              "--interactive",
              "--fatal-deprecation=unknown",
            ]);
            expect(
              sass.stdout,
              emits(contains('Invalid deprecation "unknown".')),
            );
            await sass.shouldExit(64);
          });
        });
  
        group("a parse-time deprecation", () {
          setUp(
            () => d.file("test.scss", "@if true {} @elseif false {}").create(),
          );
  
          test("in immediate mode", () async {
            var sass = await runSass(["--fatal-deprecation=elseif", "test.scss"]);
            expect(sass.stderr, emits(startsWith("Error: ")));
            await sass.shouldExit(65);
          });
  
          test("in watch mode", () async {
            var sass = await runSass([
              "--watch",
              "--poll",
              "--fatal-deprecation=elseif",
              "test.scss:out.css",
            ]);
            await expectLater(sass.stderr, emits(startsWith("Error: ")));
            await expectLater(
              sass.stdout,
              emitsInOrder([
                "Sass is watching for changes. Press Ctrl-C to stop.",
                "",
              ]),
            );
            await sass.kill();
          });
  
          test("in repl mode", () async {
            var sass = await runSass([
              "--interactive",
              "--fatal-deprecation=strict-unary",
            ]);
            sass.stdin.writeln("4 -(5)");
            await expectLater(
              sass.stdout,
              emitsInOrder([
                ">> 4 -(5)",
                emitsThrough(startsWith("Error: ")),
                emitsThrough(contains("Remove this setting")),
              ]),
            );
  
            // Verify that there's no output written for the previous line.
            sass.stdin.writeln("1");
            await expectLater(sass.stdout, emitsInOrder([">> 1", "1"]));
            await sass.kill();
          });
        });
  
        group("an evaluation-time deprecation", () {
          setUp(
            () => d.file("test.scss", """
              @use 'sass:math';
              a {b: math.random(1px)}
            """).create(),
          );
  
          test("in immediate mode", () async {
            var sass = await runSass([
              "--fatal-deprecation=function-units",
              "test.scss",
            ]);
            expect(sass.stderr, emits(startsWith("Error: ")));
            await sass.shouldExit(65);
          });
  
          test("in watch mode", () async {
            var sass = await runSass([
              "--watch",
              "--poll",
              "--fatal-deprecation=function-units",
              "test.scss:out.css",
            ]);
            await expectLater(sass.stderr, emits(startsWith("Error: ")));
            await expectLater(
              sass.stdout,
              emitsInOrder([
                "Sass is watching for changes. Press Ctrl-C to stop.",
                "",
              ]),
            );
            await sass.kill();
          });
  
          test("in repl mode", () async {
            var sass = await runSass([
              "--interactive",
              "--fatal-deprecation=function-units",
            ]);
            sass.stdin.writeln("@use 'sass:math'");
            await expectLater(sass.stdout, emits(">> @use 'sass:math'"));
            sass.stdin.writeln("math.random(1px)");
            await expectLater(
              sass.stdout,
              emitsInOrder([
                ">> math.random(1px)",
                emitsThrough(startsWith("Error: ")),
                emitsThrough(contains("Remove this setting")),
              ]),
            );
  
            // Verify that there's no output written for the previous line.
            sass.stdin.writeln("1");
            await expectLater(sass.stdout, emitsInOrder([">> 1", "1"]));
            await sass.kill();
          });
        });
      });
    });
  
    group("--future-deprecation", () {
      group("prints a warning for", () {
        group("an active deprecation", () {
          setUp(() => d.file("test.scss", "").create());
  
          test("in immediate mode", () async {
            var sass = await runSass([
              "--future-deprecation=function-units",
              "test.scss",
            ]);
            expect(
              sass.stderr,
              emits(contains("function-units is not a future deprecation")),
            );
            await sass.shouldExit(0);
          });
  
          test("in watch mode", () async {
            var sass = await runSass([
              "--watch",
              "--poll",
              "--future-deprecation=function-units",
              "test.scss:out.css",
            ]);
            expect(
              sass.stderr,
              emits(contains("function-units is not a future deprecation")),
            );
  
            await expectLater(
              sass.stdout,
              emitsThrough(endsWith('Compiled test.scss to out.css.')),
            );
            await sass.kill();
          });
  
          test("in repl mode", () async {
            // TODO: test this when there's an expression-level future deprecation
          });
        });
  
        test("an obsolete deprecation", () async {
          var sass = await runSass([
            "--future-deprecation=mixed-decls",
            "test.scss",
          ]);
          expect(sass.stderr,
              emits(contains("mixed-decls deprecation is obsolete")));
          await sass.shouldExit(0);
        });
  
        group("a parse-time deprecation", () {
          setUp(() async {
            await d.file("test.scss", "@import 'other';").create();
            await d.file("_other.scss", "").create();
          });
  
          test("in immediate mode", () async {
            var sass = await runSass([
              "--future-deprecation=import",
              "test.scss",
            ]);
            expect(sass.stderr, emits(startsWith("DEPRECATION WARNING")));
            await sass.shouldExit(0);
          });
  
          test("in watch mode", () async {
            var sass = await runSass([
              "--watch",
              "--poll",
              "--future-deprecation=import",
              "test.scss:out.css",
            ]);
  
            await expectLater(
              sass.stderr,
              emits(startsWith("DEPRECATION WARNING")),
            );
            await sass.kill();
          });
  
          test("in repl mode", () async {
            // TODO: test this when there's an expression-level future deprecation
          });
        });
  
        group("an evaluation-time deprecation", () {
          // TODO: test this when there's an evaluation-time future deprecation
        });
      });
  
      group("throws an error for", () {
        group("an unknown deprecation", () {
          setUp(() => d.file("test.scss", "").create());
  
          test("in immediate mode", () async {
            var sass = await runSass([
              "--future-deprecation=unknown",
              "test.scss",
            ]);
            expect(
              sass.stdout,
              emits(contains('Invalid deprecation "unknown".')),
            );
            await sass.shouldExit(64);
          });
  
          test("in watch mode", () async {
            var sass = await runSass([
              "--watch",
              "--poll",
              "--future-deprecation=unknown",
              "test.scss:out.css",
            ]);
            expect(
              sass.stdout,
              emits(contains('Invalid deprecation "unknown".')),
            );
            await sass.shouldExit(64);
          });
  
          test("in repl mode", () async {
            var sass = await runSass([
              "--interactive",
              "--future-deprecation=unknown",
            ]);
            expect(
              sass.stdout,
              emits(contains('Invalid deprecation "unknown".')),
            );
            await sass.shouldExit(64);
          });
        });
  
        group("a fatal deprecation", () {
          setUp(() async {
            await d.file("test.scss", "@import 'other';").create();
            await d.file("_other.scss", "").create();
          });
  
          test("in immediate mode", () async {
            var sass = await runSass([
              "--fatal-deprecation=import",
              "--future-deprecation=import",
              "test.scss",
            ]);
            expect(sass.stderr, emits(startsWith("Error: ")));
            await sass.shouldExit(65);
          });
  
          test("in watch mode", () async {
            var sass = await runSass([
              "--watch",
              "--poll",
              "--fatal-deprecation=import",
              "--future-deprecation=import",
              "test.scss:out.css",
            ]);
            await expectLater(sass.stderr, emits(startsWith("Error: ")));
            await expectLater(
              sass.stdout,
              emitsInOrder([
                "Sass is watching for changes. Press Ctrl-C to stop.",
                "",
              ]),
            );
            await sass.kill();
          });
  
          test("in repl mode", () async {
            // TODO: test this when there's an expression-level future deprecation
          });
        });
      });
      // Skipping while no future deprecations exist
    }, skip: true);
  }
  