Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 18 additions & 7 deletions .github/workflows/e2e_tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ jobs:
working-directory: tests
script: |
sleep 15
$ANDROID_HOME/platform-tools/adb logcat '*:D' > adb-log.txt &
flutter drive --target=./test_driver/driver_e2e.dart --dart-define=CI=true
$ANDROID_HOME/platform-tools/adb logcat '*:E' > adb-log.txt &
flutter test integration_test/e2e_test.dart --dart-define=CI=true

- name: Compress Emulator Log
if: always()
Expand Down Expand Up @@ -159,7 +159,7 @@ jobs:
export CCACHE_DEPEND=true
export CCACHE_INODECACHE=true
ccache -s
flutter build ios --no-codesign --simulator --debug --target=./test_driver/driver_e2e.dart --dart-define=CI=true
flutter build ios --no-codesign --simulator --debug --target=integration_test/e2e_test.dart --dart-define=CI=true
ccache -s
- name: Start Firebase Emulator
run: cd ./.github/workflows/scripts && ./start-firebase-emulator.sh
Expand All @@ -174,7 +174,7 @@ jobs:
sleep 15
# Uncomment following line to have simulator logs printed out for debugging purposes.
# xcrun simctl spawn booted log stream --predicate 'eventMessage contains "flutter"' &
flutter drive -d "$SIMULATOR" --target=./test_driver/driver_e2e.dart --dart-define=CI=true
flutter test integration_test/e2e_test.dart -d "$SIMULATOR" --dart-define=CI=true
FLUTTER_DRIVE_EXIT_CODE=$?
xcrun simctl shutdown "$SIMULATOR"
exit $FLUTTER_DRIVE_EXIT_CODE
Expand Down Expand Up @@ -230,14 +230,17 @@ jobs:
export CCACHE_DEPEND=true
export CCACHE_INODECACHE=true
ccache -s
flutter build macos --debug --target=./test_driver/driver_e2e.dart --device-id=macos --dart-define=CI=true
flutter build macos --debug --target=integration_test/e2e_test.dart --device-id=macos --dart-define=CI=true
ccache -s
- name: Start Firebase Emulator
run: cd ./.github/workflows/scripts && ./start-firebase-emulator.sh
- name: "E2E Tests"
working-directory: tests
run: |
flutter drive -d macos --target=./test_driver/driver_e2e.dart --dart-define=CI=true
flutter test \
integration_test/e2e_test.dart \
-d macos \
--dart-define=CI=true

web:
runs-on: ubuntu-latest
Expand Down Expand Up @@ -268,6 +271,14 @@ jobs:
run: cd ./.github/workflows/scripts && ./start-firebase-emulator.sh
- name: "E2E Tests"
working-directory: tests
# Web devices are not supported for the `flutter test` command yet. As a
# workaround we can use the `flutter drive` command. Tracking issue:
# https://github.com/flutter/flutter/issues/66264
run: |
chromedriver --port=4444 &
flutter drive --verbose-system-logs --device-id=web-server --target=./test_driver/driver_e2e.dart --dart-define=CI=true
flutter drive \
--verbose-system-logs \
-d web-server \
--driver=test_driver/integration_test.dart \
--target=integration_test/e2e_test.dart \
--dart-define=CI=true
4 changes: 3 additions & 1 deletion tests/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,11 @@ android {
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "io.flutter.plugins.firebase.tests"
minSdkVersion 19
minSdkVersion 21
targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
multiDexEnabled true
}

