Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -206,8 +206,6 @@ class _SmoothAutocompleteTextFieldState
return _SearchResults.empty();
}

final DateTime start = DateTime.now();

if (_suggestions[search] != null) {
return _suggestions[search]!;
} else if (widget.manager == null ||
Expand All @@ -222,19 +220,16 @@ class _SmoothAutocompleteTextFieldState
_suggestions[search] = _SearchResults(
await widget.manager!.getSuggestions(search),
);
} catch (_) {}
} catch (_) {
_setLoading(false);
return _SearchResults.empty();
}

if (_suggestions[search]?.isEmpty ?? true && search == _searchInput) {
_setLoading(false);
}

if (_searchInput != search &&
start.difference(DateTime.now()).inSeconds > 5) {
// Ignore this request, it's too long and this is not even the current search
return _SearchResults.empty();
} else {
return _suggestions[search] ?? _SearchResults.empty();
}
return _suggestions[search] ?? _SearchResults.empty();
}
}

Expand Down
16 changes: 8 additions & 8 deletions packages/smooth_app/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -273,10 +273,10 @@ packages:
dependency: transitive
description:
name: characters
sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b
url: "https://pub.dev"
source: hosted
version: "1.4.0"
version: "1.4.1"
clock:
dependency: transitive
description:
Expand Down Expand Up @@ -1052,18 +1052,18 @@ packages:
dependency: transitive
description:
name: matcher
sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
sha256: "12956d0ad8390bbcc63ca2e1469c0619946ccb52809807067a7020d57e647aa6"
url: "https://pub.dev"
source: hosted
version: "0.12.17"
version: "0.12.18"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b"
url: "https://pub.dev"
source: hosted
version: "0.11.1"
version: "0.13.0"
matomo_tracker:
dependency: "direct main"
description:
Expand Down Expand Up @@ -1679,10 +1679,10 @@ packages:
dependency: transitive
description:
name: test_api
sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55
sha256: "93167629bfc610f71560ab9312acdda4959de4df6fac7492c89ff0d3886f6636"
url: "https://pub.dev"
source: hosted
version: "0.7.7"
version: "0.7.9"
torch_light:
dependency: "direct main"
description:
Expand Down
66 changes: 66 additions & 0 deletions packages/smooth_app/test/pages/autocomplete_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:openfoodfacts/openfoodfacts.dart';

/// Mock autocompleter that simulates slow/failing network
class _MockAutocompleter implements Autocompleter {
_MockAutocompleter({this.delay = Duration.zero, this.shouldFail = false});

final Duration delay;
final bool shouldFail;
int callCount = 0;

@override
Future<List<String>> getSuggestions(String input) async {
callCount++;
await Future<void>.delayed(delay);
if (shouldFail) {
throw Exception('Network error');
}
return <String>['$input-result1', '$input-result2'];
}
}

void main() {
group('AutocompleteManager', () {
test('cache hit returns immediately without server call', () async {
final _MockAutocompleter mock = _MockAutocompleter();
final AutocompleteManager manager = AutocompleteManager(mock);

// First call hits server
final List<String> first = await manager.getSuggestions('bo');
expect(first, contains('bo-result1'));
expect(mock.callCount, 1);

// Second call should hit cache — no new server call
final List<String> second = await manager.getSuggestions('bo');
expect(second, contains('bo-result1'));
expect(mock.callCount, 1); // still 1 — cache served it
});

test('returns most recent cached result when out of order', () async {
final _MockAutocompleter slowMock = _MockAutocompleter(
delay: const Duration(milliseconds: 100),
);
final AutocompleteManager manager = AutocompleteManager(slowMock);

// Fire both requests simultaneously
final Future<List<String>> boFuture = manager.getSuggestions('bo');
final Future<List<String>> botFuture = manager.getSuggestions('bot');

final List<String> boResult = await boFuture;
final List<String> botResult = await botFuture;

// Both should have cached their own results
expect(boResult, isNotEmpty);
expect(botResult, isNotEmpty);
});

test('network failure throws exception', () async {
final _MockAutocompleter failMock = _MockAutocompleter(shouldFail: true);
final AutocompleteManager manager = AutocompleteManager(failMock);

// Should throw — smooth-app catch block must handle this
expect(() => manager.getSuggestions('bo'), throwsException);
});
});
}