From 8190f2b6ad9eba79408b99f4885e02c3dd0d2184 Mon Sep 17 00:00:00 2001 From: Dan Caseley Date: Wed, 25 Aug 2021 09:42:51 +0100 Subject: [PATCH] Fixes bug where new instances of the same vendor could be init'd --- lib/src/analytics_x.dart | 19 ++++++++++++++++++- test/analytics_x_test.dart | 19 +++++++++++++++++++ test/util/vendors_and_actions.dart | 2 ++ 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/lib/src/analytics_x.dart b/lib/src/analytics_x.dart index d4104a1..a4adf05 100644 --- a/lib/src/analytics_x.dart +++ b/lib/src/analytics_x.dart @@ -38,7 +38,10 @@ class AnalyticsX { Future init(List vendors, [AnalyticsError? onError]) async { this.onError = onError; - final newVendors = List.from(vendors)..removeWhere((v) => _vendors.contains(v)); + final uniqueVendors = _getUniqueVendorsById(vendors); + + final newVendors = List.from(uniqueVendors) + ..removeWhere((v) => _getVendorsById([v.id]).isNotEmpty); if (newVendors.isEmpty) { return; @@ -83,9 +86,23 @@ class AnalyticsX { return _vendors.where((element) => ids.contains(element.id)).toList(); } + List _getUniqueVendorsById(List vendorList) { + final List uniqueIds = []; + for (final AnalyticsVendor vendor in List.from(vendorList)) { + if (uniqueIds.contains(vendor.id)) { + vendorList.remove(vendor); + } + uniqueIds.add(vendor.id); + } + return vendorList; + } + /// Resets the list of known vendors. /// /// Doesn't perform any additional work on the [AnalyticsVendor], but permits all vendors to be passed to [init] /// again and have their [AnalyticsVendor.init] method invoked. void reset() => _vendors.clear(); + + /// Fetches the list of all registered (init'd) vendors + List get allRegisteredVendors => _vendors; } diff --git a/test/analytics_x_test.dart b/test/analytics_x_test.dart index 2d43fcd..4a73148 100644 --- a/test/analytics_x_test.dart +++ b/test/analytics_x_test.dart @@ -67,4 +67,23 @@ void main() { await ax.invokeAction(FakeAction("potato"), ['NonExistentVendorId']); expect(fakeVendor.handleActionWasCalledXTimes, 0); }); + + test('AnalyticsX only registers one of each class of AnalyticsVendor when initialised together', () async { + final anotherFakeVendor = FakeVendor(); + await ax.init([fakeVendor, anotherFakeVendor]); + expect(AnalyticsX().allRegisteredVendors.length, 1); + }); + + test('AnalyticsX only registers one of each class of AnalyticsVendor when initialised separately', () async { + final anotherFakeVendor = FakeVendor(); + await ax.init([fakeVendor]); + await ax.init([anotherFakeVendor]); + expect(AnalyticsX().allRegisteredVendors.length, 1); + }); + + test('AnalyticsX only registers one AnalyticsVendor when two implementations are given the same ID', () async { + final anotherFakeVendor = FakeVendorWithSameID(); + await ax.init([fakeVendor, anotherFakeVendor]); + expect(AnalyticsX().allRegisteredVendors.length, 1); + }); } diff --git a/test/util/vendors_and_actions.dart b/test/util/vendors_and_actions.dart index 10b847e..bbad639 100644 --- a/test/util/vendors_and_actions.dart +++ b/test/util/vendors_and_actions.dart @@ -31,6 +31,8 @@ class FakeVendor2 extends FakeVendor { FakeVendor2() : super.withVendorId('Dummy2'); } +class FakeVendorWithSameID extends FakeVendor {} + class BrokenFakeVendor extends FakeVendor { bool initWillThrow = true; bool handleActionWillThrow = false;