diff --git a/packages/firebase_data_connect/firebase_data_connect/lib/src/optional.dart b/packages/firebase_data_connect/firebase_data_connect/lib/src/optional.dart index e40cc1bfe962..69c6f6abfeca 100644 --- a/packages/firebase_data_connect/firebase_data_connect/lib/src/optional.dart +++ b/packages/firebase_data_connect/firebase_data_connect/lib/src/optional.dart @@ -120,9 +120,9 @@ DynamicDeserializer> listDeserializer( DynamicDeserializer deserializer, ) { return (dynamic data) => - (data as List).map((e) => deserializer(e)).toList(); + (data as List).map((e) => deserializer(e)).toList(); } DynamicSerializer> listSerializer(DynamicSerializer serializer) { - return (dynamic data) => (data as List).map((e) => serializer(e)).toList(); + return (dynamic data) => (data as List).map((e) => serializer(e as T)).toList(); } diff --git a/packages/firebase_data_connect/firebase_data_connect/test/src/optional_regression_test.dart b/packages/firebase_data_connect/firebase_data_connect/test/src/optional_regression_test.dart new file mode 100644 index 000000000000..e56638d7c1bd --- /dev/null +++ b/packages/firebase_data_connect/firebase_data_connect/test/src/optional_regression_test.dart @@ -0,0 +1,64 @@ +// Copyright 2024 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import 'package:firebase_data_connect/firebase_data_connect.dart'; +import 'package:firebase_data_connect/src/common/common_library.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('Optional Regression Tests', () { + test('listDeserializer should handle List input', () { + final stringDeserializer = (dynamic json) => json as String; + final deserializer = listDeserializer(stringDeserializer); + + // Simulating JSON decode which produces List + final List jsonList = ['a', 'b']; + + final result = deserializer(jsonList); + expect(result, isA>()); + expect(result, equals(['a', 'b'])); + }); + + test('listSerializer should handle List input if elements are correct type', () { + final stringSerializer = (String value) => value; + final serializer = listSerializer(stringSerializer); + + // List but contains Strings + final List list = ['a', 'b']; + + // We need to cast it to List to pass type check of `DynamicSerializer>` + // which expects `List`. + // Wait, `DynamicSerializer` is defined as `typedef DynamicSerializer = dynamic Function(Variables vars);` + // So `listSerializer` returns `DynamicSerializer>` i.e. `dynamic Function(List vars)`. + // Thus we cannot pass `List` to it directly in a statically typed language if strict checks are on. + // But we can cast it to dynamic first to bypass static check, or use `Function.apply`. + + // However, the internal implementation of `listSerializer` casts `data` to `List`. + // So if we pass it as dynamic, it should work. + + final result = (serializer as Function)(list); + expect(result, equals(['a', 'b'])); + }); + + test('listSerializer should fail if elements are incorrect type', () { + final stringSerializer = (String value) => value; + final serializer = listSerializer(stringSerializer); + + // List contains int + final List list = [1, 2]; + + expect(() => (serializer as Function)(list), throwsA(isA())); + }); + }); +}