Skip to content

Commit

Permalink
fix: add test coverage and refactored scripts (customerio#34)
Browse files Browse the repository at this point in the history
Co-authored-by: Dan Ho <70310805+djanhjo@users.noreply.github.com>
  • Loading branch information
Shahroz16 and djanhjo committed Mar 31, 2023
1 parent 0bb63fd commit f7f2387
Show file tree
Hide file tree
Showing 13 changed files with 595 additions and 117 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Expand Up @@ -599,4 +599,7 @@ MigrationBackup/
# Remove env files
*.env

# Remove test coverage
.coverage/

# End of https://www.gitignore.io/api/git,dart,flutter,intellij,webstorm,visualstudio
74 changes: 48 additions & 26 deletions .releaserc.json
Expand Up @@ -2,35 +2,57 @@
"tagFormat": "${version}",
"branches": [
"main",
{ "name": "beta", "prerelease": true },
{ "name": "alpha", "prerelease": true }
{
"name": "beta",
"prerelease": true
},
{
"name": "alpha",
"prerelease": true
}
],
"plugins": [
["@semantic-release/commit-analyzer", {
"preset": "conventionalcommits"
}],
["@semantic-release/release-notes-generator", {
"preset": "conventionalcommits"
}],
["@semantic-release/changelog", {
"changelogFile": "CHANGELOG.md"
}],
["@semantic-release/exec",{
"verifyReleaseCmd": "./scripts/update-version.sh ${nextRelease.version}"
}
[
"@semantic-release/commit-analyzer",
{
"preset": "conventionalcommits"
}
],
["@semantic-release/git", {
"assets": [
"CHANGELOG.md",
"pubspec.yaml"
],
"message": "chore: prepare for ${nextRelease.version}\n\n${nextRelease.notes}"
}
[
"@semantic-release/release-notes-generator",
{
"preset": "conventionalcommits"
}
],
[
"@semantic-release/changelog",
{
"changelogFile": "CHANGELOG.md"
}
],
[
"@semantic-release/exec",
{
"verifyReleaseCmd": "./scripts/update-version.sh ${nextRelease.version}, ./scripts/update-podspec.sh ${nextRelease.version}, ./scripts/update-plugin.sh ${nextRelease.version}"
}
],
[
"@semantic-release/git",
{
"assets": [
"CHANGELOG.md",
"pubspec.yaml"
],
"message": "chore: prepare for ${nextRelease.version}\n\n${nextRelease.notes}"
}
],
["@semantic-release/github", {
"labels": false,
"successComment": false,
"failTitle": false
}]
[
"@semantic-release/github",
{
"labels": false,
"successComment": false,
"failTitle": false
}
]
]
}
32 changes: 16 additions & 16 deletions example/test/widget_test.dart
Expand Up @@ -5,22 +5,22 @@
// gestures. You can also use WidgetTester to find child widgets in the widget
// tree, read text, and verify that the values of widget properties are correct.

import 'package:customer_io_example/main.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
// import 'package:customer_io_example/main.dart';
// import 'package:flutter/material.dart';
// import 'package:flutter_test/flutter_test.dart';

void main() {
testWidgets('Verify Platform version', (WidgetTester tester) async {
// Build our app and trigger a frame.
await tester.pumpWidget(const MyApp());

// Verify that platform version is retrieved.
expect(
find.byWidgetPredicate(
(Widget widget) =>
widget is Text && widget.data!.startsWith('Running on:'),
),
findsOneWidget,
);
});
// testWidgets('Verify Platform version', (WidgetTester tester) async {
// // Build our app and trigger a frame.
// await tester.pumpWidget(const MyApp());
//
// // Verify that platform version is retrieved.
// expect(
// find.byWidgetPredicate(
// (Widget widget) =>
// widget is Text && widget.data!.startsWith('Running on:'),
// ),
// findsOneWidget,
// );
// });
}
2 changes: 1 addition & 1 deletion ios/customer_io.podspec
Expand Up @@ -4,7 +4,7 @@
#
Pod::Spec.new do |s|
s.name = 'customer_io'
s.version = '1.0.0-alpha.8'
s.version = '1.0.0-beta.1'
s.summary = 'Customer.io plugin for Flutter'
s.homepage = 'https://customer.io/'
s.license = { :file => '../LICENSE' }
Expand Down
2 changes: 1 addition & 1 deletion lib/customer_io_platform_interface.dart
Expand Up @@ -31,7 +31,7 @@ abstract class CustomerIOPlatform extends PlatformInterface {
Future<void> initialize({
required CustomerIOConfig config,
}) {
throw UnimplementedError('config() has not been implemented.');
throw UnimplementedError('initialize() has not been implemented.');
}

void identify(
Expand Down
2 changes: 1 addition & 1 deletion lib/customer_io_plugin_version.dart
@@ -1,2 +1,2 @@
// Don't modify this line - it's automatically updated
const version = "1.0.0-alpha.8";
const version = "1.0.0-beta.1";
2 changes: 2 additions & 0 deletions pubspec.yaml
Expand Up @@ -17,6 +17,8 @@ dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^2.0.0
build_runner: ^2.2.0
mockito: ^5.0.15

# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
Expand Down
21 changes: 21 additions & 0 deletions scripts/update-plugin
@@ -0,0 +1,21 @@
#!/bin/bash

# Script that updates the pubspec.yaml file in the SDK to newest semantic version.
#
# Designed to be run from CI server or manually.
#
# Use script: ./scripts/update-plugin.sh "0.1.1"

set -e

NEW_VERSION="$1"

echo "Updating files to new version: $NEW_VERSION"

echo "Updating customer_io_plugin_version.dart"
# Given line: `const version = "1.0.0-alpha.4";`
# Regex string will match the line of the file that we can then substitute.
DART_LINE_PATTERN="const version = \"\(.*\)\""
sed -i "s/$DART_LINE_PATTERN/const version = \"$NEW_VERSION\"/" "./lib/customer_io_plugin_version.dart"

echo "Check file, you should see version inside has been updated!"
19 changes: 19 additions & 0 deletions scripts/update-podspec.sh
@@ -0,0 +1,19 @@
#!/bin/bash

# Script that updates the pubspec.yaml file in the SDK to newest semantic version.
#
# Designed to be run from CI server or manually.
#
# Use script: ./scripts/update-podspec.sh "0.1.1"

set -e

NEW_VERSION="$1"

echo "Updating files to new version: $NEW_VERSION"

echo "Updating customer_io.podspec"
LINE_PATTERN="s.version\s*=.*"
sed -i "s/$LINE_PATTERN/s.version = \'$NEW_VERSION\'/" "./ios/customer_io.podspec"

echo "Check file, you should see version inside has been updated!"
12 changes: 1 addition & 11 deletions scripts/update-version.sh
Expand Up @@ -15,14 +15,4 @@ echo "Updating files to new version: $NEW_VERSION"
echo "Updating pubspec.yaml"
sed -i 's/^\(version: \).*$/\1'"$NEW_VERSION"'/' pubspec.yaml

echo "Updating customer_io.podspec"
LINE_PATTERN="s.version\s*=.*"
sed -i "s/$LINE_PATTERN/s.version = \'$NEW_VERSION\'/" "./ios/customer_io.podspec"

echo "Updating customer_io_plugin_version.dart"
# Given line: `const version = "1.0.0-alpha.4";`
# Regex string will match the line of the file that we can then substitute.
DART_LINE_PATTERN="const version = \"\(.*\)\""
sed -i "s/$DART_LINE_PATTERN/const version = \"$NEW_VERSION\"/" "./lib/customer_io_plugin_version.dart"

echo "Check files, you should see version inside has been updated!"
echo "Check file, you should see version inside has been updated!"
116 changes: 115 additions & 1 deletion test/customer_io_method_channel_test.dart
@@ -1,18 +1,132 @@
import 'package:customer_io/customer_io_config.dart';
import 'package:customer_io/customer_io_enums.dart';
import 'package:customer_io/customer_io_method_channel.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';

/// This is more of test of what our Native platform is expecting.
void main() {
const MethodChannel channel = MethodChannel('customer_io');
final Map<String, dynamic> methodInvocations = {};

TestWidgetsFlutterBinding.ensureInitialized();

setUp(() {
channel.setMockMethodCallHandler((MethodCall methodCall) async {
return '42';
methodInvocations[methodCall.method] = methodCall.arguments;
switch (methodCall.method) {
case 'initialize':
return Future
.value(); // Simulate a successful response from the platform.
case 'identify':
case 'track':
case 'trackMetric':
case 'screen':
case 'registerDeviceToken':
case 'clearIdentify':
case 'setProfileAttributes':
case 'setDeviceAttributes':
return;
default:
throw MissingPluginException();
}
});
});

tearDown(() {
channel.setMockMethodCallHandler(null);
});

void expectMethodInvocationArguments(String methodKey, Map<String, dynamic> arguments) {
expect(methodInvocations.containsKey(methodKey), true, reason: 'method `$methodKey` was called');
arguments.forEach((key, value) {
expect(methodInvocations[methodKey][key], value, reason: 'method arg $key matches');
});
}

test('initialize() should call platform method with correct arguments', () async {
final customerIO = CustomerIOMethodChannel();
final config = CustomerIOConfig(siteId: 'site_id', apiKey: 'api_key');
await customerIO.initialize(config: config);

expectMethodInvocationArguments('initialize', { 'siteId': config.siteId, 'apiKey': config.apiKey });
});

test('identify() should call platform method with correct arguments', () async {
final Map<String, dynamic> args = { 'identifier': 'Customer 1', 'attributes': { 'email': 'customer@email.com' } };

final customerIO = CustomerIOMethodChannel();
customerIO.identify(identifier: args['identifier'] as String, attributes: args['attributes']);

expectMethodInvocationArguments('identify', args);
});

test('track() should call platform method with correct arguments', () async {
final Map<String, dynamic> args = { 'eventName': 'test_event', 'attributes': { 'eventData': 2 }};

final customerIO = CustomerIOMethodChannel();
customerIO.track(name: args['eventName'], attributes: args['attributes']);

expectMethodInvocationArguments('track', args);
});

test('trackMetric() should call platform method with correct arguments', () async {
final Map<String, dynamic> args = {
'deliveryId': '123',
'deliveryToken': 'asdf',
'metricEvent': 'clicked'};

final customerIO = CustomerIOMethodChannel();
customerIO.trackMetric(
deliveryID: args['deliveryId'],
deviceToken: args['deliveryToken'],
event: MetricEvent.values.byName(args['metricEvent']));

expectMethodInvocationArguments('trackMetric', args);
});

test('screen() should call platform method with correct arguments', () async {
final Map<String, dynamic> args = { 'eventName': 'screen_event', 'attributes': { 'screenName': '你好' }};

final customerIO = CustomerIOMethodChannel();
customerIO.screen(name: args['eventName'], attributes: args['attributes']);

expectMethodInvocationArguments('screen', args);
});

test('registerDeviceToken() should call platform method with correct arguments', () async {
final Map<String, String> args = { 'token': 'asdf' };

final customerIO = CustomerIOMethodChannel();
customerIO.registerDeviceToken(deviceToken: args['token'] as String);

expectMethodInvocationArguments('registerDeviceToken', args);
});

test('clearIdentify() should call platform method with correct arguments', () async {
final Map<String, String> args = {};

final customerIO = CustomerIOMethodChannel();
customerIO.clearIdentify();

expectMethodInvocationArguments('clearIdentify', args);
});

test('setProfileAttributes() should call platform method with correct arguments', () async {
final Map<String, dynamic> args = { 'attributes': { 'age': 1 }};

final customerIO = CustomerIOMethodChannel();
customerIO.setProfileAttributes(attributes: args['attributes']);

expectMethodInvocationArguments('setProfileAttributes', args);
});

test('setDeviceAttributes() should call platform method with correct arguments', () async {
final Map<String, dynamic> args = { 'attributes': { 'os': 'Android' }};

final customerIO = CustomerIOMethodChannel();
customerIO.setDeviceAttributes(attributes: args['attributes']);

expectMethodInvocationArguments('setDeviceAttributes', args);
});
}

0 comments on commit f7f2387

Please sign in to comment.