You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

523 lines
19 KiB

2 years ago
import 'dart:collection';
import "package:flutter/services.dart";
import "package:flutter_test/flutter_test.dart";
import 'package:mockito/annotations.dart';
import "package:mockito/mockito.dart";
import "package:platform/platform.dart";
import "package:telephony/telephony.dart";
import 'package:collection/collection.dart';
import 'mocks/messages.dart';
import 'telephony_test.mocks.dart';
@GenerateMocks([MethodChannel])
main() {
TestWidgetsFlutterBinding.ensureInitialized();
MockMethodChannel methodChannel = MockMethodChannel();
late Telephony telephony;
setUp(() {
methodChannel = MockMethodChannel();
telephony = Telephony.private(
methodChannel, FakePlatform(operatingSystem: "android"));
});
tearDown(() {
verifyNoMoreInteractions(methodChannel);
});
group('telephony', () {
group("should request", () {
test("sms permissions", () async {
when(methodChannel.invokeMethod(REQUEST_SMS_PERMISSION))
.thenAnswer((_) => Future<bool>.value(true));
final permissionGranted = await telephony.requestSmsPermissions;
verify(methodChannel.invokeMethod<bool>(REQUEST_SMS_PERMISSION))
.called(1);
expect(permissionGranted, true);
});
test("phone permissions", () async {
when(methodChannel.invokeMethod(REQUEST_PHONE_PERMISSION))
.thenAnswer((_) => Future<bool>.value(true));
final permissionGranted = await telephony.requestPhonePermissions;
verify(methodChannel.invokeMethod<bool>(REQUEST_PHONE_PERMISSION))
.called(1);
expect(permissionGranted, true);
});
test("phone and sms permissions", () async {
when(methodChannel.invokeMethod(REQUEST_PHONE_AND_SMS_PERMISSION))
.thenAnswer((_) => Future<bool>.value(true));
final permissionGranted = await telephony.requestPhoneAndSmsPermissions;
verify(methodChannel
.invokeMethod<bool>(REQUEST_PHONE_AND_SMS_PERMISSION))
.called(1);
expect(permissionGranted, true);
});
});
group("should get", () {
test("service state", () async {
when(methodChannel.invokeMethod(GET_SERVICE_STATE))
.thenAnswer((_) => Future<int>.value(1));
final state = await telephony.serviceState;
verify(methodChannel.invokeMethod<int>(GET_SERVICE_STATE)).called(1);
expect(state, ServiceState.OUT_OF_SERVICE);
});
test("signal strengths", () async {
when(methodChannel.invokeMethod(GET_SIGNAL_STRENGTH))
.thenAnswer((_) => Future<List>.value([0, 1]));
final strengths = await telephony.signalStrengths;
verify(methodChannel.invokeMethod(GET_SIGNAL_STRENGTH)).called(1);
expect(
strengths, [SignalStrength.NONE_OR_UNKNOWN, SignalStrength.POOR]);
});
test("is network roaming", () async {
when(methodChannel.invokeMethod<bool>(IS_NETWORK_ROAMING))
.thenAnswer((_) => Future<bool>.value(false));
final result = await telephony.isNetworkRoaming;
verify(methodChannel.invokeMethod(IS_NETWORK_ROAMING)).called(1);
expect(result, false);
});
test("sim state", () async {
when(methodChannel.invokeMethod(GET_SIM_STATE))
.thenAnswer((_) => Future<int>.value(5));
final state = await telephony.simState;
verify(methodChannel.invokeMethod(GET_SIM_STATE)).called(1);
expect(state, SimState.READY);
});
test("sim operator name", () async {
when(methodChannel.invokeMethod(GET_SIM_OPERATOR_NAME))
.thenAnswer((_) => Future<String>.value("operatorName"));
final name = await telephony.simOperatorName;
verify(methodChannel.invokeMethod(GET_SIM_OPERATOR_NAME)).called(1);
expect(name, "operatorName");
});
test("sim operator", () async {
when(methodChannel.invokeMethod(GET_SIM_OPERATOR))
.thenAnswer((_) => Future<String>.value("operator"));
final name = await telephony.simOperator;
verify(methodChannel.invokeMethod(GET_SIM_OPERATOR)).called(1);
expect(name, "operator");
});
test("phone type", () async {
when(methodChannel.invokeMethod(GET_PHONE_TYPE))
.thenAnswer((_) => Future<int>.value(2));
final type = await telephony.phoneType;
verify(methodChannel.invokeMethod(GET_PHONE_TYPE)).called(1);
expect(type, PhoneType.CDMA);
});
test("data network type", () async {
when(methodChannel.invokeMethod(GET_DATA_NETWORK_TYPE))
.thenAnswer((_) => Future<int>.value(0));
final type = await telephony.dataNetworkType;
verify(methodChannel.invokeMethod(GET_DATA_NETWORK_TYPE)).called(1);
expect(type, NetworkType.UNKNOWN);
});
test("network operator name", () async {
when(methodChannel.invokeMethod(GET_NETWORK_OPERATOR_NAME))
.thenAnswer((_) => Future<String>.value("operator name"));
final name = await telephony.networkOperatorName;
verify(methodChannel.invokeMethod(GET_NETWORK_OPERATOR_NAME)).called(1);
expect(name, "operator name");
});
test("network operator", () async {
when(methodChannel.invokeMethod(GET_NETWORK_OPERATOR))
.thenAnswer((_) => Future<String>.value("operator"));
final operator = await telephony.networkOperator;
verify(methodChannel.invokeMethod(GET_NETWORK_OPERATOR)).called(1);
expect(operator, "operator");
});
test("data activity", () async {
when(methodChannel.invokeMethod(GET_DATA_ACTIVITY))
.thenAnswer((_) => Future<int>.value(1));
final activity = await telephony.dataActivity;
verify(methodChannel.invokeMethod(GET_DATA_ACTIVITY)).called(1);
expect(activity, DataActivity.IN);
});
test("call state", () async {
when(methodChannel.invokeMethod(GET_CALL_STATE))
.thenAnswer((_) => Future<int>.value(2));
final state = await telephony.callState;
verify(methodChannel.invokeMethod(GET_CALL_STATE)).called(1);
expect(state, CallState.OFFHOOK);
});
test("cellular data state", () async {
when(methodChannel.invokeMethod(GET_CELLULAR_DATA_STATE))
.thenAnswer((_) => Future<int>.value(0));
final state = await telephony.cellularDataState;
verify(methodChannel.invokeMethod(GET_CELLULAR_DATA_STATE)).called(1);
expect(state, DataState.DISCONNECTED);
});
test("is sms capable", () async {
when(methodChannel.invokeMethod(IS_SMS_CAPABLE))
.thenAnswer((_) => Future<bool>.value(true));
final result = await telephony.isSmsCapable;
verify(methodChannel.invokeMethod(IS_SMS_CAPABLE)).called(1);
expect(result, true);
});
});
group("should send", () {
test("sms", () async {
final String address = "0000000000";
final String body = "Test message";
when(methodChannel.invokeMethod(SEND_SMS, {
"address": address,
"message_body": body,
"listen_status": false
})).thenAnswer((realInvocation) => Future<void>.value());
telephony.sendSms(to: address, message: body);
verify(methodChannel.invokeMethod(SEND_SMS, {
"address": address,
"message_body": body,
"listen_status": false
})).called(1);
});
test("multipart message", () async {
final args = {
"address": "123456",
"message_body": "some long message",
"listen_status": false
};
when(methodChannel.invokeMethod(SEND_MULTIPART_SMS, args))
.thenAnswer((realInvocation) => Future<void>.value());
telephony.sendSms(
to: "123456", message: "some long message", isMultipart: true);
verifyNever(methodChannel.invokeMethod(SEND_SMS, args));
verify(methodChannel.invokeMethod(SEND_MULTIPART_SMS, args)).called(1);
});
test("sms by default app", () async {
final String address = "123456";
final String body = "message";
when(methodChannel.invokeMethod(
SEND_SMS_INTENT, {"address": address, "message_body": body}))
.thenAnswer((realInvocation) => Future<void>.value());
telephony.sendSmsByDefaultApp(to: address, message: body);
verify(methodChannel.invokeMethod(
SEND_SMS_INTENT, {"address": address, "message_body": body}))
.called(1);
});
});
group("smsMessage fromMap should", () {
test("correctly parse SmsType", () {
final columns = DEFAULT_SMS_COLUMNS.toList();
columns.add(SmsColumn.TYPE);
final message = mockMessageWithSmsType;
final sms = SmsMessage.fromMap(message, columns);
expect(sms.type, equals(SmsType.MESSAGE_TYPE_INBOX));
});
test("correctly parse SmsType when tryParse returns null", () {
final columns = DEFAULT_SMS_COLUMNS.toList();
columns.add(SmsColumn.TYPE);
final message = mockMessageWithInvalidSmsType;
final sms = SmsMessage.fromMap(message, columns);
expect(sms.type, equals(null));
});
});
group("should query", () {
test("inbox", () async {
final args = {
"projection": ["_id", "address", "body", "date"],
};
when(methodChannel.invokeMethod<List<LinkedHashMap>>(
GET_ALL_INBOX_SMS, args))
.thenAnswer((_) => Future.value(mockMessages));
final inbox = await telephony.getInboxSms();
verify(methodChannel.invokeMethod(GET_ALL_INBOX_SMS, args)).called(1);
expect(
inbox[0].equals(
SmsMessage.fromMap(mockMessages[0], DEFAULT_SMS_COLUMNS)),
isTrue);
expect(
inbox[1].equals(
SmsMessage.fromMap(mockMessages[1], DEFAULT_SMS_COLUMNS)),
isTrue);
});
test("inbox with filters", () async {
final columns = [SmsColumn.ID, SmsColumn.ADDRESS];
final SmsFilter filter = SmsFilter.where(SmsColumn.ID)
.equals("3")
.and(SmsColumn.ADDRESS)
.like("mess");
final sortOrder = [OrderBy(SmsColumn.ID, sort: Sort.ASC)];
final args = {
"projection": ["_id", "address"],
"selection": " _id = ? AND address LIKE ?",
"selection_args": ["3", "mess"],
"sort_order": "_id ASC"
};
when(methodChannel.invokeMethod<List<LinkedHashMap>>(
GET_ALL_INBOX_SMS, args))
.thenAnswer((_) => Future.value(mockMessages));
final inbox = await telephony.getInboxSms(
columns: columns, filter: filter, sortOrder: sortOrder);
verify(await methodChannel.invokeMethod(GET_ALL_INBOX_SMS, args))
.called(1);
expect(inbox[0].equals(SmsMessage.fromMap(mockMessages[0], columns)),
isTrue);
expect(inbox[1].equals(SmsMessage.fromMap(mockMessages[1], columns)),
isTrue);
});
test("sent", () async {
final args = {
"projection": ["_id", "address", "body", "date"],
};
when(methodChannel.invokeMethod<List<LinkedHashMap>>(
GET_ALL_SENT_SMS, args))
.thenAnswer((_) => Future.value(mockMessages));
final sent = await telephony.getSentSms();
verify(methodChannel.invokeMethod(GET_ALL_SENT_SMS, args)).called(1);
expect(
sent[0].equals(
SmsMessage.fromMap(mockMessages[0], DEFAULT_SMS_COLUMNS)),
isTrue);
expect(
sent[1].equals(
SmsMessage.fromMap(mockMessages[1], DEFAULT_SMS_COLUMNS)),
isTrue);
});
test("sent with filters", () async {
final columns = [SmsColumn.ID, SmsColumn.ADDRESS];
final SmsFilter filter = SmsFilter.where(SmsColumn.ID)
.equals("4")
.and(SmsColumn.DATE)
.greaterThan("12");
final sortOrder = [OrderBy(SmsColumn.ID, sort: Sort.ASC)];
final args = {
"projection": ["_id", "address"],
"selection": " _id = ? AND date > ?",
"selection_args": ["4", "12"],
"sort_order": "_id ASC"
};
when(methodChannel.invokeMethod<List<LinkedHashMap>>(
GET_ALL_SENT_SMS, args))
.thenAnswer((_) => Future.value(mockMessages));
final sent = await telephony.getSentSms(
columns: columns, filter: filter, sortOrder: sortOrder);
verify(await methodChannel.invokeMethod(GET_ALL_SENT_SMS, args))
.called(1);
expect(sent[0].equals(SmsMessage.fromMap(mockMessages[0], columns)),
isTrue);
expect(sent[1].equals(SmsMessage.fromMap(mockMessages[1], columns)),
isTrue);
});
test("draft", () async {
final args = {
"projection": ["_id", "address", "body", "date"],
};
when(methodChannel.invokeMethod<List<LinkedHashMap>>(
GET_ALL_DRAFT_SMS, args))
.thenAnswer((_) => Future.value(mockMessages));
final drafts = await telephony.getDraftSms();
verify(methodChannel.invokeMethod(GET_ALL_DRAFT_SMS, args)).called(1);
expect(
drafts[0].equals(
SmsMessage.fromMap(mockMessages[0], DEFAULT_SMS_COLUMNS)),
isTrue);
expect(
drafts[1].equals(
SmsMessage.fromMap(mockMessages[1], DEFAULT_SMS_COLUMNS)),
isTrue);
});
test("draft with filters", () async {
final columns = [SmsColumn.ID, SmsColumn.ADDRESS];
final SmsFilter filter = SmsFilter.where(SmsColumn.ID)
.equals("4")
.and(SmsColumn.DATE)
.greaterThan("12");
final sortOrder = [OrderBy(SmsColumn.ID, sort: Sort.ASC)];
final args = {
"projection": ["_id", "address"],
"selection": " _id = ? AND date > ?",
"selection_args": ["4", "12"],
"sort_order": "_id ASC"
};
when(methodChannel.invokeMethod<List<LinkedHashMap>>(
GET_ALL_DRAFT_SMS, args))
.thenAnswer((_) => Future.value(mockMessages));
final drafts = await telephony.getDraftSms(
columns: columns, filter: filter, sortOrder: sortOrder);
verify(await methodChannel.invokeMethod(GET_ALL_DRAFT_SMS, args))
.called(1);
expect(drafts[0].equals(SmsMessage.fromMap(mockMessages[0], columns)),
isTrue);
expect(drafts[1].equals(SmsMessage.fromMap(mockMessages[1], columns)),
isTrue);
});
test("conversations", () async {
final args = {
"projection": ["snippet", "thread_id", "msg_count"]
};
when(methodChannel.invokeMethod<List<LinkedHashMap>>(
GET_ALL_CONVERSATIONS, args))
.thenAnswer((realInvocation) => Future.value(mockConversations));
final conversations = await telephony.getConversations();
verify(methodChannel.invokeMethod(GET_ALL_CONVERSATIONS, args))
.called(1);
expect(
conversations[0]
.equals(SmsConversation.fromMap(mockConversations[0])),
isTrue);
expect(
conversations[1]
.equals(SmsConversation.fromMap(mockConversations[1])),
isTrue);
});
test("conversations with filter", () async {
final ConversationFilter filter =
ConversationFilter.where(ConversationColumn.MSG_COUNT)
.equals("4")
.and(ConversationColumn.THREAD_ID)
.greaterThan("12");
final sortOrder = [
OrderBy(ConversationColumn.THREAD_ID, sort: Sort.ASC)
];
final args = {
"projection": ["snippet", "thread_id", "msg_count"],
"selection": " msg_count = ? AND thread_id > ?",
"selection_args": ["4", "12"],
"sort_order": "thread_id ASC"
};
when(methodChannel.invokeMethod<List<LinkedHashMap>>(
GET_ALL_CONVERSATIONS, args))
.thenAnswer((realInvocation) => Future.value(mockConversations));
final conversations = await telephony.getConversations(
filter: filter, sortOrder: sortOrder);
verify(await methodChannel.invokeMethod(GET_ALL_CONVERSATIONS, args))
.called(1);
expect(
conversations[0]
.equals(SmsConversation.fromMap(mockConversations[0])),
isTrue);
expect(
conversations[1]
.equals(SmsConversation.fromMap(mockConversations[1])),
isTrue);
});
});
group("should generate", () {
test("sms filter statement", () async {
final SmsFilter statement = SmsFilter.where(SmsColumn.ADDRESS)
.greaterThan("1")
.and(SmsColumn.ID)
.greaterThanOrEqualTo("2")
.or(SmsColumn.DATE)
.between("3", "4")
.or(SmsColumn.TYPE)
.not
.like("5");
expect(
statement.selection,
equals(
" address > ? AND _id >= ? OR date BETWEEN ? OR NOT type LIKE ?"));
expect(
ListEquality()
.equals(statement.selectionArgs, ["1", "2", "3 AND 4", "5"]),
isTrue);
});
test("conversation filter statement", () async {
final ConversationFilter statement =
ConversationFilter.where(ConversationColumn.THREAD_ID)
.lessThanOrEqualTo("1")
.or(ConversationColumn.MSG_COUNT)
.notEqualTo("6")
.and(ConversationColumn.SNIPPET)
.not
.notEqualTo("7");
expect(statement.selection,
" thread_id <= ? OR msg_count != ? AND NOT snippet != ?");
expect(ListEquality().equals(statement.selectionArgs, ["1", "6", "7"]),
isTrue);
});
});
group("should initiate call", () {
test("via default phone app", () async {
final args = {"phoneNumber": "123456789"};
when(methodChannel.invokeMethod(OPEN_DIALER, args))
.thenAnswer((realInvocation) async {});
await telephony.openDialer("123456789");
verify(methodChannel.invokeMethod(OPEN_DIALER, args)).called(1);
});
test('directly', () async {
final args = {"phoneNumber": "123456789"};
when(methodChannel.invokeMethod(DIAL_PHONE_NUMBER, args))
.thenAnswer((realInvocation) async {});
await telephony.dialPhoneNumber("123456789");
verify(methodChannel.invokeMethod(DIAL_PHONE_NUMBER, args)).called(1);
});
});
});
}