Skip to content

Commit

Permalink
feat: 802 - new "get product" method specific to OBF OPF OPFF (#806)
Browse files Browse the repository at this point in the history
New files:
* `api_not_food_get_product_test.dart`: tests around OBF OPF OPFF and `getOldProduct`
* `old_product_result.dart`: Product Result (old style).
* `old_product_result.g.dart`: generated

Impacted files:
* `open_food_api_client.dart`: new `getOldProduct` method, dedicated to OBF OPF OPFF, and supposed to disappear when they support API V3.
* `openfoodfacts.dart`: exported new class.
  • Loading branch information
monsieurtanuki authored Sep 20, 2023
1 parent 7753cb0 commit e824de2
Show file tree
Hide file tree
Showing 5 changed files with 166 additions and 0 deletions.
1 change: 1 addition & 0 deletions lib/openfoodfacts.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export 'src/model/nutriments.dart';
// export 'src/model/product_list.dart'; // not needed
export 'src/model/ocr_ingredients_result.dart';
export 'src/model/ocr_packaging_result.dart';
export 'src/model/old_product_result.dart';
export 'src/model/ordered_nutrient.dart';
export 'src/model/ordered_nutrients.dart';
export 'src/model/origins_of_ingredients.dart';
Expand Down
26 changes: 26 additions & 0 deletions lib/src/model/old_product_result.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import 'package:json_annotation/json_annotation.dart';
import '../interface/json_object.dart';
import 'product.dart';

part 'old_product_result.g.dart';

/// Product Result (old style).
// TODO(monsieurtanuki): get rid of it when OBF OPF OPFF support api v3
@JsonSerializable()
class OldProductResult extends JsonObject {
final int? status;
@JsonKey(name: 'code')
final String? barcode;
@JsonKey(name: 'status_verbose')
final String? statusVerbose;
final Product? product;

const OldProductResult(
{this.status, this.barcode, this.statusVerbose, this.product});

factory OldProductResult.fromJson(Map<String, dynamic> json) =>
_$OldProductResultFromJson(json);

@override
Map<String, dynamic> toJson() => _$OldProductResultToJson(this);
}
25 changes: 25 additions & 0 deletions lib/src/model/old_product_result.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 28 additions & 0 deletions lib/src/open_food_api_client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import 'interface/json_object.dart';
import 'model/login_status.dart';
import 'model/ocr_ingredients_result.dart';
import 'model/ocr_packaging_result.dart';
import 'model/old_product_result.dart';
import 'model/ordered_nutrients.dart';
import 'model/parameter/barcode_parameter.dart';
import 'model/product.dart';
Expand Down Expand Up @@ -277,6 +278,33 @@ class OpenFoodAPIClient {
return result;
}

/// Returns the product for the given barcode, with an old syntax.
///
/// Temporarily needed for OBF, OPF and OPFF, that do not support api v3.
// TODO(monsieurtanuki): get rid of it when OBF OPF OPFF support api v3
static Future<OldProductResult> getOldProduct(
final ProductQueryConfiguration configuration, {
final User? user,
final UriProductHelper uriHelper = uriHelperFoodProd,
}) async {
if (configuration.matchesV3()) {
Exception("The configuration must not match V3!");
}
final String productString = await getProductString(
configuration,
user: user,
uriHelper: uriHelper,
);
final String jsonStr = _replaceQuotes(productString);
final OldProductResult result =
OldProductResult.fromJson(jsonDecode(jsonStr));
if (result.product != null) {
ProductHelper.removeImages(result.product!, configuration.language);
ProductHelper.createImageUrls(result.product!, uriHelper: uriHelper);
}
return result;
}

/// Returns the ids of all uploaded images for that product.
///
/// To be used in combination with [ImageHelper.getUploadedImageUrl].
Expand Down
86 changes: 86 additions & 0 deletions test/api_not_food_get_product_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import 'package:openfoodfacts/openfoodfacts.dart';
import 'package:test/test.dart';

import 'test_constants.dart';

void main() {
OpenFoodAPIConfiguration.userAgent = TestConstants.TEST_USER_AGENT;
OpenFoodAPIConfiguration.globalUser = TestConstants.PROD_USER;

const UriProductHelper uriHelperBeautyProd = UriProductHelper(
host: 'world.openbeautyfacts.org',
imageUrlBase: 'https://static.openbeautyfacts.org/images/products/',
);
const UriProductHelper uriHelperProductsProd = UriProductHelper(
host: 'world.openproductsfacts.org',
imageUrlBase: 'https://static.openproductsfacts.org/images/products/',
);
const UriProductHelper uriHelperPetFoodProd = UriProductHelper(
host: 'world.openpetfoodfacts.org',
imageUrlBase: 'https://static.openpetfoodfacts.org/images/products/',
);

const String beautyBarcode = '4056489234692';
const String productsBarcode = '7898927451035';
const String petFoodBarcode = '3564700266809';

group('$OpenFoodAPIClient get not food products', () {
Future<Product?> findProduct(
final String barcode,
final UriProductHelper uriHelper,
final bool shouldBeThere,
) async {
final ProductQueryConfiguration configurations =
ProductQueryConfiguration(
barcode,
language: OpenFoodFactsLanguage.ENGLISH,
fields: [ProductField.ALL],
version: ProductQueryVersion(2),
);
final OldProductResult result = await OpenFoodAPIClient.getOldProduct(
configurations,
uriHelper: uriHelper,
);
if (shouldBeThere) {
expect(result.status, 1);
expect(result.barcode, barcode);
expect(result.product, isNotNull);
expect(result.product!.barcode, barcode);
} else {
expect(result.status, 0);
expect(result.barcode, barcode);
expect(result.product, isNull);
}
return result.product;
}

test('get beauty product', () async {
final String barcode = beautyBarcode;
await findProduct(barcode, uriHelperBeautyProd, true);
await findProduct(barcode, uriHelperProductsProd, false);
await findProduct(barcode, uriHelperPetFoodProd, false);
await findProduct(barcode, uriHelperPetFoodProd, false);
await findProduct(barcode, uriHelperFoodProd, false);
});

test('get products product', () async {
final String barcode = productsBarcode;
await findProduct(barcode, uriHelperBeautyProd, false);
await findProduct(barcode, uriHelperProductsProd, true);
await findProduct(barcode, uriHelperPetFoodProd, false);
await findProduct(barcode, uriHelperFoodProd, false);
});

test('get pet food product', () async {
final String barcode = petFoodBarcode;
await findProduct(barcode, uriHelperBeautyProd, false);
await findProduct(barcode, uriHelperProductsProd, false);
await findProduct(barcode, uriHelperPetFoodProd, true);
await findProduct(barcode, uriHelperFoodProd, false);
});
},
timeout: Timeout(
// some tests can be slow here
Duration(seconds: 300),
));
}

0 comments on commit e824de2

Please sign in to comment.