Skip to content

Commit

Permalink
Merge pull request #63 from Workiva/null-safety
Browse files Browse the repository at this point in the history
FEDX-126 FED-1719 Null Safety Migration
  • Loading branch information
rmconsole7-wk authored Nov 28, 2023
2 parents 572c496 + 6bc0767 commit 7a74c64
Show file tree
Hide file tree
Showing 112 changed files with 1,147 additions and 1,403 deletions.
6 changes: 2 additions & 4 deletions .github/workflows/build_and_deploy_docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
strategy:
fail-fast: false
matrix:
sdk: [ 2.18.7 ]
sdk: [ 2.19.6 ]
steps:
- uses: actions/checkout@v3
- uses: dart-lang/setup-dart@v1
Expand All @@ -32,7 +32,7 @@ jobs:
- id: build-docs
name: Build Docs
run: dart pub get && dart doc .
if: ${{ matrix.sdk == '2.18.7' }}
if: ${{ matrix.sdk == '2.19.6' }}

# Upload the artifact as required by actions/deploy-pages
- name: Archive Dartdoc Artifact
Expand All @@ -49,5 +49,3 @@ jobs:
with:
artifact_name: dartdoc
if: ${{ steps.build-docs.outcome == 'success' && steps.archive-dartdoc-artifact.outcome == 'success' && github.event_name == 'push' }}


2 changes: 1 addition & 1 deletion .github/workflows/dart_ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
strategy:
fail-fast: false
matrix:
sdk: [ 2.18.7 ]
sdk: [ 2.19.6 ]
steps:
- uses: actions/checkout@v2
- uses: dart-lang/setup-dart@v1
Expand Down
2 changes: 0 additions & 2 deletions lib/dom/accessibility.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// @dart = 2.7

// Copyright 2021 Workiva Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
Expand Down
2 changes: 0 additions & 2 deletions lib/dom/async.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// @dart = 2.7

// Copyright 2021 Workiva Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
Expand Down
2 changes: 0 additions & 2 deletions lib/dom/configure.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// @dart = 2.7

// Copyright 2021 Workiva Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
Expand Down
2 changes: 0 additions & 2 deletions lib/dom/debugging.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// @dart = 2.7

// Copyright 2021 Workiva Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
Expand Down
2 changes: 0 additions & 2 deletions lib/dom/events.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// @dart = 2.7

// Copyright 2021 Workiva Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
Expand Down
2 changes: 0 additions & 2 deletions lib/dom/queries.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// @dart = 2.7

// Copyright 2021 Workiva Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
Expand Down
2 changes: 0 additions & 2 deletions lib/matchers.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// @dart = 2.7

// Copyright 2021 Workiva Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
Expand Down
2 changes: 0 additions & 2 deletions lib/react/react.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// @dart = 2.7

// Copyright 2021 Workiva Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
Expand Down
2 changes: 0 additions & 2 deletions lib/react_testing_library.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// @dart = 2.7

// Copyright 2021 Workiva Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
Expand Down
2 changes: 0 additions & 2 deletions lib/src/dom/accessibility_helpers.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// @dart = 2.7

// Copyright 2021 Workiva Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
Expand Down
30 changes: 14 additions & 16 deletions lib/src/dom/async/types.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// @dart = 2.7

// Copyright 2021 Workiva Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -33,16 +31,16 @@ class SharedJsWaitForOptions {
///
/// How long to wait for the node to appear in the DOM before throwing a `TestFailure`, defaulting to `1000ms`.
/// {@endtemplate}
external int get timeout;
external set timeout(int value);
external int? get timeout;
external set timeout(int? value);

/// {@template sharedWaitForOptionsIntervalDescription}
/// ### [interval]
///
/// How often the callback is called, defaulting to `50ms`.
/// {@endtemplate}
external int get interval;
external set interval(int value);
external int? get interval;
external set interval(int? value);

