// Copyright 2023 The Dart Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

@Timeout(Duration(minutes: 1))
library;

import 'package:dwds/src/utilities/shared.dart';
import 'package:test/test.dart';
import 'package:vm_service/vm_service.dart';

import 'fixtures/context.dart';

void main() {
  group('wrapInErrorHandlerAsync', () {
    test('returns future success value if callback succeeds', () async {
      Future<bool> successCallback() async {
        await Future.delayed(Duration(milliseconds: 500));
        return true;
      }

      final result = await wrapInErrorHandlerAsync(
        'successCallback',
        successCallback,
      );
      expect(result, equals(true));
    });

    test('throws RPCError if callback throws RPCError', () async {
      Future<bool> rpcErrorCallback() async {
        await Future.delayed(Duration(milliseconds: 500));
        throw RPCError(
          'rpcErrorCallback',
          RPCErrorKind.kInvalidRequest.code,
          'An error message',
        );
      }

      await expectLater(
        wrapInErrorHandlerAsync('rpcErrorCallback', rpcErrorCallback),
        throwsRPCErrorWithMessage('An error message'),
      );
    });

    test(
      'throws SentinelException if callback throws SentinelException',
      () async {
        Future<bool> sentinelExceptionCallback() async {
          await Future.delayed(Duration(milliseconds: 500));
          throw SentinelException.parse('sentinelExceptionCallback', {
            'message': 'a sentinel exception',
          });
        }

        await expectLater(
          wrapInErrorHandlerAsync(
            'sentinelExceptionCallback',
            sentinelExceptionCallback,
          ),
          throwsSentinelException,
        );
      },
    );

    test('throws RPCError if callback throws other error type', () async {
      Future<bool> exceptionCallback() async {
        await Future.delayed(Duration(milliseconds: 500));
        throw Exception('An unexpected exception');
      }

      try {
        await wrapInErrorHandlerAsync('exceptionCallback', exceptionCallback);
        fail('RPCError not thrown.');
      } catch (error) {
        expect(
          error,
          isRPCErrorWithMessage(
            'Unexpected DWDS error for exceptionCallback: Exception: An unexpected exception',
          ),
        );
      }
    });
  });
}