buildTypes {
Expand All @@ -67,5 +68,6 @@ flutter {
}

dependencies {
implementation 'com.android.support:multidex:1.0.3'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
// Generated file.
//
// If you wish to remove Flutter's multidex support, delete this entire file.
//
// Modifications to this file should be done in a copy under a different name
// as this file may be regenerated.

package io.flutter.app;

import android.app.Application;
import android.content.Context;
import androidx.annotation.CallSuper;
import androidx.multidex.MultiDex;

/** Extension of {@link io.flutter.app.FlutterApplication}, adding multidex support. */
public class FlutterMultiDexApplication extends FlutterApplication {
/** Extension of {@link android.app.Application}, adding multidex support. */
public class FlutterMultiDexApplication extends Application {
@Override
@CallSuper
protected void attachBaseContext(Context base) {
Expand Down
194 changes: 194 additions & 0 deletions tests/integration_test/cloud_functions/cloud_functions_e2e_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
// Copyright 2021, the Chromium 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.

import 'dart:typed_data';

import 'package:cloud_functions/cloud_functions.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:tests/firebase_options.dart';

import 'sample_data.dart' as data;

String kTestFunctionDefaultRegion = 'testFunctionDefaultRegion';
String kTestFunctionCustomRegion = 'testFunctionCustomRegion';
String kTestFunctionTimeout = 'testFunctionTimeout';
String kTestMapConvertType = 'testMapConvertType';

void main() {
group('cloud_functions', () {
late HttpsCallable callable;

setUpAll(() async {
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
FirebaseFunctions.instance.useFunctionsEmulator('localhost', 5001);
callable =
FirebaseFunctions.instance.httpsCallable(kTestFunctionDefaultRegion);
});

group('HttpsCallable', () {
test('returns a [HttpsCallableResult]', () async {
var result = await callable();
expect(result, isA<HttpsCallableResult>());
});

test('accepts no arguments', () async {
HttpsCallableResult result = await callable();
expect(result.data, equals('null'));
});

test('accepts `null arguments', () async {
HttpsCallableResult result = await callable(null);
expect(result.data, equals('null'));
});

test('accepts a string value', () async {
HttpsCallableResult result = await callable('foo');
expect(result.data, equals('string'));
});

test('accepts a number value', () async {
HttpsCallableResult result = await callable(123);
expect(result.data, equals('number'));
HttpsCallableResult result2 = await callable(12.3);
expect(result2.data, equals('number'));
});

test('accepts a boolean value', () async {
HttpsCallableResult result = await callable(true);
expect(result.data, equals('boolean'));
HttpsCallableResult result2 = await callable(false);
expect(result2.data, equals('boolean'));
});

test('accepts a [List]', () async {
HttpsCallableResult result = await callable(data.list);
expect(result.data, equals('array'));
});

test('accepts a deeply nested [Map]', () async {
HttpsCallableResult result = await callable({
'type': 'deepMap',
'inputData': data.deepMap,
});
expect(result.data, equals(data.deepMap));
});

test('accepts a deeply nested [List]', () async {
HttpsCallableResult result = await callable({
'type': 'deepList',
'inputData': data.deepList,
});
expect(result.data, equals(data.deepList));
});

test(
'accepts raw data as arguments',
() async {
HttpsCallableResult result = await callable({
'type': 'rawData',
'list': Uint8List(100),
'int': Int32List(39),
'long': Int64List(45),
'float': Float32List(23),
'double': Float64List(1001),
});
final data = result.data;
expect(data['list'], isA<List>());
expect(data['int'], isA<List>());
expect(data['long'], isA<List>());
expect(data['float'], isA<List>());
expect(data['double'], isA<List>());
},
// Int64List is not supported on Web.
skip: kIsWeb,
);

test(
'[HttpsCallableResult.data] should return Map<String, dynamic> type for returned objects',
() async {
HttpsCallable callable =
FirebaseFunctions.instance.httpsCallable(kTestMapConvertType);

var result = await callable();

expect(result.data, isA<Map<String, dynamic>>());
},
);
});

group('FirebaseFunctionsException', () {
test('HttpsCallable returns a FirebaseFunctionsException on error',
() async {
try {
await callable({});
fail('Should have thrown');
} on FirebaseFunctionsException catch (e) {
expect(e.code, equals('invalid-argument'));
expect(e.message, equals('Invalid test requested.'));
return;
} catch (e) {
fail('$e');
}
});

test('it returns "details" value as part of the exception', () async {
try {
await callable({
'type': 'deepMap',
'inputData': data.deepMap,
'asError': true,
});
fail('Should have thrown');
} on FirebaseFunctionsException catch (e) {
expect(e.code, equals('cancelled'));
expect(
e.message,
equals(
'Response data was requested to be sent as part of an Error payload, so here we are!',
),
);
expect(e.details, equals(data.deepMap));
} catch (e) {
fail('$e');
}
});
});

group('instanceFor', () {
test('accepts a custom region', () async {
final instance = FirebaseFunctions.instanceFor(region: 'europe-west1');
instance.useFunctionsEmulator('localhost', 5001);
final customRegionCallable =
instance.httpsCallable(kTestFunctionCustomRegion);
final result = await customRegionCallable();
expect(result.data, equals('europe-west1'));
});
});

group('HttpsCallableOptions', () {
test('times out when the provided timeout option is exceeded', () async {
final instance = FirebaseFunctions.instance;
instance.useFunctionsEmulator('localhost', 5001);
final timeoutCallable = FirebaseFunctions.instance.httpsCallable(
kTestFunctionTimeout,
options: HttpsCallableOptions(timeout: const Duration(seconds: 3)),
);
try {
await timeoutCallable({
'testTimeout': const Duration(seconds: 6).inMilliseconds.toString(),
});
fail('Should have thrown');
} on FirebaseFunctionsException catch (e) {
expect(e.code, equals('deadline-exceeded'));
} catch (e) {
fail('$e');
}
});
});
});
}
25 changes: 25 additions & 0 deletions tests/integration_test/cloud_functions/sample_data.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright 2021, the Chromium 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.

Map<String, dynamic> map = <String, dynamic>{
'number': 123,
'string': 'foo',
'booleanTrue': true,
'booleanFalse': false,
'null': null,
};

List<dynamic> list = ['1', 2, true, false];

Map<String, dynamic> deepMap = <String, dynamic>{
...map,
'list': list,
'map': map,
};

List<dynamic> deepList = [
...list,
list,
map,
];
40 changes: 40 additions & 0 deletions tests/integration_test/e2e_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright 2019, the Chromium 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.

import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';

import 'cloud_functions/cloud_functions_e2e_test.dart' as cloud_functions;
import 'firebase_app_installations/firebase_app_installations_e2e_test.dart'
as firebase_app_installations;
import 'firebase_analytics/firebase_analytics_e2e_test.dart'
as firebase_analytics;
import 'firebase_core/firebase_core_e2e_test.dart' as firebase_core;
import 'firebase_messaging/firebase_messaging_e2e_test.dart'
as firebase_messaging;
import 'firebase_database/firebase_database_e2e_test.dart' as firebase_database;
import 'firebase_dynamic_links/firebase_dynamic_links_e2e_test.dart'
as firebase_dynamic_links;
import 'firebase_in_app_messaging/firebase_in_app_messaging_e2e_test.dart'
as firebase_in_app_messaging;
import 'firebase_crashlytics/firebase_crashlytics_e2e_test.dart'
as firebase_crashlytics;
import 'firebase_auth/firebase_auth_e2e_test.dart' as firebase_auth;

void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();

group('FlutterFire', () {
cloud_functions.main();
firebase_app_installations.main();
firebase_analytics.main();
firebase_core.main();
firebase_messaging.main();
firebase_database.main();
firebase_dynamic_links.main();
firebase_in_app_messaging.main();
firebase_crashlytics.main();
firebase_auth.main();
});
}
Loading