/// {@template sharedWaitForOptionsOnTimeoutDescription}
/// ### [onTimeout]
Expand Down Expand Up @@ -73,20 +71,20 @@ class SharedJsWaitForOptions {
@JS()
@anonymous
class JsMutationObserverOptions {
external bool get subtree;
external set subtree(bool value);
external bool? get subtree;
external set subtree(bool? value);

external bool get childList;
external set childList(bool value);
external bool? get childList;
external set childList(bool? value);

external bool get attributes;
external set attributes(bool value);
external bool? get attributes;
external set attributes(bool? value);

external bool get characterData;
external set characterData(bool value);
external bool? get characterData;
external set characterData(bool? value);

external List<String> get attributeFilter;
external set attributeFilter(List<String> value);
external List<String>? get attributeFilter;
external set attributeFilter(List<String>? value);
}

/// Builds a set of options that can be used for any async query like `waitFor`,
Expand Down
82 changes: 43 additions & 39 deletions lib/src/dom/async/wait_for.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// @dart = 2.7

// Copyright 2021 Workiva Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -56,48 +54,52 @@ export 'package:react_testing_library/src/dom/async/types.dart' show JsMutationO
/// {@category Async}
Future<T> waitFor<T>(
FutureOr<T> Function() expectation, {
Node container,
Duration timeout,
Duration interval = const Duration(milliseconds: 50),
QueryTimeoutFn onTimeout,
Node? container,
Duration? timeout,
Duration interval = defaultAsyncCallbackCheckInterval,
QueryTimeoutFn? onTimeout,
MutationObserverOptions mutationObserverOptions = defaultMutationObserverOptions,
}) async {
final config = getConfig();
container ??= document.body;
container ??= document.body!;
timeout ??= Duration(milliseconds: config.asyncUtilTimeout);
onTimeout ??= (error) => error;

/*Error*/ dynamic lastError;
MutationObserver observer;
Timer intervalTimer;
Timer overallTimeoutTimer;
/*Error*/ Object? lastError;
late MutationObserver observer;
late Timer intervalTimer;
late Timer overallTimeoutTimer;
var isPending = false;
final doneCompleter = Completer<T>();

void onDone(Object error, T result) {
void onDone(T result) {
if (doneCompleter.isCompleted) return;

overallTimeoutTimer.cancel();
intervalTimer.cancel();
observer.disconnect();

if (error != null) {
doneCompleter.completeError(error);
} else if (result is TestFailure) {
if (result is TestFailure) {
doneCompleter.completeError(result);
} else {
doneCompleter.complete(result);
}
}

// Separate error handling to enforce non-nullability of the result.
void onDoneWithError(Object error) {
if (doneCompleter.isCompleted) return;

overallTimeoutTimer.cancel();
intervalTimer.cancel();
observer.disconnect();

doneCompleter.completeError(error);
}

void handleTimeout() {
/*Error*/ dynamic error;
if (lastError != null) {
error = lastError;
} else {
error = TimeoutException('Timed out in waitFor after ${timeout.inMilliseconds}ms.');
}
onDone(onTimeout(error), null);
final error = lastError ?? TimeoutException('Timed out in waitFor after ${timeout!.inMilliseconds}ms.');
onDoneWithError(onTimeout!(error));
}

void checkCallback() {
Expand All @@ -106,11 +108,11 @@ Future<T> waitFor<T>(
final result = expectation();
if (result is Future) {
isPending = true;
(result as Future)
.then((resolvedValue) => onDone(null, resolvedValue as T), onError: (e) => lastError = e)
(result! as Future)
.then((resolvedValue) => onDone(resolvedValue as T), onError: (e) => lastError = e)
.whenComplete(() => isPending = false);
} else {
onDone(null, result as T);
onDone(result);
}
// If `callback` throws, wait for the next mutation, interval, or timeout.
} catch (error) {
Expand Down Expand Up @@ -159,20 +161,19 @@ Future<T> waitFor<T>(
/// {@category Async}
Future<void> waitForElementToBeRemoved(
Node Function() callback, {
Node container,
Duration timeout,
Node? container,
Duration? timeout,
Duration interval = const Duration(milliseconds: 50),
QueryTimeoutFn onTimeout,
QueryTimeoutFn? onTimeout,
MutationObserverOptions mutationObserverOptions = defaultMutationObserverOptions,
}) async {
final config = getConfig();
container ??= document.body;
container ??= document.body!;
timeout ??= Duration(milliseconds: config.asyncUtilTimeout);

final el = callback();
if (el == null) {
throw TestingLibraryElementError('The callback must return a non-null Element.');
}
// Keep null check to maintain backwards compatibility for consumers that are not opted in to null safety.
ArgumentError.checkNotNull(el);

if (!container.contains(el)) {
throw TestingLibraryElementError(
Expand All @@ -181,14 +182,14 @@ Future<void> waitForElementToBeRemoved(
}

await waitFor(
() => expect(container.contains(el), isFalse),
() => expect(container!.contains(el), isFalse),
container: container,
timeout: timeout,
interval: interval,
onTimeout: onTimeout ??
(error) {
return TimeoutException(
'The element returned from the callback was still present in the container after ${timeout.inMilliseconds}ms:\n\n'
'The element returned from the callback was still present in the container after ${timeout!.inMilliseconds}ms:\n\n'
'${prettyDOM(container)}');
},
mutationObserverOptions: mutationObserverOptions,
Expand Down Expand Up @@ -216,16 +217,19 @@ Future<void> waitForElementToBeRemoved(
/// {@category Async}
Future<void> waitForElementsToBeRemoved(
List<Node> Function() callback, {
Node container,
Duration timeout,
Node? container,
Duration? timeout,
Duration interval = const Duration(milliseconds: 50),
QueryTimeoutFn onTimeout,
QueryTimeoutFn? onTimeout,
MutationObserverOptions mutationObserverOptions = defaultMutationObserverOptions,
}) async {
container ??= document.body;
container ??= document.body!;
final els = callback();

if (els == null || els.isEmpty) {
// Keep null check to maintain backwards compatibility for consumers that are not opted in to null safety.
ArgumentError.checkNotNull(els);

if (els.isEmpty) {
throw TestingLibraryElementError('The callback must return one or more non-null Elements.');
}

Expand Down
22 changes: 10 additions & 12 deletions lib/src/dom/config/configure.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// @dart = 2.7

// Copyright 2021 Workiva Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -29,16 +27,16 @@ export 'package:react_testing_library/src/dom/config/types.dart' show JsConfig;
///
/// > See: <https://testing-library.com/docs/dom-testing-library/api-configuration/>
void configure({
String testIdAttribute,
int asyncUtilTimeout,
bool computedStyleSupportsPseudoElements,
bool defaultHidden,
bool showOriginalStackTrace,
bool throwSuggestions,
TestingLibraryElementError Function(Object message, Element container) getElementError,
String? testIdAttribute,
int? asyncUtilTimeout,
bool? computedStyleSupportsPseudoElements,
bool? defaultHidden,
bool? showOriginalStackTrace,
bool? throwSuggestions,
TestingLibraryElementError Function(Object? message, Element container)? getElementError,
}) {
JsError _getJsGetElementError(Object message, Element container) {
final dartError = allowInterop(getElementError)(message, container);
JsError _getJsGetElementError(Object? message, Element container) {
final dartError = allowInterop(getElementError!)(message ?? '', container);
return buildJsGetElementError(dartError.message, container);
}

Expand All @@ -55,7 +53,7 @@ void configure({
}

@JS('rtl.configure')
external void jsConfigure([JsConfig newConfig]);
external void jsConfigure([JsConfig? newConfig]);

/// Returns the configuration options being used by react-testing-library.
///
Expand Down
6 changes: 2 additions & 4 deletions lib/src/dom/config/types.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// @dart = 2.7

// Copyright 2021 Workiva Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -42,6 +40,6 @@ class JsConfig {
external bool get throwSuggestions;
external set throwSuggestions(bool value);

external /*JsError*/ dynamic Function(String message, Element container) get getElementError;
external set getElementError(/*JsError*/ dynamic Function(String message, Element container) value);
external /*JsError*/ dynamic Function(String? message, Element container) get getElementError;
external set getElementError(/*JsError*/ dynamic Function(String? message, Element container) value);
}
9 changes: 2 additions & 7 deletions lib/src/dom/fire_event.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// @dart = 2.7

// Copyright 2021 Workiva Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -125,8 +123,8 @@ external JsMap get _fireEventObj;
/// See: <https://testing-library.com/docs/dom-testing-library/api-events/#fireeventeventname>
///
/// {@category UserActions}
bool fireEventByName(String eventName, Element element, [Map eventProperties]) {
if (!JsBackedMap.fromJs(_jsEventMap).keys.contains(eventName)) {
bool fireEventByName(String eventName, Element element, [Map? eventProperties]) {
if (!JsBackedMap.fromJs(_fireEventObj).keys.contains(eventName)) {
throw ArgumentError.value(eventName, 'eventName');
}

Expand All @@ -139,6 +137,3 @@ bool fireEventByName(String eventName, Element element, [Map eventProperties]) {

return eventHandlerErrorCatcher(() => jsFireEventByNameFn(element, jsifyAndAllowInterop(eventProperties)));
}

@JS('rtl.eventMap')
external JsMap get _jsEventMap;
Loading

0 comments on commit 7a74c64

Please sign in to comment.