diff --git a/example/lib/main.dart b/example/lib/main.dart index 7e09272d9f..787acab541 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'package:openfoodfacts/model/OcrIngredientsResult.dart'; +import 'package:openfoodfacts/model/ProductResultV3.dart'; import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:openfoodfacts/utils/TagType.dart'; @@ -8,11 +9,16 @@ import 'package:openfoodfacts/utils/TagType.dart'; Future getProduct() async { var barcode = '0048151623426'; - ProductQueryConfiguration configuration = ProductQueryConfiguration(barcode, - language: OpenFoodFactsLanguage.GERMAN, fields: [ProductField.ALL]); - ProductResult result = await OpenFoodAPIClient.getProduct(configuration); + final ProductQueryConfiguration configuration = ProductQueryConfiguration( + barcode, + language: OpenFoodFactsLanguage.GERMAN, + fields: [ProductField.ALL], + version: ProductQueryVersion.v3, + ); + final ProductResultV3 result = + await OpenFoodAPIClient.getProductV3(configuration); - if (result.status == 1) { + if (result.status == ProductResultV3.statusSuccess) { return result.product; } else { throw Exception('product not found, please insert data for $barcode'); @@ -120,16 +126,20 @@ void saveAndExtractIngredient() async { } //Get The saved product's ingredients from the server - ProductQueryConfiguration configurations = ProductQueryConfiguration( - '3613042717385', - language: OpenFoodFactsLanguage.FRENCH, - fields: [ - ProductField.INGREDIENTS_TEXT, - ]); - ProductResult productResult = - await OpenFoodAPIClient.getProduct(configurations, user: myUser); - - if (productResult.status != 1) { + final ProductQueryConfiguration configurations = ProductQueryConfiguration( + '3613042717385', + language: OpenFoodFactsLanguage.FRENCH, + fields: [ + ProductField.INGREDIENTS_TEXT, + ], + version: ProductQueryVersion.v3, + ); + final ProductResultV3 productResult = await OpenFoodAPIClient.getProductV3( + configurations, + user: myUser, + ); + + if (productResult.status != ProductResultV3.statusSuccess) { throw Exception('product not found, please insert data for 3613042717385'); } } diff --git a/lib/model/LocalizedTag.dart b/lib/model/LocalizedTag.dart new file mode 100644 index 0000000000..11db3dc90c --- /dev/null +++ b/lib/model/LocalizedTag.dart @@ -0,0 +1,35 @@ +import 'package:json_annotation/json_annotation.dart'; +import '../interface/JsonObject.dart'; + +part 'LocalizedTag.g.dart'; + +/// Tag with localizations (in English and an additional language). +/// +/// We need to populate URL parameter `tag_lc` to get [lcName]. +@JsonSerializable() +class LocalizedTag extends JsonObject { + /// Tag id. + @JsonKey(includeIfNull: false) + String? id; + + /// Name in English. + @JsonKey(includeIfNull: false) + String? name; + + /// Localized name - according to query parameter `tags_lc`. + @JsonKey(name: 'lc_name', includeIfNull: false) + String? lcName; + + LocalizedTag(); + + factory LocalizedTag.fromJson(Map json) => + _$LocalizedTagFromJson(json); + + @override + Map toJson() => _$LocalizedTagToJson(this); + + Map toServerData() => JsonObject.toDataStatic(toJson()); + + @override + String toString() => toServerData().toString(); +} diff --git a/lib/model/LocalizedTag.g.dart b/lib/model/LocalizedTag.g.dart new file mode 100644 index 0000000000..9673e3d40f --- /dev/null +++ b/lib/model/LocalizedTag.g.dart @@ -0,0 +1,27 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'LocalizedTag.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +LocalizedTag _$LocalizedTagFromJson(Map json) => LocalizedTag() + ..id = json['id'] as String? + ..name = json['name'] as String? + ..lcName = json['lc_name'] as String?; + +Map _$LocalizedTagToJson(LocalizedTag instance) { + final val = {}; + + void writeNotNull(String key, dynamic value) { + if (value != null) { + val[key] = value; + } + } + + writeNotNull('id', instance.id); + writeNotNull('name', instance.name); + writeNotNull('lc_name', instance.lcName); + return val; +} diff --git a/lib/model/ProductResult.dart b/lib/model/ProductResult.dart index 57b03318d5..308441ebc8 100644 --- a/lib/model/ProductResult.dart +++ b/lib/model/ProductResult.dart @@ -4,6 +4,8 @@ import 'Product.dart'; part 'ProductResult.g.dart'; +// TODO: deprecated from 2022-12-01; remove when old enough +@Deprecated('Use ProductResultV3 instead') @JsonSerializable() class ProductResult extends JsonObject { final int? status; diff --git a/lib/model/ProductResultField.dart b/lib/model/ProductResultField.dart new file mode 100644 index 0000000000..28cc7b4655 --- /dev/null +++ b/lib/model/ProductResultField.dart @@ -0,0 +1,28 @@ +import 'package:json_annotation/json_annotation.dart'; +import '../interface/JsonObject.dart'; + +part 'ProductResultField.g.dart'; + +/// Field part of an API V3 answer. +@JsonSerializable() +class ProductResultField extends JsonObject { + ProductResultField(); + + @JsonKey(includeIfNull: false) + String? id; + + @JsonKey(includeIfNull: false) + String? value; + + @JsonKey(name: 'default_value', includeIfNull: false) + String? defaultValue; + + factory ProductResultField.fromJson(Map json) => + _$ProductResultFieldFromJson(json); + + @override + Map toJson() => _$ProductResultFieldToJson(this); + + @override + String toString() => toJson().toString(); +} diff --git a/lib/model/ProductResultField.g.dart b/lib/model/ProductResultField.g.dart new file mode 100644 index 0000000000..665e85dd01 --- /dev/null +++ b/lib/model/ProductResultField.g.dart @@ -0,0 +1,28 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'ProductResultField.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +ProductResultField _$ProductResultFieldFromJson(Map json) => + ProductResultField() + ..id = json['id'] as String? + ..value = json['value'] as String? + ..defaultValue = json['default_value'] as String?; + +Map _$ProductResultFieldToJson(ProductResultField instance) { + final val = {}; + + void writeNotNull(String key, dynamic value) { + if (value != null) { + val[key] = value; + } + } + + writeNotNull('id', instance.id); + writeNotNull('value', instance.value); + writeNotNull('default_value', instance.defaultValue); + return val; +} diff --git a/lib/model/ProductResultFieldAnswer.dart b/lib/model/ProductResultFieldAnswer.dart new file mode 100644 index 0000000000..1b6b23800e --- /dev/null +++ b/lib/model/ProductResultFieldAnswer.dart @@ -0,0 +1,33 @@ +import 'package:json_annotation/json_annotation.dart'; +import 'package:openfoodfacts/interface/JsonObject.dart'; +import 'package:openfoodfacts/model/LocalizedTag.dart'; +import 'package:openfoodfacts/model/ProductResultField.dart'; + +part 'ProductResultFieldAnswer.g.dart'; + +/// API V3 answer for one field. +@JsonSerializable() +class ProductResultFieldAnswer extends JsonObject { + ProductResultFieldAnswer(); + + /// Field on which there is a specific answer. + @JsonKey(includeIfNull: false) + ProductResultField? field; + + /// Impact, e.g. "Field ignored". + @JsonKey(includeIfNull: false) + LocalizedTag? impact; + + /// Message, e.g. "Missing field". + @JsonKey(includeIfNull: false) + LocalizedTag? message; + + factory ProductResultFieldAnswer.fromJson(Map json) => + _$ProductResultFieldAnswerFromJson(json); + + @override + Map toJson() => _$ProductResultFieldAnswerToJson(this); + + @override + String toString() => toJson().toString(); +} diff --git a/lib/model/ProductResultFieldAnswer.g.dart b/lib/model/ProductResultFieldAnswer.g.dart new file mode 100644 index 0000000000..88c3b2df46 --- /dev/null +++ b/lib/model/ProductResultFieldAnswer.g.dart @@ -0,0 +1,36 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'ProductResultFieldAnswer.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +ProductResultFieldAnswer _$ProductResultFieldAnswerFromJson( + Map json) => + ProductResultFieldAnswer() + ..field = json['field'] == null + ? null + : ProductResultField.fromJson(json['field'] as Map) + ..impact = json['impact'] == null + ? null + : LocalizedTag.fromJson(json['impact'] as Map) + ..message = json['message'] == null + ? null + : LocalizedTag.fromJson(json['message'] as Map); + +Map _$ProductResultFieldAnswerToJson( + ProductResultFieldAnswer instance) { + final val = {}; + + void writeNotNull(String key, dynamic value) { + if (value != null) { + val[key] = value; + } + } + + writeNotNull('field', instance.field); + writeNotNull('impact', instance.impact); + writeNotNull('message', instance.message); + return val; +} diff --git a/lib/model/ProductResultV3.dart b/lib/model/ProductResultV3.dart new file mode 100644 index 0000000000..3681971ca1 --- /dev/null +++ b/lib/model/ProductResultV3.dart @@ -0,0 +1,87 @@ +import 'package:json_annotation/json_annotation.dart'; +import 'package:openfoodfacts/interface/JsonObject.dart'; +import 'package:openfoodfacts/model/LocalizedTag.dart'; +import 'package:openfoodfacts/model/ProductResultFieldAnswer.dart'; +import 'package:openfoodfacts/openfoodfacts.dart'; + +part 'ProductResultV3.g.dart'; + +/// API V3 answer from a call to /api/v3/product/$barcode. +/// +/// Same /api/v3/product/$barcode URL can be used for GET (get that product) +/// and PATCH (upsert that product and return the modified version). +@JsonSerializable() +class ProductResultV3 extends JsonObject { + ProductResultV3(); + + /// Barcode of a GET operation. + @JsonKey(name: 'code', includeIfNull: false) + String? barcode; + + /// Result, e.g. "Product found". + /// + /// Does not seem to be populated for PATH=update. + @JsonKey(includeIfNull: false) + LocalizedTag? result; + + /// Status. + /// + /// Typical values: [statusFailure], [statusWarning] or [statusSuccess] + @JsonKey(includeIfNull: false) + String? status; + + /// Errors. + /// + /// Typically populated if [status] is [statusFailure]. + @JsonKey(includeIfNull: false, fromJson: _fromJsonListAnswerForField) + List? errors; + + /// Warnings. + /// + /// Typically populated if [status] is [statusWarning]. + @JsonKey(includeIfNull: false, fromJson: _fromJsonListAnswerForField) + List? warnings; + + @JsonKey(includeIfNull: false) + Product? product; + + /// Possible value for [status]: the operation failed. + static const String statusFailure = 'failure'; + + /// Possible value for [status]: the operation succeeded with warnings. + static const String statusWarning = 'success_with_warnings'; + + /// Possible value for [status]: the operation succeeded. + static const String statusSuccess = 'success'; + + /// Possible value for [result.id]: product found + static const String resultProductFound = 'product_found'; + + /// Possible value for [result.id]: product not found + static const String resultProductNotFound = 'product_not_found'; + + factory ProductResultV3.fromJson(Map json) => + _$ProductResultV3FromJson(json); + + @override + Map toJson() => _$ProductResultV3ToJson(this); + + @override + String toString() => toJson().toString(); + + /// From a `List` in `dynamic`'s clothing (JsonKey) + static List? _fromJsonListAnswerForField( + dynamic list) { + if (list == null) { + return null; + } + if (list is! List) { + throw Exception('Expected type: List, got ${list.runtimeType}'); + } + final List result = []; + for (final item in list) { + result.add(ProductResultFieldAnswer.fromJson(item)); + } + return result; + } +} diff --git a/lib/model/ProductResultV3.g.dart b/lib/model/ProductResultV3.g.dart new file mode 100644 index 0000000000..22dafec9be --- /dev/null +++ b/lib/model/ProductResultV3.g.dart @@ -0,0 +1,38 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'ProductResultV3.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +ProductResultV3 _$ProductResultV3FromJson(Map json) => + ProductResultV3() + ..barcode = json['code'] as String? + ..result = json['result'] == null + ? null + : LocalizedTag.fromJson(json['result'] as Map) + ..status = json['status'] as String? + ..errors = ProductResultV3._fromJsonListAnswerForField(json['errors']) + ..warnings = ProductResultV3._fromJsonListAnswerForField(json['warnings']) + ..product = json['product'] == null + ? null + : Product.fromJson(json['product'] as Map); + +Map _$ProductResultV3ToJson(ProductResultV3 instance) { + final val = {}; + + void writeNotNull(String key, dynamic value) { + if (value != null) { + val[key] = value; + } + } + + writeNotNull('code', instance.barcode); + writeNotNull('result', instance.result); + writeNotNull('status', instance.status); + writeNotNull('errors', instance.errors); + writeNotNull('warnings', instance.warnings); + writeNotNull('product', instance.product); + return val; +} diff --git a/lib/openfoodfacts.dart b/lib/openfoodfacts.dart index 374ec98b7a..d721a27bfb 100644 --- a/lib/openfoodfacts.dart +++ b/lib/openfoodfacts.dart @@ -6,6 +6,7 @@ import 'dart:developer'; import 'package:http/http.dart'; import 'package:openfoodfacts/interface/JsonObject.dart'; +import 'package:openfoodfacts/model/ProductResultV3.dart'; import 'package:openfoodfacts/model/KnowledgePanels.dart'; import 'package:openfoodfacts/model/LoginStatus.dart'; import 'package:openfoodfacts/model/OcrIngredientsResult.dart'; @@ -180,6 +181,8 @@ class OpenFoodAPIClient { /// No parsing of ingredients. /// No adjustment by language. /// No replacing of '"' with '"'. +// TODO: deprecated from 2022-12-01; remove when old enough + @Deprecated('Use getProductV3 instead') static Future getProductRaw( String barcode, OpenFoodFactsLanguage language, { @@ -205,11 +208,16 @@ class OpenFoodAPIClient { /// /// Please read the language mechanics explanation if you intend to show /// or update data in specific language: https://github.com/openfoodfacts/openfoodfacts-dart/blob/master/DOCUMENTATION.md#about-languages-mechanics +// TODO: deprecated from 2022-12-01; remove when old enough + @Deprecated('Use getProductV3 instead') static Future getProduct( ProductQueryConfiguration configuration, { User? user, QueryType? queryType, }) async { + if (configuration.matchesV3()) { + Exception("The configuration must not match V3!"); + } final String productString = await getProductString( configuration, user: user, @@ -224,6 +232,35 @@ class OpenFoodAPIClient { return result; } + /// Returns the product for the given barcode. + /// The ProductResult does not contain a product, if the product is not available. + /// ingredients, images and product name will be prepared for the given language. + /// + /// Please read the language mechanics explanation if you intend to show + /// or update data in specific language: https://github.com/openfoodfacts/openfoodfacts-dart/blob/master/DOCUMENTATION.md#about-languages-mechanics + static Future getProductV3( + ProductQueryConfiguration configuration, { + User? user, + QueryType? queryType, + }) async { + if (!configuration.matchesV3()) { + Exception("The configuration must match V3!"); + } + final String productString = await getProductString( + configuration, + user: user, + queryType: queryType, + ); + final String jsonStr = _replaceQuotes(productString); + final ProductResultV3 result = + ProductResultV3.fromJson(jsonDecode(jsonStr)); + if (result.product != null) { + ProductHelper.removeImages(result.product!, configuration.language); + ProductHelper.createImageUrls(result.product!, queryType: queryType); + } + return result; + } + /// Returns the response body of "get product" API for the given barcode. static Future getProductString( final ProductQueryConfiguration configuration, { diff --git a/lib/utils/ProductQueryConfigurations.dart b/lib/utils/ProductQueryConfigurations.dart index 89bccaaedb..2d2a177020 100644 --- a/lib/utils/ProductQueryConfigurations.dart +++ b/lib/utils/ProductQueryConfigurations.dart @@ -2,6 +2,11 @@ import 'package:openfoodfacts/utils/AbstractQueryConfiguration.dart'; import 'package:openfoodfacts/utils/CountryHelper.dart'; import 'package:openfoodfacts/utils/LanguageHelper.dart'; import 'package:openfoodfacts/utils/ProductFields.dart'; +import 'package:http/http.dart'; +import 'package:openfoodfacts/model/User.dart'; +import 'package:openfoodfacts/utils/HttpHelper.dart'; +import 'package:openfoodfacts/utils/QueryType.dart'; +import 'package:openfoodfacts/utils/UriHelper.dart'; /// Query version for single barcode class ProductQueryVersion { @@ -11,6 +16,7 @@ class ProductQueryVersion { static const ProductQueryVersion v0 = ProductQueryVersion(0); static const ProductQueryVersion v2 = ProductQueryVersion(2); + static const ProductQueryVersion v3 = ProductQueryVersion(3); String getPath(final String barcode) { if (version == 0) { @@ -18,6 +24,8 @@ class ProductQueryVersion { } return '/api/v$version/product/$barcode/'; } + + bool matchesV3() => version >= 3; } /// Query Configuration for single barcode @@ -41,6 +49,36 @@ class ProductQueryConfiguration extends AbstractQueryConfiguration { fields: fields, ); + bool matchesV3() => version.matchesV3(); + @override String getUriPath() => version.getPath(barcode); + + @override + Future getResponse( + final User? user, + final QueryType? queryType, + ) async { + if (version == ProductQueryVersion.v3) { + return await HttpHelper().doGetRequest( + UriHelper.getUri( + path: getUriPath(), + queryType: queryType, + queryParameters: getParametersMap(), + ), + user: user, + queryType: queryType, + ); + } + return await HttpHelper().doPostRequest( + UriHelper.getPostUri( + path: getUriPath(), + queryType: queryType, + ), + getParametersMap(), + user, + queryType: queryType, + addCredentialsToBody: false, + ); + } } diff --git a/test/api_addProductImage_test.dart b/test/api_addProductImage_test.dart index 3d2c7ab287..cc8cac2c2d 100644 --- a/test/api_addProductImage_test.dart +++ b/test/api_addProductImage_test.dart @@ -1,5 +1,6 @@ import 'dart:math' as math; +import 'package:openfoodfacts/model/ProductResultV3.dart'; import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:openfoodfacts/utils/OpenFoodAPIConfiguration.dart'; import 'package:openfoodfacts/utils/QueryType.dart'; @@ -66,9 +67,10 @@ void main() { final ProductQueryConfiguration configurations = ProductQueryConfiguration( barcode, fields: [ProductField.IMAGES], + version: ProductQueryVersion.v3, ); - final ProductResult result = - await OpenFoodAPIClient.getProduct(configurations); + final ProductResultV3 result = + await OpenFoodAPIClient.getProductV3(configurations); expect(result.status, isNotNull); expect(result.product!.images, isNotEmpty); @@ -132,8 +134,11 @@ void main() { test('read image', () async { //Get product without setting ProductField final ProductQueryConfiguration configurations = - ProductQueryConfiguration(barcode); - final ProductResult result = await OpenFoodAPIClient.getProduct( + ProductQueryConfiguration( + barcode, + version: ProductQueryVersion.v3, + ); + final ProductResultV3 result = await OpenFoodAPIClient.getProductV3( configurations, user: user, ); @@ -239,10 +244,12 @@ void main() { language: language, ); - final ProductResult productResult = await OpenFoodAPIClient.getProduct( + final ProductResultV3 productResult = + await OpenFoodAPIClient.getProductV3( ProductQueryConfiguration( barcode, fields: [ProductField.SELECTED_IMAGE], + version: ProductQueryVersion.v3, ), ); expect(productResult.product, isNotNull); diff --git a/test/api_getProductRaw_test.dart b/test/api_getProductRaw_test.dart deleted file mode 100644 index bbaf1f0acc..0000000000 --- a/test/api_getProductRaw_test.dart +++ /dev/null @@ -1,130 +0,0 @@ -import 'package:openfoodfacts/model/Nutrient.dart'; -import 'package:openfoodfacts/model/NutrientLevels.dart'; -import 'package:openfoodfacts/model/Nutriments.dart'; -import 'package:openfoodfacts/model/PerSize.dart'; -import 'package:openfoodfacts/openfoodfacts.dart'; -import 'package:openfoodfacts/utils/OpenFoodAPIConfiguration.dart'; -import 'package:openfoodfacts/utils/QueryType.dart'; -import 'package:test/test.dart'; - -import 'test_constants.dart'; - -void main() { - OpenFoodAPIConfiguration.globalQueryType = QueryType.PROD; - OpenFoodAPIConfiguration.globalUser = TestConstants.PROD_USER; - - group('$OpenFoodAPIClient get raw products', () { - test('get product test 1', () async { - const String barcode = '8008698011065'; - final ProductResult result = await OpenFoodAPIClient.getProductRaw( - barcode, - OpenFoodFactsLanguage.GERMAN, - ); - - expect(result.status, 1); - expect(result.barcode, barcode); - expect(result.product, isNotNull); - expect(result.product!.barcode, barcode); - expect(result.product!.quantity, '350g'); - expect(result.product!.ingredients, isNotNull); - expect(result.product!.selectedImages, isNotNull); - expect(result.product!.selectedImages!.length, - greaterThan(20)); // 2022-04-01 value was 21 - expect(result.product!.images, isNotNull); - expect(result.product!.images!, isNotEmpty); - expect(result.product!.labelsTags!.contains('en:gluten-free'), false); - expect(result.product!.tracesTags, isNotNull); - expect(result.product!.tracesTags!, contains('en:lupin')); - - expect(result.product!.nutriments, isNotNull); - final Nutriments nutriments = result.product!.nutriments!; - - const PerSize perSize = PerSize.oneHundredGrams; - expect(nutriments.getValue(Nutrient.energyKJ, perSize), 1099.0); - expect(nutriments.getValue(Nutrient.sugars, perSize), 0.9); - expect(nutriments.getValue(Nutrient.salt, perSize), 1.0); - expect(nutriments.getValue(Nutrient.fiber, perSize), 8.8); - expect(nutriments.getValue(Nutrient.fat, perSize), 9.2); - expect(nutriments.getValue(Nutrient.saturatedFat, perSize), 1.1); - expect(nutriments.getValue(Nutrient.proteins, perSize), 4.5); - - expect(result.product!.additives!.ids, isEmpty); - - expect( - result.product!.nutrientLevels!.levels[NutrientLevels.NUTRIENT_SUGARS], - Level.LOW, - ); - expect( - result.product!.nutrientLevels!.levels[NutrientLevels.NUTRIENT_FAT], - Level.MODERATE, - ); - expect( - result.product!.nutrientLevels! - .levels[NutrientLevels.NUTRIENT_SATURATED_FAT], - Level.LOW, - ); - expect( - result.product!.nutrientLevels!.levels[NutrientLevels.NUTRIENT_SALT], - Level.MODERATE, - ); - expect( - result.product!.countries, - 'Bélgica,Francia,Alemania,Países Bajos,España,Suiza', - ); - }); - - test('get product tiny twists - Rold Gold Pretzels - 16 OZ. (1 LB) 453.6g', - () async { - const String barcode = '0028400047685'; - final ProductQueryConfiguration configurations = - ProductQueryConfiguration(barcode, - language: OpenFoodFactsLanguage.ENGLISH, - fields: [ProductField.ALL]); - final ProductResult result = await OpenFoodAPIClient.getProduct( - configurations, - ); - expect(result.status, 1); - expect(result.barcode, barcode); - expect(result.product, isNotNull); - expect(result.product!.barcode, barcode); - expect(result.product!.nutriments, isNotNull); - final Nutriments nutriments = result.product!.nutriments!; - - const PerSize perSize = PerSize.serving; - expect(nutriments.getValue(Nutrient.carbohydrates, perSize), isNotNull); - expect(nutriments.getValue(Nutrient.proteins, perSize), isNotNull); - expect(nutriments.getValue(Nutrient.salt, perSize), isNotNull); - expect(nutriments.getValue(Nutrient.proteins, perSize), isNotNull); - expect(nutriments.getValue(Nutrient.fat, perSize), isNotNull); - }); - - test('get product test 2', () async { - const String barcode = '4388810057787'; - - final ProductResult result = await OpenFoodAPIClient.getProductRaw( - barcode, - OpenFoodFactsLanguage.GERMAN, - ); - - expect(result.status, 1); - expect(result.barcode, barcode); - expect(result.product, isNotNull); - expect(result.product!.barcode, barcode); - - expect(result.product!.productName, 'Wasser Elitess Still, Neutral'); - - expect(result.product!.nutriments, isNotNull); - final Nutriments nutriments = result.product!.nutriments!; - - const PerSize perSize = PerSize.oneHundredGrams; - expect(nutriments.getComputedKJ(perSize), 0.0); - expect(nutriments.getValue(Nutrient.sugars, perSize), 0.0); - expect(nutriments.getValue(Nutrient.salt, perSize), 0.0); - expect(nutriments.getValue(Nutrient.fiber, perSize), isNull); - expect(nutriments.getValue(Nutrient.fat, perSize), 0.0); - expect(nutriments.getValue(Nutrient.saturatedFat, perSize), 0.0); - expect(nutriments.getValue(Nutrient.proteins, perSize), 0.0); - expect(nutriments.getValue(Nutrient.fat, PerSize.serving), isNull); - }); - }); -} diff --git a/test/api_getProduct_test.dart b/test/api_getProduct_test.dart index dfc1fc1953..e7bdc41639 100644 --- a/test/api_getProduct_test.dart +++ b/test/api_getProduct_test.dart @@ -5,6 +5,7 @@ import 'package:openfoodfacts/model/Nutrient.dart'; import 'package:openfoodfacts/model/NutrientLevels.dart'; import 'package:openfoodfacts/model/Nutriments.dart'; import 'package:openfoodfacts/model/PerSize.dart'; +import 'package:openfoodfacts/model/ProductResultV3.dart'; import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:openfoodfacts/utils/CountryHelper.dart'; import 'package:openfoodfacts/utils/InvalidBarcodes.dart'; @@ -23,6 +24,36 @@ void main() { OpenFoodAPIConfiguration.globalQueryType = QueryType.TEST; + void _findExpectedIngredients( + final List ingredients, + final List labels, + ) { + bool foundIngredient( + final String label, + final List ingredients, + ) { + for (final Ingredient ingredient in ingredients) { + if (ingredient.text == label) { + return true; + } + if (ingredient.ingredients != null) { + if (foundIngredient(label, ingredient.ingredients!)) { + return true; + } + } + } + return false; + } + + for (final String label in labels) { + expect( + foundIngredient(label, ingredients), + true, + reason: 'Could not find ingredient "$label"', + ); + } + } + group('$OpenFoodAPIClient get products', () { test('get product Coca Cola Light', () async { const String barcode = '1111111111111'; @@ -76,13 +107,14 @@ void main() { barcode, language: OpenFoodFactsLanguage.GERMAN, fields: [ProductField.ALL], + version: ProductQueryVersion.v3, ); - final ProductResult result = await OpenFoodAPIClient.getProduct( + final ProductResultV3 result = await OpenFoodAPIClient.getProductV3( configurations, user: TestConstants.TEST_USER, ); - expect(result.status, 1); + expect(result.status, ProductResultV3.statusSuccess); expect(result.barcode, barcode); expect(result.product, isNotNull); final Product product = result.product!; @@ -117,17 +149,20 @@ void main() { //Refactor the test once the issue #48 is fixed String barcode = '0028400047685'; - ProductQueryConfiguration configurations = ProductQueryConfiguration( - barcode, - language: OpenFoodFactsLanguage.ENGLISH, - fields: [ProductField.ALL]); - ProductResult result = await OpenFoodAPIClient.getProduct( + final ProductQueryConfiguration configurations = + ProductQueryConfiguration( + barcode, + language: OpenFoodFactsLanguage.ENGLISH, + fields: [ProductField.ALL], + version: ProductQueryVersion.v3, + ); + final ProductResultV3 result = await OpenFoodAPIClient.getProductV3( configurations, user: TestConstants.TEST_USER, ); - expect(result.status, 1); + expect(result.status, ProductResultV3.statusSuccess); expect(result.barcode, barcode); - expect(result.product != null, true); + expect(result.product, isNotNull); expect(result.product!.barcode, barcode); expect(result.product!.nutriments, isNotNull); @@ -153,12 +188,13 @@ void main() { barcode, languages: languages, fields: [ProductField.PACKAGING_TEXT_IN_LANGUAGES], + version: ProductQueryVersion.v3, ); - final ProductResult result = await OpenFoodAPIClient.getProduct( + final ProductResultV3 result = await OpenFoodAPIClient.getProductV3( configurations, user: TestConstants.TEST_USER, ); - expect(result.status, 1); + expect(result.status, ProductResultV3.statusSuccess); expect(result.product, isNotNull); expect(result.product!.packagingTextInLanguages, isNotNull); for (final OpenFoodFactsLanguage language in languages) { @@ -170,14 +206,17 @@ void main() { const String barcode = '3119780259625'; final ProductQueryConfiguration configurations = - ProductQueryConfiguration(barcode, - language: OpenFoodFactsLanguage.ENGLISH, - fields: [ProductField.ALL]); - ProductResult result = await OpenFoodAPIClient.getProduct( + ProductQueryConfiguration( + barcode, + language: OpenFoodFactsLanguage.ENGLISH, + fields: [ProductField.ALL], + version: ProductQueryVersion.v3, + ); + ProductResultV3 result = await OpenFoodAPIClient.getProductV3( configurations, user: TestConstants.TEST_USER, ); - expect(result.status, 1); + expect(result.status, ProductResultV3.statusSuccess); expect(result.barcode, barcode); expect(result.product != null, true); expect(result.product!.barcode, barcode); @@ -200,78 +239,54 @@ void main() { test('get product Danish Butter Cookies & Chocolate Chip Cookies', () async { - String barcode = BARCODE_DANISH_BUTTER_COOKIES; - ProductQueryConfiguration configurations = ProductQueryConfiguration( - barcode, - language: OpenFoodFactsLanguage.GERMAN, - fields: [ProductField.ALL]); - ProductResult result = await OpenFoodAPIClient.getProduct( + const String barcode = BARCODE_DANISH_BUTTER_COOKIES; + final ProductQueryConfiguration configurations = + ProductQueryConfiguration( + barcode, + language: OpenFoodFactsLanguage.GERMAN, + fields: [ProductField.ALL], + version: ProductQueryVersion.v3, + ); + final ProductResultV3 result = await OpenFoodAPIClient.getProductV3( configurations, user: TestConstants.TEST_USER, ); - expect(result.status, 1); + expect(result.status, ProductResultV3.statusSuccess); expect(result.barcode, barcode); - expect(result.product != null, true); + expect(result.product, isNotNull); expect(result.product!.barcode, barcode); expect(result.product!.brandsTags![0], 'kelsin'); // only german ingredients - expect(result.product!.ingredientsText != null, true); - - expect(result.product!.ingredients != null, true); - expect(result.product!.ingredients!.length, 24); - - expect(result.product!.ingredients!.any((i) => i.text == 'Buttergebäck'), - true); - expect(result.product!.ingredients!.any((i) => i.text == 'Weizenmehl'), - false); - expect(result.product!.ingredients!.any((i) => i.text == 'Zucker'), true); - expect( - result.product!.ingredients!.any((i) => i.text == 'Butter'), false); - expect(result.product!.ingredients!.any((i) => i.text == 'Speisesalz'), - true); - - expect( - result.product!.ingredients!.any((i) => i.text == 'Backtriebmittel'), - true); - expect( - result.product!.ingredients! - .any((i) => i.text == 'Ammouniumhydrogencarbonat'), - true); - expect( - result.product!.ingredients! - .any((i) => i.text == 'Invertzuckersirup'), - true); - expect( - result.product!.ingredients! - .any((i) => i.text == 'natürliches Aroma'), - true); - expect( - result.product!.ingredients! - .any((i) => i.text == 'Schokolade Mürbegebäck'), - true); + expect(result.product!.ingredientsText, isNotNull); - expect(result.product!.ingredients!.any((i) => i.text == 'Pflanzenfett'), - true); - expect(result.product!.ingredients!.any((i) => i.text == 'Palm'), true); - expect( - result.product!.ingredients! - .any((i) => i.text == 'Schokoladenstückchen'), - true); - expect(result.product!.ingredients!.any((i) => i.text == 'Kakaomasse'), - true); - expect(result.product!.ingredients!.any((i) => i.text == 'Kakaobutter'), - true); + expect(result.product!.ingredients, isNotNull); + expect(result.product!.ingredients!.length, 9); - expect( - result.product!.ingredients!.any((i) => i.text == 'Emulgator'), true); - expect( - result.product!.ingredients!.any((i) => i.text == 'Lecithin'), true); - expect( - result.product!.ingredients! - .any((i) => i.text == 'fettarmes Kakaopulver'), - true); + _findExpectedIngredients( + result.product!.ingredients!, + [ + 'Buttergebäck', + '_Weizenmehl_', + 'Zucker', + '_Butter_', + 'Speisesalz', + 'Backtriebmittel', + 'Ammouniumhydrogencarbonat', + 'Invertzuckersirup', + 'natürliches Aroma', + 'Schokolade Mürbegebäck', + 'Pflanzenfett', + 'Palm', + 'Schokoladenstückchen', + 'Kakaomasse', + 'Kakaobutter', + 'Emulgator', + 'Lecithin', + 'fettarmes Kakaopulver', + ], + ); expect(result.product!.selectedImages!.length, 9); @@ -295,15 +310,17 @@ void main() { () async { String barcode = '0038900009472'; ProductQueryConfiguration configurations = ProductQueryConfiguration( - barcode, - language: OpenFoodFactsLanguage.ENGLISH, - fields: [ProductField.ALL]); - ProductResult result = await OpenFoodAPIClient.getProduct( + barcode, + language: OpenFoodFactsLanguage.ENGLISH, + fields: [ProductField.ALL], + version: ProductQueryVersion.v3, + ); + ProductResultV3 result = await OpenFoodAPIClient.getProductV3( configurations, user: TestConstants.TEST_USER, ); - expect(result.status, 1); + expect(result.status, ProductResultV3.statusSuccess); expect(result.barcode, barcode); expect(result.product != null, true); expect(result.product!.barcode, barcode); @@ -322,14 +339,15 @@ void main() { const User user = TestConstants.PROD_USER; const OpenFoodFactsLanguage language = OpenFoodFactsLanguage.FRENCH; const List fields = [ProductField.NUTRIMENTS]; - ProductResult result; + ProductResultV3 result; late Nutriments nutriments; - result = await OpenFoodAPIClient.getProduct( + result = await OpenFoodAPIClient.getProductV3( ProductQueryConfiguration( '5060517883638', language: language, fields: fields, + version: ProductQueryVersion.v3, ), user: user, queryType: queryType, @@ -345,11 +363,12 @@ void main() { isNull, ); - result = await OpenFoodAPIClient.getProduct( + result = await OpenFoodAPIClient.getProductV3( ProductQueryConfiguration( '7612100018477', language: language, fields: fields, + version: ProductQueryVersion.v3, ), user: user, queryType: queryType, @@ -362,11 +381,12 @@ void main() { ); expect(nutriments.getValue(Nutrient.biotin, PerSize.serving), isNull); - result = await OpenFoodAPIClient.getProduct( + result = await OpenFoodAPIClient.getProductV3( ProductQueryConfiguration( '3057640257773', language: language, fields: fields, + version: ProductQueryVersion.v3, ), user: user, queryType: queryType, @@ -382,11 +402,12 @@ void main() { .015, ); - result = await OpenFoodAPIClient.getProduct( + result = await OpenFoodAPIClient.getProductV3( ProductQueryConfiguration( '4260556630007', language: language, fields: fields, + version: ProductQueryVersion.v3, ), user: user, queryType: queryType, @@ -426,11 +447,12 @@ void main() { .00002, ); - result = await OpenFoodAPIClient.getProduct( + result = await OpenFoodAPIClient.getProductV3( ProductQueryConfiguration( '3155251205319', language: language, fields: fields, + version: ProductQueryVersion.v3, ), user: user, queryType: queryType, @@ -454,11 +476,12 @@ void main() { 9.1, ); - result = await OpenFoodAPIClient.getProduct( + result = await OpenFoodAPIClient.getProductV3( ProductQueryConfiguration( '5000159461122', language: language, fields: fields, + version: ProductQueryVersion.v3, ), user: user, queryType: queryType, @@ -478,15 +501,17 @@ void main() { test('get product Confiture Rhubarbe Fraises extra', () async { String barcode = '3301595000305'; ProductQueryConfiguration configurations = ProductQueryConfiguration( - barcode, - language: OpenFoodFactsLanguage.FRENCH, - fields: [ProductField.ALL]); - ProductResult result = await OpenFoodAPIClient.getProduct( + barcode, + language: OpenFoodFactsLanguage.FRENCH, + fields: [ProductField.ALL], + version: ProductQueryVersion.v3, + ); + ProductResultV3 result = await OpenFoodAPIClient.getProductV3( configurations, user: TestConstants.TEST_USER, ); - expect(result.status, 1); + expect(result.status, ProductResultV3.statusSuccess); expect(result.barcode, barcode); expect(result.product != null, true); expect(result.product!.barcode, barcode); @@ -596,10 +621,12 @@ void main() { test('product not available', () async { String barcode = BARCODE_UNKNOWN; ProductQueryConfiguration configurations = ProductQueryConfiguration( - barcode, - language: OpenFoodFactsLanguage.GERMAN, - fields: [ProductField.ALL]); - ProductResult result = await OpenFoodAPIClient.getProduct( + barcode, + language: OpenFoodFactsLanguage.GERMAN, + fields: [ProductField.ALL], + version: ProductQueryVersion.v3, + ); + ProductResultV3 result = await OpenFoodAPIClient.getProductV3( configurations, user: TestConstants.TEST_USER, ); @@ -609,10 +636,12 @@ void main() { test('product ingredients', () async { String barcode = '4316268596299'; ProductQueryConfiguration configurations = ProductQueryConfiguration( - barcode, - language: OpenFoodFactsLanguage.GERMAN, - fields: [ProductField.ALL]); - ProductResult result = await OpenFoodAPIClient.getProduct( + barcode, + language: OpenFoodFactsLanguage.GERMAN, + fields: [ProductField.ALL], + version: ProductQueryVersion.v3, + ); + ProductResultV3 result = await OpenFoodAPIClient.getProductV3( configurations, user: TestConstants.TEST_USER, ); @@ -624,14 +653,16 @@ void main() { test('product ecoscore', () async { String barcode = '3229820129488'; ProductQueryConfiguration configurations = ProductQueryConfiguration( - barcode, - language: OpenFoodFactsLanguage.ENGLISH, - fields: [ - ProductField.ECOSCORE_GRADE, - ProductField.ECOSCORE_SCORE, - ProductField.ECOSCORE_DATA - ]); - ProductResult result = await OpenFoodAPIClient.getProduct( + barcode, + language: OpenFoodFactsLanguage.ENGLISH, + fields: [ + ProductField.ECOSCORE_GRADE, + ProductField.ECOSCORE_SCORE, + ProductField.ECOSCORE_DATA + ], + version: ProductQueryVersion.v3, + ); + ProductResultV3 result = await OpenFoodAPIClient.getProductV3( configurations, user: TestConstants.TEST_USER, ); @@ -647,10 +678,12 @@ void main() { test('product fields', () async { String barcode = '20004361'; ProductQueryConfiguration configurations = ProductQueryConfiguration( - barcode, - language: OpenFoodFactsLanguage.GERMAN, - fields: [ProductField.NAME, ProductField.BRANDS_TAGS]); - ProductResult result = await OpenFoodAPIClient.getProduct( + barcode, + language: OpenFoodFactsLanguage.GERMAN, + fields: [ProductField.NAME, ProductField.BRANDS_TAGS], + version: ProductQueryVersion.v3, + ); + ProductResultV3 result = await OpenFoodAPIClient.getProductV3( configurations, user: TestConstants.TEST_USER, ); @@ -666,10 +699,13 @@ void main() { expect(result.product!.nutrientLevels!.levels, isEmpty); expect(result.product!.lang, OpenFoodFactsLanguage.UNDEFINED); - configurations = ProductQueryConfiguration(barcode, - language: OpenFoodFactsLanguage.GERMAN, - fields: [ProductField.NAME, ProductField.LANGUAGE]); - result = await OpenFoodAPIClient.getProduct( + configurations = ProductQueryConfiguration( + barcode, + language: OpenFoodFactsLanguage.GERMAN, + fields: [ProductField.NAME, ProductField.LANGUAGE], + version: ProductQueryVersion.v3, + ); + result = await OpenFoodAPIClient.getProductV3( configurations, user: TestConstants.TEST_USER, ); @@ -685,10 +721,13 @@ void main() { expect(result.product!.nutrientLevels!.levels, isEmpty); expect(result.product!.lang, OpenFoodFactsLanguage.ENGLISH); - configurations = ProductQueryConfiguration(barcode, - language: OpenFoodFactsLanguage.GERMAN, - fields: [ProductField.NAME, ProductField.COUNTRIES]); - result = await OpenFoodAPIClient.getProduct( + configurations = ProductQueryConfiguration( + barcode, + language: OpenFoodFactsLanguage.GERMAN, + fields: [ProductField.NAME, ProductField.COUNTRIES], + version: ProductQueryVersion.v3, + ); + result = await OpenFoodAPIClient.getProductV3( configurations, user: TestConstants.TEST_USER, ); @@ -705,10 +744,13 @@ void main() { expect(result.product!.lang, OpenFoodFactsLanguage.UNDEFINED); expect(result.product!.countries, isNotNull); - configurations = ProductQueryConfiguration(barcode, - language: OpenFoodFactsLanguage.GERMAN, - fields: [ProductField.NAME, ProductField.COUNTRIES_TAGS]); - result = await OpenFoodAPIClient.getProduct( + configurations = ProductQueryConfiguration( + barcode, + language: OpenFoodFactsLanguage.GERMAN, + fields: [ProductField.NAME, ProductField.COUNTRIES_TAGS], + version: ProductQueryVersion.v3, + ); + result = await OpenFoodAPIClient.getProductV3( configurations, user: TestConstants.TEST_USER, ); @@ -729,10 +771,12 @@ void main() { test('attribute groups', () async { String barcode = '3700214614266'; ProductQueryConfiguration configurations = ProductQueryConfiguration( - barcode, - language: OpenFoodFactsLanguage.ENGLISH, - fields: [ProductField.NAME, ProductField.ATTRIBUTE_GROUPS]); - ProductResult result = await OpenFoodAPIClient.getProduct( + barcode, + language: OpenFoodFactsLanguage.ENGLISH, + fields: [ProductField.NAME, ProductField.ATTRIBUTE_GROUPS], + version: ProductQueryVersion.v3, + ); + ProductResultV3 result = await OpenFoodAPIClient.getProductV3( configurations, user: TestConstants.TEST_USER, ); @@ -781,14 +825,16 @@ void main() { String barcode = '5000112548167'; //Get product without setting OpenFoodFactsLanguage or ProductField - ProductQueryConfiguration configurations = - ProductQueryConfiguration(barcode); - ProductResult result = await OpenFoodAPIClient.getProduct( + ProductQueryConfiguration configurations = ProductQueryConfiguration( + barcode, + version: ProductQueryVersion.v3, + ); + ProductResultV3 result = await OpenFoodAPIClient.getProductV3( configurations, user: TestConstants.TEST_USER, ); - expect(result.status, 1); + expect(result.status, ProductResultV3.statusSuccess); expect(result.barcode, barcode); expect(result.product != null, true); expect(result.product!.barcode, barcode); @@ -796,8 +842,8 @@ void main() { expect(result.product!.ingredientsText != null, true); expect(result.product!.ingredients != null, true); - expect(result.product!.ingredients!.length, 13); - expect(result.product!.ingredients!.any((i) => i.text == 'Aroma'), true); + expect(result.product!.ingredients!.length, 7); + _findExpectedIngredients(result.product!.ingredients!, ['Aroma']); expect(result.product!.additives!.ids[0], 'en:e150d'); expect(result.product!.additives!.names[0], 'E150d'); @@ -824,27 +870,34 @@ void main() { 'https://static.openfoodfacts.net/images/products/500/011/254/8167/ingredients_de.7.400.jpg'); //Get product without setting ProductField - configurations = ProductQueryConfiguration(barcode, - language: OpenFoodFactsLanguage.GERMAN); - result = await OpenFoodAPIClient.getProduct( + configurations = ProductQueryConfiguration( + barcode, + language: OpenFoodFactsLanguage.GERMAN, + version: ProductQueryVersion.v3, + ); + result = await OpenFoodAPIClient.getProductV3( configurations, user: TestConstants.TEST_USER, ); - expect(result.status, 1); + expect(result.status, ProductResultV3.statusSuccess); expect(result.barcode, barcode); - expect(result.product != null, true); + expect(result.product, isNotNull); expect(result.product!.barcode, barcode); - expect(result.product!.lastModified != null, true); + expect(result.product!.lastModified, isNotNull); - expect(result.product!.ingredientsText != null, true); + expect(result.product!.ingredientsText, isNotNull); - expect(result.product!.ingredients != null, true); - expect(result.product!.ingredients!.length, 13); + expect(result.product!.ingredients, isNotNull); + expect(result.product!.ingredients!.length, 7); - expect(result.product!.ingredients!.any((i) => i.text == 'Wasser'), true); - expect(result.product!.ingredients!.any((i) => i.text == 'Kohlensäure'), - true); + _findExpectedIngredients( + result.product!.ingredients!, + [ + 'Wasser', + 'Kohlensäure', + ], + ); expect(result.product!.additives!.ids[0], 'en:e150d'); expect(result.product!.additives!.names[0], 'E150d'); @@ -871,32 +924,37 @@ void main() { 'https://static.openfoodfacts.net/images/products/500/011/254/8167/ingredients_de.7.400.jpg'); //Get product without setting OpenFoodFactsLanguage - configurations = - ProductQueryConfiguration(barcode, fields: [ProductField.ALL]); - result = await OpenFoodAPIClient.getProduct( + configurations = ProductQueryConfiguration( + barcode, + fields: [ProductField.ALL], + version: ProductQueryVersion.v3, + ); + result = await OpenFoodAPIClient.getProductV3( configurations, user: TestConstants.TEST_USER, ); - expect(result.status, 1); + expect(result.status, ProductResultV3.statusSuccess); expect(result.barcode, barcode); - expect(result.product != null, true); + expect(result.product, isNotNull); expect(result.product!.barcode, barcode); - expect(result.product!.lastModified != null, true); - - expect(result.product!.ingredientsText != null, true); + expect(result.product!.lastModified, isNotNull); - expect(result.product!.ingredients != null, true); - expect(result.product!.ingredients!.length, 13); + expect(result.product!.ingredientsText, isNotNull); - expect(result.product!.ingredients!.any((i) => i.text == 'Wasser'), true); - expect(result.product!.ingredients!.any((i) => i.text == 'Kohlensäure'), - true); - expect(result.product!.ingredients!.any((i) => i.text == 'Süßungsmittel'), - true); - expect(result.product!.ingredients!.any((i) => i.text == 'Aroma'), true); - expect(result.product!.ingredients!.any((i) => i.text == 'Aroma Koffein'), - true); + expect(result.product!.ingredients, isNotNull); + expect(result.product!.ingredients!.length, 7); + + _findExpectedIngredients( + result.product!.ingredients!, + [ + 'Wasser', + 'Kohlensäure', + 'Süßungsmittel', + 'Aroma', + 'Aroma Koffein', + ], + ); expect(result.product!.selectedImages!.length, 15); @@ -929,7 +987,7 @@ void main() { result.product!.nutrientLevels!.levels[NutrientLevels.NUTRIENT_SALT], Level.LOW); - expect(result.product!.images != null, true); + expect(result.product!.images, isNotNull); expect(result.product!.images!.length, 20); expect( result.product!.images! @@ -951,10 +1009,12 @@ void main() { () async { String barcode = BARCODE_DANISH_BUTTER_COOKIES; ProductQueryConfiguration configurations = ProductQueryConfiguration( - barcode, - language: OpenFoodFactsLanguage.GERMAN, - fields: [ProductField.ALL]); - ProductResult result = await OpenFoodAPIClient.getProduct( + barcode, + language: OpenFoodFactsLanguage.GERMAN, + fields: [ProductField.ALL], + version: ProductQueryVersion.v3, + ); + ProductResultV3 result = await OpenFoodAPIClient.getProductV3( configurations, user: TestConstants.TEST_USER, ); @@ -1000,14 +1060,22 @@ void main() { ProductField.COUNTRIES_TAGS_IN_LANGUAGES, ]; - ProductQueryConfiguration englishConf = ProductQueryConfiguration(barcode, - language: OpenFoodFactsLanguage.ENGLISH, fields: fields); - ProductQueryConfiguration russianConf = ProductQueryConfiguration(barcode, - language: OpenFoodFactsLanguage.RUSSIAN, fields: fields); + ProductQueryConfiguration englishConf = ProductQueryConfiguration( + barcode, + language: OpenFoodFactsLanguage.ENGLISH, + fields: fields, + version: ProductQueryVersion.v3, + ); + ProductQueryConfiguration russianConf = ProductQueryConfiguration( + barcode, + language: OpenFoodFactsLanguage.RUSSIAN, + fields: fields, + version: ProductQueryVersion.v3, + ); // English! - ProductResult englishResult = await OpenFoodAPIClient.getProduct( + ProductResultV3 englishResult = await OpenFoodAPIClient.getProductV3( englishConf, user: TestConstants.TEST_USER, ); @@ -1044,7 +1112,7 @@ void main() { // Russian! - ProductResult russianResult = await OpenFoodAPIClient.getProduct( + ProductResultV3 russianResult = await OpenFoodAPIClient.getProductV3( russianConf, user: TestConstants.TEST_USER, ); @@ -1123,14 +1191,22 @@ void main() { ProductField.COUNTRIES_TAGS_IN_LANGUAGES, ]; - ProductQueryConfiguration englishConf = ProductQueryConfiguration(barcode, - language: OpenFoodFactsLanguage.ENGLISH, fields: fields); - ProductQueryConfiguration russianConf = ProductQueryConfiguration(barcode, - language: OpenFoodFactsLanguage.RUSSIAN, fields: fields); + ProductQueryConfiguration englishConf = ProductQueryConfiguration( + barcode, + language: OpenFoodFactsLanguage.ENGLISH, + fields: fields, + version: ProductQueryVersion.v3, + ); + ProductQueryConfiguration russianConf = ProductQueryConfiguration( + barcode, + language: OpenFoodFactsLanguage.RUSSIAN, + fields: fields, + version: ProductQueryVersion.v3, + ); // English! - ProductResult englishResult = await OpenFoodAPIClient.getProduct( + ProductResultV3 englishResult = await OpenFoodAPIClient.getProductV3( englishConf, user: TestConstants.TEST_USER, ); @@ -1167,7 +1243,7 @@ void main() { // Russian! - ProductResult russianResult = await OpenFoodAPIClient.getProduct( + ProductResultV3 russianResult = await OpenFoodAPIClient.getProductV3( russianConf, user: TestConstants.TEST_USER, ); @@ -1241,15 +1317,18 @@ void main() { ProductField.COUNTRIES_TAGS_IN_LANGUAGES, ]; - ProductQueryConfiguration conf = ProductQueryConfiguration(barcode, - languages: [ - OpenFoodFactsLanguage.ENGLISH, - OpenFoodFactsLanguage.RUSSIAN, - OpenFoodFactsLanguage.GERMAN - ], - fields: fields); + ProductQueryConfiguration conf = ProductQueryConfiguration( + barcode, + languages: [ + OpenFoodFactsLanguage.ENGLISH, + OpenFoodFactsLanguage.RUSSIAN, + OpenFoodFactsLanguage.GERMAN + ], + fields: fields, + version: ProductQueryVersion.v3, + ); - ProductResult result = await OpenFoodAPIClient.getProduct( + ProductResultV3 result = await OpenFoodAPIClient.getProductV3( conf, user: TestConstants.TEST_USER, ); @@ -1329,14 +1408,17 @@ void main() { ]; // English first - ProductQueryConfiguration conf = ProductQueryConfiguration(barcode, - languages: [ - OpenFoodFactsLanguage.ENGLISH, - OpenFoodFactsLanguage.RUSSIAN, - OpenFoodFactsLanguage.GERMAN, - ], - fields: fields); - ProductResult result = await OpenFoodAPIClient.getProduct( + ProductQueryConfiguration conf = ProductQueryConfiguration( + barcode, + languages: [ + OpenFoodFactsLanguage.ENGLISH, + OpenFoodFactsLanguage.RUSSIAN, + OpenFoodFactsLanguage.GERMAN, + ], + fields: fields, + version: ProductQueryVersion.v3, + ); + ProductResultV3 result = await OpenFoodAPIClient.getProductV3( conf, user: TestConstants.TEST_USER, ); @@ -1346,14 +1428,17 @@ void main() { expect(product.ingredientsText, equals('Flour, water')); // German first - conf = ProductQueryConfiguration(barcode, - languages: [ - OpenFoodFactsLanguage.GERMAN, - OpenFoodFactsLanguage.RUSSIAN, - OpenFoodFactsLanguage.ENGLISH, - ], - fields: fields); - result = await OpenFoodAPIClient.getProduct( + conf = ProductQueryConfiguration( + barcode, + languages: [ + OpenFoodFactsLanguage.GERMAN, + OpenFoodFactsLanguage.RUSSIAN, + OpenFoodFactsLanguage.ENGLISH, + ], + fields: fields, + version: ProductQueryVersion.v3, + ); + result = await OpenFoodAPIClient.getProductV3( conf, user: TestConstants.TEST_USER, ); @@ -1363,14 +1448,17 @@ void main() { expect(product.ingredientsText, equals('Mehl, wasser')); // Russian first - conf = ProductQueryConfiguration(barcode, - languages: [ - OpenFoodFactsLanguage.RUSSIAN, - OpenFoodFactsLanguage.GERMAN, - OpenFoodFactsLanguage.ENGLISH, - ], - fields: fields); - result = await OpenFoodAPIClient.getProduct( + conf = ProductQueryConfiguration( + barcode, + languages: [ + OpenFoodFactsLanguage.RUSSIAN, + OpenFoodFactsLanguage.GERMAN, + OpenFoodFactsLanguage.ENGLISH, + ], + fields: fields, + version: ProductQueryVersion.v3, + ); + result = await OpenFoodAPIClient.getProductV3( conf, user: TestConstants.TEST_USER, ); @@ -1409,9 +1497,12 @@ void main() { ProductField.NAME_ALL_LANGUAGES, ProductField.INGREDIENTS_TEXT_ALL_LANGUAGES, ]; - ProductQueryConfiguration conf = - ProductQueryConfiguration(barcode, fields: fields); - ProductResult result = await OpenFoodAPIClient.getProduct( + ProductQueryConfiguration conf = ProductQueryConfiguration( + barcode, + fields: fields, + version: ProductQueryVersion.v3, + ); + ProductResultV3 result = await OpenFoodAPIClient.getProductV3( conf, user: TestConstants.TEST_USER, ); @@ -1465,13 +1556,16 @@ void main() { ProductField.INGREDIENTS_TEXT_IN_LANGUAGES, ]; // For 'in-langs' fields specify not all of the available languages - ProductQueryConfiguration conf = ProductQueryConfiguration(barcode, - languages: [ - OpenFoodFactsLanguage.RUSSIAN, - OpenFoodFactsLanguage.ENGLISH, - ], - fields: fields); - ProductResult result = await OpenFoodAPIClient.getProduct( + ProductQueryConfiguration conf = ProductQueryConfiguration( + barcode, + languages: [ + OpenFoodFactsLanguage.RUSSIAN, + OpenFoodFactsLanguage.ENGLISH, + ], + fields: fields, + version: ProductQueryVersion.v3, + ); + ProductResultV3 result = await OpenFoodAPIClient.getProductV3( conf, user: TestConstants.TEST_USER, ); @@ -1507,10 +1601,12 @@ void main() { ); ProductQueryConfiguration configurations = ProductQueryConfiguration( - barcode, - language: OpenFoodFactsLanguage.GERMAN, - fields: [ProductField.ALL]); - ProductResult result = await OpenFoodAPIClient.getProduct( + barcode, + language: OpenFoodFactsLanguage.GERMAN, + fields: [ProductField.ALL], + version: ProductQueryVersion.v3, + ); + ProductResultV3 result = await OpenFoodAPIClient.getProductV3( configurations, user: TestConstants.TEST_USER, ); @@ -1532,11 +1628,13 @@ void main() { 'nutriscore', 'root', }; - final ProductResult productResult = await OpenFoodAPIClient.getProduct( + final ProductResultV3 productResult = + await OpenFoodAPIClient.getProductV3( ProductQueryConfiguration( BARCODE_DANISH_BUTTER_COOKIES, language: OpenFoodFactsLanguage.FRENCH, fields: [ProductField.KNOWLEDGE_PANELS], + version: ProductQueryVersion.v3, ), queryType: QueryType.PROD, user: TestConstants.PROD_USER, @@ -1554,92 +1652,6 @@ void main() { Duration(seconds: 300), )); - group('$OpenFoodAPIClient test ingredients', () { - const String barcode = BARCODE_DANISH_BUTTER_COOKIES; - // Ingredients for _BARCODE_DANISH_BUTTER_COOKIES - const List expectedIngredientLabels = [ - 'Buttergebäck', - 'Zucker', - 'Speisesalz', - 'Backtriebmittel', - 'Ammouniumhydrogencarbonat', - 'Invertzuckersirup', - 'natürliches Aroma', - 'Schokolade Mürbegebäck', - 'Pflanzenfett', - 'Palm', - 'Schokoladenstückchen', - 'Kakaomasse', - 'Kakaobutter', - 'Emulgator', - 'Lecithin', - 'fettarmes Kakaopulver', - '_Weizenmehl_', - '_Butter_', - ]; - - /// Recursively adds [ingredient] labels to [labels]. - /// - /// Works with flat and tree hierarchies. - void addToIngredientLabels( - final List ingredients, - final Set labels, - ) { - for (final Ingredient ingredient in ingredients) { - labels.add(ingredient.text!); - if (ingredient.ingredients != null) { - addToIngredientLabels(ingredient.ingredients!, labels); - } - } - } - - test('get ingredients api.v0', () async { - final ProductQueryConfiguration configurations = - ProductQueryConfiguration( - barcode, - language: OpenFoodFactsLanguage.GERMAN, - fields: [ProductField.INGREDIENTS], - version: ProductQueryVersion.v0, - ); - final ProductResult result = await OpenFoodAPIClient.getProduct( - configurations, - user: TestConstants.TEST_USER, - ); - - expect(result.status, 1); - expect(result.product, isNotNull); - expect(result.product!.ingredients, isNotNull); - // in V0, everything is at the same level - expect(result.product!.ingredients!.length, 24); - final Set ingredientLabels = {}; - addToIngredientLabels(result.product!.ingredients!, ingredientLabels); - expect(ingredientLabels, containsAll(expectedIngredientLabels)); - }); - - test('get ingredients api.v2', () async { - final ProductQueryConfiguration configurations = - ProductQueryConfiguration( - barcode, - language: OpenFoodFactsLanguage.GERMAN, - fields: [ProductField.INGREDIENTS], - version: ProductQueryVersion.v2, - ); - final ProductResult result = await OpenFoodAPIClient.getProduct( - configurations, - user: TestConstants.TEST_USER, - ); - - expect(result.status, 1); - expect(result.product, isNotNull); - expect(result.product!.ingredients, isNotNull); - // in V2, same ingredients but in a tree. - expect(result.product!.ingredients!.length, 9); - final Set ingredientLabels = {}; - addToIngredientLabels(result.product!.ingredients!, ingredientLabels); - expect(ingredientLabels, containsAll(expectedIngredientLabels)); - }); - }); - test('get invalid barcodes', () async { final String url = InvalidBarcodes.getUrl(); final http.Response response = await http.get(Uri.parse(url)); @@ -1664,11 +1676,12 @@ void main() { OpenFoodFactsLanguage.GERMAN, OpenFoodFactsLanguage.FRENCH, ]; - final ProductResult productResult = await OpenFoodAPIClient.getProduct( + final ProductResultV3 productResult = await OpenFoodAPIClient.getProductV3( ProductQueryConfiguration( BARCODE_DANISH_BUTTER_COOKIES, languages: languages, fields: [ProductField.IMAGES_FRESHNESS_IN_LANGUAGES], + version: ProductQueryVersion.v3, ), ); final Product product = productResult.product!; @@ -1807,14 +1820,15 @@ void main() { ProductField.PACKAGING_TAGS, ProductField.QUANTITY, ], + version: ProductQueryVersion.v3, ); - ProductResult result = await OpenFoodAPIClient.getProduct( + final ProductResultV3 result = await OpenFoodAPIClient.getProductV3( configurations, user: TestConstants.TEST_USER, ); - expect(result.status, 1); + expect(result.status, ProductResultV3.statusSuccess); expect(result.product?.barcode, null); expect(result.product?.genericName, 'Softdrink'); expect(result.product?.labels, 'MyTestLabel'); @@ -1829,29 +1843,31 @@ void main() { test('get new product fields', () async { late ProductQueryConfiguration configuration; - late ProductResult result; + late ProductResultV3 result; configuration = ProductQueryConfiguration( BARCODE_DANISH_BUTTER_COOKIES, fields: [ProductField.COMPARED_TO_CATEGORY], + version: ProductQueryVersion.v3, ); - result = await OpenFoodAPIClient.getProduct( + result = await OpenFoodAPIClient.getProductV3( configuration, queryType: QueryType.PROD, ); - expect(result.status, 1); + expect(result.status, ProductResultV3.statusSuccess); expect(result.product, isNotNull); expect(result.product!.comparedToCategory, isNotNull); configuration = ProductQueryConfiguration( '7300400481588', fields: [ProductField.WEBSITE], + version: ProductQueryVersion.v3, ); - result = await OpenFoodAPIClient.getProduct( + result = await OpenFoodAPIClient.getProductV3( configuration, queryType: QueryType.PROD, ); - expect(result.status, 1); + expect(result.status, ProductResultV3.statusSuccess); expect(result.product, isNotNull); expect(result.product!.website, isNotNull); expect(result.product!.website, isNotEmpty); @@ -1884,9 +1900,10 @@ void main() { ProductField.NO_NUTRITION_DATA, ProductField.NUTRIMENTS, ], + version: ProductQueryVersion.v3, ); - final ProductResult result = await OpenFoodAPIClient.getProduct( + final ProductResultV3 result = await OpenFoodAPIClient.getProductV3( configurations, user: TestConstants.TEST_USER, ); @@ -1905,9 +1922,10 @@ void main() { ProductField.NO_NUTRITION_DATA, ProductField.NUTRIMENTS, ], + version: ProductQueryVersion.v3, ); - final ProductResult result = await OpenFoodAPIClient.getProduct( + final ProductResultV3 result = await OpenFoodAPIClient.getProductV3( configurations, user: TestConstants.TEST_USER, ); diff --git a/test/api_matchedProductV1_test.dart b/test/api_matchedProductV1_test.dart index 5bce140b38..e9722a4cdb 100644 --- a/test/api_matchedProductV1_test.dart +++ b/test/api_matchedProductV1_test.dart @@ -1,5 +1,6 @@ import 'package:http/http.dart' as http; import 'package:openfoodfacts/model/Attribute.dart'; +import 'package:openfoodfacts/model/ProductResultV3.dart'; import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:openfoodfacts/personalized_search/available_attribute_groups.dart'; import 'package:openfoodfacts/personalized_search/available_preference_importances.dart'; @@ -61,12 +62,13 @@ void main() { barcode, language: language, fields: [ProductField.NAME, ProductField.ATTRIBUTE_GROUPS], + version: ProductQueryVersion.v3, ); - final ProductResult result = await OpenFoodAPIClient.getProduct( + final ProductResultV3 result = await OpenFoodAPIClient.getProductV3( configurations, user: TestConstants.TEST_USER, ); - expect(result.status, 1); + expect(result.status, ProductResultV3.statusSuccess); expect(result.barcode, barcode); final String attributeId1 = Attribute.ATTRIBUTE_NUTRISCORE; diff --git a/test/api_ocrIngredients_test.dart b/test/api_ocrIngredients_test.dart index 19410c5f0b..246c142e3d 100644 --- a/test/api_ocrIngredients_test.dart +++ b/test/api_ocrIngredients_test.dart @@ -1,4 +1,5 @@ import 'package:openfoodfacts/model/OcrIngredientsResult.dart'; +import 'package:openfoodfacts/model/ProductResultV3.dart'; import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:openfoodfacts/utils/OcrField.dart'; import 'package:openfoodfacts/utils/OpenFoodAPIConfiguration.dart'; @@ -116,12 +117,12 @@ void main() { //Get The saved product's ingredients from the server ProductQueryConfiguration configurations = ProductQueryConfiguration( - barcode, - language: OpenFoodFactsLanguage.FRENCH, - fields: [ - ProductField.INGREDIENTS_TEXT, - ]); - ProductResult result = await OpenFoodAPIClient.getProduct( + barcode, + language: OpenFoodFactsLanguage.FRENCH, + fields: [ProductField.INGREDIENTS_TEXT], + version: ProductQueryVersion.v3, + ); + final ProductResultV3 result = await OpenFoodAPIClient.getProductV3( configurations, user: TestConstants.PROD_USER, ); diff --git a/test/api_saveProduct_test.dart b/test/api_saveProduct_test.dart index f15a41f6d9..897e1f9241 100644 --- a/test/api_saveProduct_test.dart +++ b/test/api_saveProduct_test.dart @@ -3,6 +3,7 @@ import 'dart:math'; import 'package:openfoodfacts/model/Nutrient.dart'; import 'package:openfoodfacts/model/Nutriments.dart'; import 'package:openfoodfacts/model/PerSize.dart'; +import 'package:openfoodfacts/model/ProductResultV3.dart'; import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:openfoodfacts/utils/OpenFoodAPIConfiguration.dart'; import 'package:openfoodfacts/utils/QueryType.dart'; @@ -19,19 +20,19 @@ void main() { String servingSize_1 = '100g'; double servingQuantity_1 = 100; - void testProductResult1(ProductResult result) { - expect(result.status, 1); + void testProductResult1(ProductResultV3 result) { + expect(result.status, ProductResultV3.statusSuccess); expect(result.barcode, barcode_1); - expect(result.product != null, true); + expect(result.product, isNotNull); expect(result.product!.barcode, barcode_1); - expect(result.product!.quantity != null, true); + expect(result.product!.quantity, isNotNull); expect(result.product!.quantity, quantity_1); - expect(result.product!.servingQuantity != null, true); + expect(result.product!.servingQuantity, isNotNull); expect(result.product!.servingQuantity, servingQuantity_1); - expect(result.product!.servingSize != null, true); + expect(result.product!.servingSize, isNotNull); expect(result.product!.servingSize, servingSize_1); } @@ -59,10 +60,12 @@ void main() { expect(status.statusVerbose, 'fields saved'); ProductQueryConfiguration configurations = ProductQueryConfiguration( - barcode_1, - language: OpenFoodFactsLanguage.ENGLISH, - fields: [ProductField.ALL]); - ProductResult result = await OpenFoodAPIClient.getProduct( + barcode_1, + language: OpenFoodFactsLanguage.ENGLISH, + fields: [ProductField.ALL], + version: ProductQueryVersion.v3, + ); + ProductResultV3 result = await OpenFoodAPIClient.getProductV3( configurations, user: TestConstants.TEST_USER, ); @@ -79,7 +82,7 @@ void main() { expect(status2.status, 1); expect(status2.statusVerbose, 'fields saved'); - ProductResult result2 = await OpenFoodAPIClient.getProduct( + ProductResultV3 result2 = await OpenFoodAPIClient.getProductV3( configurations, user: TestConstants.TEST_USER, ); @@ -140,14 +143,16 @@ void main() { // get french fields for product final ProductQueryConfiguration frenchConfig = ProductQueryConfiguration( - barcode, - language: OpenFoodFactsLanguage.FRENCH, - fields: [ - ProductField.NAME, - ProductField.BRANDS, - ProductField.QUANTITY - ]); - final frenchResult = await OpenFoodAPIClient.getProduct( + barcode, + language: OpenFoodFactsLanguage.FRENCH, + fields: [ + ProductField.NAME, + ProductField.BRANDS, + ProductField.QUANTITY, + ], + version: ProductQueryVersion.v3, + ); + final frenchResult = await OpenFoodAPIClient.getProductV3( frenchConfig, ); expect(frenchResult.product, isNotNull); @@ -155,14 +160,12 @@ void main() { // get german fields for product final ProductQueryConfiguration germanConfig = ProductQueryConfiguration( - barcode, - language: OpenFoodFactsLanguage.GERMAN, - fields: [ - ProductField.NAME, - ProductField.BRANDS, - ProductField.QUANTITY - ]); - final germanResult = await OpenFoodAPIClient.getProduct( + barcode, + language: OpenFoodFactsLanguage.GERMAN, + fields: [ProductField.NAME, ProductField.BRANDS, ProductField.QUANTITY], + version: ProductQueryVersion.v3, + ); + final germanResult = await OpenFoodAPIClient.getProductV3( germanConfig, ); @@ -171,15 +174,16 @@ void main() { // get preferably French, then German fields for product final ProductQueryConfiguration frenchGermanConfig = - ProductQueryConfiguration(barcode, languages: [ - OpenFoodFactsLanguage.FRENCH, - OpenFoodFactsLanguage.GERMAN, - ], fields: [ - ProductField.NAME, - ProductField.BRANDS, - ProductField.QUANTITY - ]); - final frenchGermanResult = await OpenFoodAPIClient.getProduct( + ProductQueryConfiguration( + barcode, + languages: [ + OpenFoodFactsLanguage.FRENCH, + OpenFoodFactsLanguage.GERMAN, + ], + fields: [ProductField.NAME, ProductField.BRANDS, ProductField.QUANTITY], + version: ProductQueryVersion.v3, + ); + final frenchGermanResult = await OpenFoodAPIClient.getProductV3( frenchGermanConfig, ); @@ -290,9 +294,11 @@ Like that: expect(status.status, 1); expect(status.statusVerbose, 'fields saved'); - ProductQueryConfiguration configurations = - ProductQueryConfiguration('7340011364184'); - ProductResult result = await OpenFoodAPIClient.getProduct( + ProductQueryConfiguration configurations = ProductQueryConfiguration( + '7340011364184', + version: ProductQueryVersion.v3, + ); + ProductResultV3 result = await OpenFoodAPIClient.getProductV3( configurations, user: TestConstants.TEST_USER, ); @@ -346,13 +352,16 @@ Like that: expect(status.status, 1); expect(status.statusVerbose, 'fields saved'); - final ProductResult result = await OpenFoodAPIClient.getProductRaw( - BARCODE, - OpenFoodFactsLanguage.ENGLISH, + final ProductResultV3 result = await OpenFoodAPIClient.getProductV3( + ProductQueryConfiguration( + BARCODE, + language: OpenFoodFactsLanguage.ENGLISH, + version: ProductQueryVersion.v3, + ), user: USER, ); - expect(result.status, 1); + expect(result.status, ProductResultV3.statusSuccess); expect(result.barcode, BARCODE); final Product? searchedProduct = result.product; expect(searchedProduct != null, true); @@ -411,14 +420,15 @@ Like that: barcode, language: OpenFoodFactsLanguage.FRENCH, fields: [ProductField.ALL], + version: ProductQueryVersion.v3, ); // Step 1: get the product - ProductResult result = await OpenFoodAPIClient.getProduct( + ProductResultV3 result = await OpenFoodAPIClient.getProductV3( configurations, user: TestConstants.TEST_USER, ); - expect(result.status, 1); + expect(result.status, ProductResultV3.statusSuccess); expect(result.product, isNotNull); expect(result.product!.nutriments, isNotNull); final Nutriments nutriments = result.product!.nutriments!; @@ -441,11 +451,11 @@ Like that: expect(status.error, null); // Step 3: check if the value was correctly saved - result = await OpenFoodAPIClient.getProduct( + result = await OpenFoodAPIClient.getProductV3( configurations, user: TestConstants.TEST_USER, ); - expect(result.status, 1); + expect(result.status, ProductResultV3.statusSuccess); expect(result.product, isNotNull); expect(result.product!.nutriments, isNotNull); final double? latestValue = diff --git a/test/json_product_generation_test.dart b/test/json_product_generation_test.dart index 0dc9065a94..1a1294bcda 100644 --- a/test/json_product_generation_test.dart +++ b/test/json_product_generation_test.dart @@ -5,6 +5,7 @@ import 'package:openfoodfacts/model/EcoscoreData.dart'; import 'package:openfoodfacts/model/IngredientsAnalysisTags.dart'; import 'package:openfoodfacts/model/OriginsOfIngredients.dart'; import 'package:openfoodfacts/model/Packaging.dart'; +import 'package:openfoodfacts/model/ProductResultV3.dart'; import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:test/test.dart'; @@ -14,12 +15,16 @@ void main() { test('Generate JSON - database example', () async { String barcode = '0030000010204'; ProductQueryConfiguration configurations = ProductQueryConfiguration( - barcode, - language: OpenFoodFactsLanguage.ENGLISH, - fields: [ProductField.ALL]); - ProductResult result = await OpenFoodAPIClient.getProduct(configurations, - user: TestConstants.TEST_USER); - expect(result.status, 1); + barcode, + language: OpenFoodFactsLanguage.ENGLISH, + fields: [ProductField.ALL], + version: ProductQueryVersion.v3, + ); + ProductResultV3 result = await OpenFoodAPIClient.getProductV3( + configurations, + user: TestConstants.TEST_USER, + ); + expect(result.status, ProductResultV3.statusSuccess); Product product = result.product!; Map productMap = product.toJson(); jsonEncode(productMap); @@ -49,17 +54,17 @@ void main() { ]; IngredientsAnalysisTags ingredientsAnalysisTags = IngredientsAnalysisTags(data); - assert(ingredientsAnalysisTags.vegetarianStatus == - VegetarianStatus.VEGETARIAN); - assert(ingredientsAnalysisTags.veganStatus == VeganStatus.NON_VEGAN); - assert(ingredientsAnalysisTags.palmOilFreeStatus == + expect( + ingredientsAnalysisTags.vegetarianStatus, VegetarianStatus.VEGETARIAN); + expect(ingredientsAnalysisTags.veganStatus, VeganStatus.NON_VEGAN); + expect(ingredientsAnalysisTags.palmOilFreeStatus, PalmOilFreeStatus.PALM_OIL_CONTENT_UNKNOWN); List jsonStrings = IngredientsAnalysisTags.toJson(ingredientsAnalysisTags); - assert(jsonStrings[0] == 'en:non-vegan'); - assert(jsonStrings[1] == 'en:vegetarian'); - assert(jsonStrings[2] == 'en:palm-oil-content-unknown'); + expect(jsonStrings[0], 'en:non-vegan'); + expect(jsonStrings[1], 'en:vegetarian'); + expect(jsonStrings[2], 'en:palm-oil-content-unknown'); }); } diff --git a/test/product_from_json_test.dart b/test/product_from_json_test.dart index 24fe683d3c..25b4dce52f 100644 --- a/test/product_from_json_test.dart +++ b/test/product_from_json_test.dart @@ -1,5 +1,6 @@ import 'dart:convert'; +import 'package:openfoodfacts/model/ProductResultV3.dart'; import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:test/test.dart'; @@ -9,18 +10,17 @@ void main() { // Verify that we can save the product as a JSON string and then load it back test('Load product from JSON', () async { String barcode = '0030000010204'; - ProductQueryConfiguration configurations = - ProductQueryConfiguration(barcode, languages: [ - OpenFoodFactsLanguage.ENGLISH, - OpenFoodFactsLanguage.FRENCH - ], fields: [ - ProductField.ALL, - ]); - ProductResult result = await OpenFoodAPIClient.getProduct( + ProductQueryConfiguration configurations = ProductQueryConfiguration( + barcode, + languages: [OpenFoodFactsLanguage.ENGLISH, OpenFoodFactsLanguage.FRENCH], + fields: [ProductField.ALL], + version: ProductQueryVersion.v3, + ); + ProductResultV3 result = await OpenFoodAPIClient.getProductV3( configurations, user: TestConstants.TEST_USER, ); - expect(result.status, 1); + expect(result.status, ProductResultV3.statusSuccess); Product product = result.product!; Map productMap = product.toJson(); String encodedJson = jsonEncode(productMap);