// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

@TestOn('vm')
@OnPlatform({'windows': Skip('https://github.com/dart-lang/test/issues/1613')})
library;

import 'dart:async';
import 'dart:io';

import 'package:test/test.dart';
import 'package:test_descriptor/test_descriptor.dart' as d;

import '../io.dart';

void main() {
  setUpAll(precompileTestExecutable);

  test('pauses the test runner for each file until the user presses enter',
      () async {
    await d.file('test1.dart', '''
import 'package:test/test.dart';

void main() {
  print('loaded test 1!');

  test("success", () {});
}
''').create();

    await d.file('test2.dart', '''
import 'package:test/test.dart';

void main() {

  print('loaded test 2!');
  test("success", () {});
}
''').create();

    var test = await runTest(
        ['--pause-after-load', '-p', 'chrome', 'test1.dart', 'test2.dart']);
    await expectLater(test.stdout, emitsThrough('loaded test 1!'));
    await expectLater(test.stdout, emitsThrough(equalsIgnoringWhitespace('''
      The test runner is paused. Open the dev console in Chrome and set
      breakpoints. Once you're finished, return to this terminal and press
      Enter.
    ''')));

    var nextLineFired = false;
    unawaited(test.stdout.next.then(expectAsync1((line) {
      expect(line, contains('+0: test1.dart: success'));
      nextLineFired = true;
    })));

    // Wait a little bit to be sure that the tests don't start running without
    // our input.
    await Future<void>.delayed(const Duration(seconds: 2));
    expect(nextLineFired, isFalse);

    test.stdin.writeln();

    await expectLater(test.stdout, emitsThrough('loaded test 2!'));
    await expectLater(test.stdout, emitsThrough(equalsIgnoringWhitespace('''
      The test runner is paused. Open the dev console in Chrome and set
      breakpoints. Once you're finished, return to this terminal and press
      Enter.
    ''')));

    nextLineFired = false;
    unawaited(test.stdout.next.then(expectAsync1((line) {
      expect(line, contains('+1: test2.dart: success'));
      nextLineFired = true;
    })));

    // Wait a little bit to be sure that the tests don't start running without
    // our input.
    await Future<void>.delayed(const Duration(seconds: 2));
    expect(nextLineFired, isFalse);

    test.stdin.writeln();
    await expectLater(
        test.stdout, emitsThrough(contains('+2: All tests passed!')));
    await test.shouldExit(0);
  }, tags: 'chrome');

  test('pauses the test runner for each platform until the user presses enter',
      () async {
    await d.file('test.dart', '''
import 'package:test/test.dart';

void main() {
  print('loaded test!');

  test("success", () {});
}
''').create();

    var test = await runTest([
      '--pause-after-load',
      '-p',
      'firefox',
      '-p',
      'chrome',
      '-p',
      'vm',
      'test.dart'
    ]);
    await expectLater(test.stdout, emitsThrough('loaded test!'));
    await expectLater(test.stdout, emitsThrough(equalsIgnoringWhitespace('''
      The test runner is paused. Open the dev console in Firefox and set
      breakpoints. Once you're finished, return to this terminal and press
      Enter.
    ''')));

    var nextLineFired = false;
    unawaited(test.stdout.next.then(expectAsync1((line) {
      expect(line, contains('+0: [Firefox, Dart2Js] success'));
      nextLineFired = true;
    })));

    // Wait a little bit to be sure that the tests don't start running without
    // our input.
    await Future<void>.delayed(const Duration(seconds: 2));
    expect(nextLineFired, isFalse);

    test.stdin.writeln();

    await expectLater(test.stdout, emitsThrough('loaded test!'));
    await expectLater(
        test.stdout,
        emitsThrough(emitsInOrder([
          'The test runner is paused. Open the dev console in Chrome and set '
              "breakpoints. Once you're finished, return to this terminal and "
              'press Enter.'
        ])));

    nextLineFired = false;
    unawaited(test.stdout.next.then(expectAsync1((line) {
      expect(line, contains('+1: [Chrome, Dart2Js] success'));
      nextLineFired = true;
    })));

    // Wait a little bit to be sure that the tests don't start running without
    // our input.
    await Future<void>.delayed(const Duration(seconds: 2));
    expect(nextLineFired, isFalse);

    test.stdin.writeln();
    await expectLater(test.stdout, emitsThrough('loaded test!'));
    await expectLater(
        test.stdout,
        emitsThrough(emitsInOrder([
          'The test runner is paused. Open the Observatory and set '
              "breakpoints. Once you're finished, return to this terminal "
              'and press Enter.'
        ])));

    nextLineFired = false;
    unawaited(test.stdout.next.then(expectAsync1((line) {
      expect(line, contains('+2: [VM, Kernel] success'));
      nextLineFired = true;
    })));

    // Wait a little bit to be sure that the tests don't start running without
    // our input.
    await Future<void>.delayed(const Duration(seconds: 2));
    expect(nextLineFired, isFalse);

    test.stdin.writeln();

    await expectLater(
        test.stdout, emitsThrough(contains('+3: All tests passed!')));
    await test.shouldExit(0);
  }, tags: ['firefox', 'chrome', 'vm']);

  test('stops immediately if killed while paused', () async {
    await d.file('test.dart', '''
import 'package:test/test.dart';

void main() {
  print('loaded test!');

  test("success", () {});
}
''').create();

    var test =
        await runTest(['--pause-after-load', '-p', 'chrome', 'test.dart']);
    await expectLater(test.stdout, emitsThrough('loaded test!'));
    await expectLater(test.stdout, emitsThrough(equalsIgnoringWhitespace('''
      The test runner is paused. Open the dev console in Chrome and set
      breakpoints. Once you're finished, return to this terminal and press
      Enter.
    ''')));

    test.signal(ProcessSignal.sigterm);
    await test.shouldExit();
    await expectLater(test.stderr, emitsDone);
  }, tags: 'chrome', testOn: '!windows');

  test('disables timeouts', () async {
    await d.file('test.dart', '''
import 'dart:async';

import 'package:test/test.dart';

void main() {
  print('loaded test 1!');

  test("success", () async {
    await Future.delayed(Duration.zero);
  }, timeout: Timeout(Duration.zero));
}
''').create();

    var test = await runTest(
        ['--pause-after-load', '-p', 'chrome', '-n', 'success', 'test.dart']);
    await expectLater(test.stdout, emitsThrough('loaded test 1!'));
    await expectLater(test.stdout, emitsThrough(equalsIgnoringWhitespace('''
      The test runner is paused. Open the dev console in Chrome and set
      breakpoints. Once you're finished, return to this terminal and press
      Enter.
    ''')));

    var nextLineFired = false;
    unawaited(test.stdout.next.then(expectAsync1((line) {
      expect(line, contains('+0: success'));
      nextLineFired = true;
    })));

    // Wait a little bit to be sure that the tests don't start running without
    // our input.
    await Future<void>.delayed(const Duration(seconds: 2));
    expect(nextLineFired, isFalse);

    test.stdin.writeln();
    await expectLater(
        test.stdout, emitsThrough(contains('+1: All tests passed!')));
    await test.shouldExit(0);
  }, tags: 'chrome');

  // Regression test for #304.
  test('supports test name patterns', () async {
    await d.file('test.dart', '''
import 'package:test/test.dart';

void main() {
  print('loaded test 1!');

  test("failure 1", () {});
  test("success", () {});
  test("failure 2", () {});
}
''').create();

    var test = await runTest(
        ['--pause-after-load', '-p', 'chrome', '-n', 'success', 'test.dart']);
    await expectLater(test.stdout, emitsThrough('loaded test 1!'));
    await expectLater(test.stdout, emitsThrough(equalsIgnoringWhitespace('''
      The test runner is paused. Open the dev console in Chrome and set
      breakpoints. Once you're finished, return to this terminal and press
      Enter.
    ''')));

    var nextLineFired = false;
    unawaited(test.stdout.next.then(expectAsync1((line) {
      expect(line, contains('+0: success'));
      nextLineFired = true;
    })));

    // Wait a little bit to be sure that the tests don't start running without
    // our input.
    await Future<void>.delayed(const Duration(seconds: 2));
    expect(nextLineFired, isFalse);

    test.stdin.writeln();
    await expectLater(
        test.stdout, emitsThrough(contains('+1: All tests passed!')));
    await test.shouldExit(0);
  }, tags: 'chrome');
}
