Skip to content

Commit

Permalink
feature_2/openfoodfacts#210 - add nutrient order and list
Browse files Browse the repository at this point in the history
Impacted files:
* `openfoodfacts.dart`: created method `getOrderedNutrients`
* `ordered_nutrient_test.dart`: used new method `OpenFoodAPIClient.getOrderedNutrients`; refactored
  • Loading branch information
monsieurtanuki committed Oct 19, 2021
1 parent 787bdd4 commit 8c6fe57
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 51 deletions.
30 changes: 30 additions & 0 deletions lib/openfoodfacts.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'dart:developer';

import 'package:http/http.dart';
import 'package:openfoodfacts/interface/JsonObject.dart';
import 'package:openfoodfacts/model/OrderedNutrients.dart';
import 'package:openfoodfacts/model/TaxonomyAllergen.dart';
import 'package:openfoodfacts/model/TaxonomyCategory.dart';
import 'package:openfoodfacts/model/TaxonomyIngredient.dart';
Expand Down Expand Up @@ -818,4 +819,33 @@ class OpenFoodAPIClient {
return KnowledgePanels.empty();
}
}

/// Returns the nutrient hierarchy specific to a country, localized.
///
/// [cc] is the country code, as ISO 3166-1 alpha-2
static Future<OrderedNutrients?> getOrderedNutrients({
required final String cc,
required final OpenFoodFactsLanguage language,
final QueryType? queryType,
}) async {
final Uri uri = UriHelper.getUri(
path: 'cgi/nutrients.pl',
queryType: queryType,
queryParameters: <String, String>{'cc': cc, 'lc': language.code},
);

try {
final Response response = await HttpHelper().doGetRequest(
uri,
userAgent: OpenFoodAPIConfiguration.userAgent,
);
if (response.statusCode != 200) {
return null;
}
final json = jsonDecode(response.body);
return OrderedNutrients.fromJson(json);
} catch (exception) {
return null;
}
}
}
102 changes: 51 additions & 51 deletions test/ordered_nutrient_test.dart
Original file line number Diff line number Diff line change
@@ -1,18 +1,34 @@
import 'dart:convert';

import 'package:openfoodfacts/model/OrderedNutrient.dart';
import 'package:openfoodfacts/model/OrderedNutrients.dart';
import 'package:openfoodfacts/openfoodfacts.dart';
import 'package:openfoodfacts/utils/OpenFoodAPIConfiguration.dart';
import 'package:openfoodfacts/utils/QueryType.dart';
import 'package:test/test.dart';
import 'package:http/http.dart' as http;
import 'package:openfoodfacts/utils/HttpHelper.dart';

/// Tests related to [OrderedNutrient] and [OrderedNutrients]
void main() {
OpenFoodAPIConfiguration.globalQueryType = QueryType.TEST;

OrderedNutrient? _findOrderedNutrient(
final List<OrderedNutrient>? list,
final String nutrientId,
) {
if (list == null) {
return null;
}
for (final OrderedNutrient item in list) {
if (item.id == nutrientId) {
return item;
}
final OrderedNutrient? found =
_findOrderedNutrient(item.subNutrients, nutrientId);
if (found != null) {
return found;
}
}
return null;
}

group('$OpenFoodAPIClient ordered nutrients', () {
test('find expected nutrients', () async {
// Very long list, experimentally created from the 3 initial URLs.
Expand Down Expand Up @@ -126,65 +142,49 @@ void main() {
'zinc',
};

const List<String> urls = [
'https://fr.openfoodfacts.org/cgi/nutrients.pl',
'https://us.openfoodfacts.org/cgi/nutrients.pl',
'https://us-es.openfoodfacts.org/cgi/nutrients.pl',
];
for (final String url in urls) {
final http.Response response =
await HttpHelper().doGetRequest(Uri.parse(url));
final json = jsonDecode(response.body);
final OrderedNutrients orderedNutrients =
OrderedNutrients.fromJson(json);
const Set<String> countries = {'fr', 'br', 'us'};
const OpenFoodFactsLanguage language = OpenFoodFactsLanguage.AFRIKAANS;
for (final String country in countries) {
final OrderedNutrients? orderedNutrients =
await OpenFoodAPIClient.getOrderedNutrients(
cc: country,
language: language,
);
expect(orderedNutrients, isNotNull);
for (final String expectedNutrient in expectedNutrients) {
expect(
_findOrderedNutrient(orderedNutrients.nutrients, expectedNutrient),
_findOrderedNutrient(orderedNutrients!.nutrients, expectedNutrient),
isNotNull,
reason: 'Could not find $expectedNutrient in $url',
reason:
'Could not find nutrient $expectedNutrient for country $country',
);
}
}
});

test('check localized "energy"', () async {
const String nutrientId = 'energy';
const Map<String, String> energies = {
'https://fr.openfoodfacts.org/cgi/nutrients.pl': 'Énergie',
'https://us.openfoodfacts.org/cgi/nutrients.pl': 'Energy',
'https://us-es.openfoodfacts.org/cgi/nutrients.pl': 'Energía',
const Map<OpenFoodFactsLanguage, String> energies = {
OpenFoodFactsLanguage.FRENCH: 'Énergie',
OpenFoodFactsLanguage.SPANISH: 'Energía',
OpenFoodFactsLanguage.ENGLISH: 'Energy',
OpenFoodFactsLanguage.PORTUGUESE: 'Energia',
};
for (final String url in energies.keys) {
final http.Response response =
await HttpHelper().doGetRequest(Uri.parse(url));
final json = jsonDecode(response.body);
final OrderedNutrients orderedNutrients =
OrderedNutrients.fromJson(json);
final OrderedNutrient? found =
_findOrderedNutrient(orderedNutrients.nutrients, nutrientId);
expect(found, isNotNull);
expect(found!.name, energies[url]);
const Set<String> countries = {'us', 'it', 'br'};
for (final OpenFoodFactsLanguage language in energies.keys) {
for (final String country in countries) {
final OrderedNutrients? orderedNutrients =
await OpenFoodAPIClient.getOrderedNutrients(
cc: country,
language: language,
);
expect(orderedNutrients, isNotNull);
final OrderedNutrient? found =
_findOrderedNutrient(orderedNutrients!.nutrients, nutrientId);
expect(found, isNotNull);
expect(found!.name, energies[language]);
}
}
});
});
}

OrderedNutrient? _findOrderedNutrient(
final List<OrderedNutrient>? list,
final String nutrientId,
) {
if (list == null) {
return null;
}
for (final OrderedNutrient item in list) {
if (item.id == nutrientId) {
return item;
}
final OrderedNutrient? found =
_findOrderedNutrient(item.subNutrients, nutrientId);
if (found != null) {
return found;
}
}
return null;
}

0 comments on commit 8c6fe57

Please sign in to comment.