Skip to content

Commit

Permalink
feat: openfoodfacts#158 - refactored after code review
Browse files Browse the repository at this point in the history
Impacted files:
* `api_folksonomy_test.dart`: refactored and added tests
* `folksonomy.dart`: fixed side-effects; refactored the comments
  • Loading branch information
monsieurtanuki committed Dec 20, 2021
1 parent 1f2817e commit 635014a
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 49 deletions.
20 changes: 14 additions & 6 deletions lib/folksonomy.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ class FolksonomyAPIClient {
_checkResponse(response);
}

/// Returns all the [ProductStats] with that tag key, or with tag key == value
/// Returns all the [ProductStats], with an optional filter.
///
/// The result can be filtered with that [key], or with [key] = [value].
static Future<List<ProductStats>> getProductStats({
final String? key,
final String? value,
Expand Down Expand Up @@ -63,14 +65,18 @@ class FolksonomyAPIClient {
);
_checkResponse(response);
final List<ProductStats> result = <ProductStats>[];
if (response.body == 'null') {
// not found
return result;
}
final List<dynamic> json = jsonDecode(response.body) as List<dynamic>;
for (var element in json) {
result.add(ProductStats.fromJson(element));
}
return result;
}

/// Returns all the products with that tag key.
/// Returns all the products with that [key].
///
/// The key of the returned map is the barcode, the value is the tag value.
static Future<Map<String, String>> getProducts({
Expand Down Expand Up @@ -111,7 +117,7 @@ class FolksonomyAPIClient {

/// Returns all the [ProductTag]s for this product
///
/// The key of the returned map is the key.
/// The key of the returned map is the tag key.
static Future<Map<String, ProductTag>> getProductTags({
required final String barcode,
final QueryType? queryType,
Expand Down Expand Up @@ -237,7 +243,7 @@ Future<void> deleteProductTag({
}
*/

/// Folksonomy: returns the versions of [ProductTag] for this product and key.
/// Returns the versions of [ProductTag] for this [barcode] and [key].
static Future<List<ProductTag>> getProductTagVersions({
required final String barcode,
required final String key,
Expand Down Expand Up @@ -323,11 +329,12 @@ Future<void> deleteProductTag({
}
*/

/// Returns the list of tag keys with statistics.
static Future<Map<String, KeyStats>> getKeys({
final QueryType? queryType,
}) async {
final Map<String, String> parameters = <String, String>{};
/* TODO
/* TODO "The keys list can be restricted to private tags from some owner"
if (owner != null) {
parameters['owner'] = owner;
}
Expand Down Expand Up @@ -363,9 +370,10 @@ Future<void> deleteProductTag({
_checkResponse(response);
}

/// Throws a detailed exception if relevant. Does nothing if [response] is OK.
static void _checkResponse(final Response response) {
if (response.statusCode != 200) {
print('ERROR: ${response.body}');
// TODO have a look at ValidationError in https://api.folksonomy.openfoodfacts.org/docs
throw Exception('Wrong status code: ${response.statusCode}');
}
}
Expand Down
123 changes: 80 additions & 43 deletions test/api_folksonomy_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,70 +8,107 @@ void main() {
// TODO have it working on TEST too
OpenFoodAPIConfiguration.globalQueryType = QueryType.PROD;

const String barcode = '9310036071174';
const String key = 'packaging:character:wikidata';
const String unknownBarcode = 'blablabla$barcode';
const String unknownKey = 'blablabla$key';
// of course we need to check that those 3 "known" guys combine well
const String knownBarcode = '9310036071174';
const String knownKey = 'packaging:character:wikidata';
const String knownValue = 'Q51785';

const String unknownBarcode = 'blablabla$knownBarcode';
const String unknownKey = 'blablabla$knownKey';
const String unknownValue = 'blablabla$knownValue';

const List<Map<String, String>> unknownParameters = <Map<String, String>>[
{'barcode': unknownBarcode, 'key': key},
{'barcode': barcode, 'key': unknownKey},
{'barcode': unknownBarcode, 'key': knownKey},
{'barcode': knownBarcode, 'key': unknownKey},
];

void _checkProductTagList(
final Iterable<ProductTag> list,
final String expectedBarcode, {
final String? key,
}) {
/// Checks that all [ProductTag]s concern that [barcode], and [key] in option.
void _checkProductTagList(final Iterable<ProductTag> list) {
bool found = false;
for (var element in list) {
expect(element.barcode, barcode);
if (key != null) {
if (element.key == key) {
found = true;
}
expect(element.barcode, knownBarcode);
if (element.key == knownKey) {
found = true;
expect(element.value, knownValue);
}
}
expect(found, key != null);
expect(found, true);
}

/// Checks that all [ProductStats]s concern that [barcode], and [key] in option.
void _checkProductStatsList(final Iterable<ProductStats> list) {
bool foundBarcode = false;
for (final ProductStats productStats in list) {
if (productStats.barcode == knownBarcode) {
foundBarcode = true;
expect(productStats.numberOfKeys, greaterThanOrEqualTo(1));
}
}
expect(foundBarcode, true);
}

group('$OpenFoodAPIClient Folksonomy', () {
test('hello', () async => await FolksonomyAPIClient.hello());

test('getProductStats', () async {
test('getProductStats - all', () async {
final List<ProductStats> result =
await FolksonomyAPIClient.getProductStats();
expect(result, isNotEmpty);
bool foundBarcode = false;
for (final ProductStats productStats in result) {
if (productStats.barcode == barcode) {
foundBarcode = true;
expect(productStats.numberOfKeys, greaterThanOrEqualTo(1));
}
}
expect(foundBarcode, true);
_checkProductStatsList(result);
});

test('getProducts - found', () async {
test('getProductStats - found', () async {
final List<ProductStats> result =
await FolksonomyAPIClient.getProductStats(key: knownKey);
expect(result, isNotEmpty);
_checkProductStatsList(result);
});

test('getProductStats - not found', () async {
final List<ProductStats> result =
await FolksonomyAPIClient.getProductStats(key: unknownKey);
expect(result, isEmpty);
});

test('getProducts - found key', () async {
final Map<String, String> result = await FolksonomyAPIClient.getProducts(
key: knownKey,
);
expect(result, isNotEmpty);
expect(result[knownBarcode], knownValue);
});

test('getProducts - found key and value', () async {
final Map<String, String> result = await FolksonomyAPIClient.getProducts(
key: key,
key: knownKey,
value: knownValue,
);
expect(result, isNotEmpty);
expect(result[knownBarcode], knownValue);
});

test('getProducts - not found', () async {
test('getProducts - not found key', () async {
final Map<String, String> result = await FolksonomyAPIClient.getProducts(
key: unknownKey,
);
expect(result, isEmpty);
});

test('getProducts - not found key and value', () async {
final Map<String, String> result = await FolksonomyAPIClient.getProducts(
key: knownKey,
value: unknownValue,
);
expect(result, isEmpty);
});

test('getProductTags - found', () async {
final Map<String, ProductTag> result =
await FolksonomyAPIClient.getProductTags(
barcode: barcode,
barcode: knownBarcode,
);
expect(result, isNotEmpty);
_checkProductTagList(result.values, barcode);
_checkProductTagList(result.values);
});

test('getProductTags - not found', () async {
Expand All @@ -84,12 +121,12 @@ void main() {

test('getProductTag - found', () async {
final ProductTag? result = await FolksonomyAPIClient.getProductTag(
barcode: barcode,
key: key,
barcode: knownBarcode,
key: knownKey,
);
expect(result, isNotNull);
expect(result!.barcode, barcode);
expect(result.key, key);
expect(result!.barcode, knownBarcode);
expect(result.key, knownKey);
});

test('getProductTag - not found', () async {
Expand All @@ -105,11 +142,11 @@ void main() {
test('getProductTagWithSubKeys - found', () async {
final Map<String, ProductTag> result =
await FolksonomyAPIClient.getProductTagWithSubKeys(
barcode: barcode,
key: key,
barcode: knownBarcode,
key: knownKey,
);
expect(result, isNotEmpty);
_checkProductTagList(result.values, barcode, key: key);
_checkProductTagList(result.values);
});

test('getProductTagWithSubKeys - not found', () async {
Expand All @@ -136,11 +173,11 @@ void main() {
test('getProductTagVersions - found', () async {
final List<ProductTag> result =
await FolksonomyAPIClient.getProductTagVersions(
barcode: barcode,
key: key,
barcode: knownBarcode,
key: knownKey,
);
expect(result, isNotEmpty);
_checkProductTagList(result, barcode, key: key);
_checkProductTagList(result);
});

test('getProductTagVersions - not found', () async {
Expand Down Expand Up @@ -190,8 +227,8 @@ void main() {

test('getKeys', () async {
final Map<String, KeyStats> result = await FolksonomyAPIClient.getKeys();
final KeyStats keyStats = result[key]!;
expect(keyStats.key, key);
final KeyStats keyStats = result[knownKey]!;
expect(keyStats.key, knownKey);
expect(keyStats.count, greaterThanOrEqualTo(1));
expect(keyStats.values, greaterThanOrEqualTo(1));
});
Expand Down

0 comments on commit 635014a

Please sign in to comment.