def test_widget_from_type(self): self.assertEqual(widget_from_type("1"), get_dotted_path(forms.widgets.TextInput)) self.assertEqual(widget_from_type(1), get_dotted_path(FloatInput)) self.assertEqual(widget_from_type(True), get_dotted_path(forms.widgets.CheckboxInput)) self.assertEqual(widget_from_type(datetime.datetime.now()), get_dotted_path(forms.widgets.DateTimeInput)) self.assertEqual(widget_from_type(1.11), get_dotted_path(FloatInput))
def test_get_processed_unit_and_value(self): units: UnitManager = UnitManager() with self.subTest("str"): self.assertEqual(units.get_processed_unit_and_value("str"), Value(value="str")) with self.subTest("valid unit"): parsed_value: UnitValue = units.get_processed_unit_and_value("1kg") kg_unit: Unit = Unit.objects.get( name="kilogram", widget=get_dotted_path(FloatInput)) self.assertEqual(parsed_value, UnitValue(value=1, unit=kg_unit)) with self.subTest("undefined unit"): parsed_value: UnitValue = units.get_processed_unit_and_value( "1lkj") self.assertEqual(parsed_value, Value(value="1lkj")) with self.subTest("range value"): parsed_value: RangeUnitValue = units.get_processed_unit_and_value( "200-240v") volt_unit: Unit = Unit.objects.get( name="volt", widget=get_dotted_path(FloatInput)) self.assertEqual( parsed_value, RangeUnitValue(unit=volt_unit, value_low=200, value_high=240)) with self.subTest("bool value"): for value in ["yes", "Y", "true", "True"]: parsed_value: UnitValue = units.get_processed_unit_and_value( value) unit: Unit = Unit.objects.get(name="bool", widget=get_dotted_path( forms.widgets.CheckboxInput)) self.assertEqual(parsed_value, UnitValue(unit=unit, value=True)) with self.subTest("irregular string"): string = "5 year full warranty and 10 year parts upon registration" parsed_value: UnitValue = units.get_processed_unit_and_value( string) unit: Unit = Unit.objects.get(name="year", widget=get_dotted_path(FloatInput)) self.assertEqual(parsed_value, UnitValue(value=5, unit=unit))
def set_up_attributes(): load_size_unit, _ = Unit.objects.get_or_create(name="kilogram", widget=get_dotted_path(FloatInput)) litres_unit, _ = Unit.objects.get_or_create(name="litres", widget=get_dotted_path(FloatInput)) spin_unit, _ = Unit.objects.get_or_create(name="revolutions_per_minute", widget=get_dotted_path(FloatInput)) energy_unit, _ = Unit.objects.get_or_create(name="kwh", widget=get_dotted_path(FloatInput)) currency, _ = Unit.objects.get_or_create(name="€", alternate_names=["euro"], widget=get_dotted_path(FloatInput), repeat=HOURLY) washers = Category.objects.get(name="washing machines") fridges = Category.objects.get(name="fridges") AttributeType.objects.get_or_create(name="brand") load_size, _ = AttributeType.objects.get_or_create(name="load size", category=washers, unit=load_size_unit) capacity, _ = AttributeType.objects.get_or_create(name="capacity", category=fridges, unit=litres_unit) spin, _ = AttributeType.objects.get_or_create(name="spin speed", category=washers, unit=spin_unit) energy, _ = AttributeType.objects.get_or_create(name="energy usage", category=washers, unit=energy_unit) AttributeType.objects.get_or_create(name="price", unit=currency) CategoryAttributeConfig.objects.get_or_create(attribute_type=load_size, category=washers, weight=5, order=1, scoring=SCORING_NUMERICAL_HIGHER) CategoryAttributeConfig.objects.get_or_create(attribute_type=spin, category=washers, weight=4, order=2, scoring=SCORING_NUMERICAL_HIGHER) CategoryAttributeConfig.objects.get_or_create(attribute_type=energy, category=washers, weight=3, order=3, scoring=SCORING_NUMERICAL_LOWER)
def test_website_create_product_attribute(self): website: Website = mommy.make(Website) product: Product = mommy.make(Product) attribute: AttributeType = mommy.make(AttributeType, unit__widget=get_dotted_path( forms.widgets.NumberInput)) product_attribute: WebsiteProductAttribute = website.create_product_attribute( product, attribute, "1") self.assertEqual(product_attribute.website, website) self.assertEqual(product_attribute.attribute_type, attribute) self.assertEqual(product_attribute.data['value'], 1)
def test_custom_get_or_create__product_attribute(self): attribute_type: AttributeType = mommy.make( AttributeType, unit__widget=get_dotted_path(FloatInput)) product: Product = mommy.make(Product) created_attribute: ProductAttribute = ProductAttribute.objects.custom_get_or_create( product, attribute_type, "299") self.assertEqual(created_attribute.attribute_type, attribute_type) self.assertEqual(created_attribute.product, product) self.assertEqual(created_attribute.data['value'], 299.0) retrieved_attribute: ProductAttribute = ProductAttribute.objects.custom_get_or_create( product, attribute_type, "299") self.assertEqual(retrieved_attribute, created_attribute)
def test_unit(self): with self.subTest("text"): unit: Unit = mommy.make(Unit, widget=get_dotted_path( forms.widgets.TextInput)) self.assertEqual(unit.serializer, serializers[forms.CharField]) self.assertEqual(unit.field_class, forms.CharField) self.assertEqual(unit.widget_class, forms.widgets.TextInput) with self.subTest("int"): unit: Unit = mommy.make(Unit, widget=get_dotted_path( forms.widgets.NumberInput)) self.assertEqual(unit.serializer, serializers[forms.IntegerField]) self.assertEqual(unit.field_class, forms.IntegerField) self.assertEqual(unit.widget_class, forms.widgets.NumberInput) with self.subTest("float"): unit: Unit = mommy.make(Unit, widget=get_dotted_path(FloatInput)) self.assertEqual(unit.serializer, serializers[forms.FloatField]) self.assertEqual(unit.field_class, forms.FloatField) self.assertEqual(unit.widget_class, FloatInput) with self.subTest("bool"): unit: Unit = mommy.make(Unit, widget=get_dotted_path( forms.widgets.CheckboxInput)) self.assertEqual(unit.serializer, serializers[forms.BooleanField]) self.assertEqual(unit.field_class, forms.BooleanField) self.assertEqual(unit.widget_class, forms.widgets.CheckboxInput) with self.subTest("datetime"): unit: Unit = mommy.make(Unit, widget=get_dotted_path( forms.widgets.DateTimeInput)) self.assertEqual(unit.serializer, serializers[forms.DateTimeField]) self.assertEqual(unit.field_class, forms.DateTimeField) self.assertEqual(unit.widget_class, forms.widgets.DateTimeInput)
def setUpClass(cls) -> None: super().setUpClass() cls.website: Website = mommy.make(Website, name="test_website", currency__name="€") cls.category: Category = mommy.make(Category, name="washing machines") cls.product: Product = mommy.make(Product, model="model_number") cls.gram: Unit = mommy.make(Unit, name="gram", widget=get_dotted_path(FloatInput)) cls.attribute: AttributeType = mommy.make(AttributeType, name="test_attr", unit=cls.gram) cls.product_attribute: ProductAttribute = mommy.make( ProductAttribute, product=cls.product, attribute_type=cls.attribute)
def test_get_or_create_unit(self): units: UnitManager = UnitManager() self.assertEqual(units.get_or_create_unit("1"), Value(value=1)) with self.subTest("unit created"): self.assertFalse(Unit.objects.exists()) parsed_value: UnitValue = units.get_or_create_unit("1kg") kg_unit: Unit = Unit.objects.get( name="kilogram", widget=get_dotted_path(FloatInput)) self.assertEqual(parsed_value.unit, kg_unit) self.assertEqual(parsed_value.value, 1) with self.subTest("existing unit - with conversion"): parsed_value: UnitValue = units.get_or_create_unit("2000g", unit=kg_unit) self.assertEqual(parsed_value.unit, kg_unit) self.assertEqual(parsed_value.value, 2)
def test_product_attributes_serialize(self): attribute_type: AttributeType = mommy.make( AttributeType, name="weight", unit=mommy.make(Unit, name="kg", widget=get_dotted_path(FloatInput))) attr_1 = mommy.make(ProductAttribute, attribute_type=attribute_type, data={'value': '100'}) attr_2 = mommy.make(ProductAttribute, attribute_type=attribute_type, data={'value': '200.20'}) attrs = ProductAttribute.objects.serialize() self.assertEqual(attrs.get(pk=attr_1.pk).data['value'], 100.0) self.assertEqual(attrs.get(pk=attr_2.pk).data['value'], 200.20) mommy.make(ProductAttribute, attribute_type=attribute_type, data={'value': 'test'}) with self.assertRaises(UndefinedUnitError) as context: ProductAttribute.objects.serialize() self.assertEqual(str(context.exception), "'test' is not defined in the unit registry")
(forms.widgets.CheckboxInput, forms.BooleanField), (forms.widgets.DateTimeInput, forms.DateTimeField), ]) # Set of supported field type classes FIELD_TYPES = set(WIDGETS.values()) WIDGET_NAMES = { forms.widgets.TextInput: _("Text"), forms.widgets.NumberInput: _("Number (integer)"), forms.widgets.CheckboxInput: _("Checkbox"), forms.widgets.DateTimeInput: _("Date & Time"), FloatInput: _("Number (decimal)"), } WIDGET_CHOICES = [(get_dotted_path(cls), WIDGET_NAMES.get(cls, cls.__name__)) for cls in WIDGETS.keys()] OPERATOR_MEAN = 'mean' OPERATOR_MAX = 'max' OPERATOR_MIN = 'min' OPERATOR_SUM = 'sum' OPERATORS = (OPERATOR_MEAN, OPERATOR_MAX, OPERATOR_MIN, OPERATOR_SUM) EPREL_API_ROOT_URL = 'https://eprel.ec.europa.eu/api/products/' WEBSITE_TYPE_RETAILER = 'retailer' WEBSITE_TYPE_SUPPLIER = 'supplier' WEBSITE_TYPES = ( (WEBSITE_TYPE_RETAILER, _('Retailer')),
def test_attribute_type_convert_unit(self): kilogram: Unit = mommy.make(Unit, name="kilogram", widget=get_dotted_path(FloatInput)) attribute_type: AttributeType = mommy.make(AttributeType, name="weight", unit=kilogram) with self.subTest("same unit type"): self.assertEqual( attribute_type.convert_unit(kilogram).unit, kilogram) gram: Unit = mommy.make(Unit, name="gram", widget=get_dotted_path(FloatInput)) mommy.make(ProductAttribute, attribute_type=attribute_type, data={'value': 7}) with self.subTest("convert to grams"): self.assertEqual(attribute_type.convert_unit(gram).unit, gram) self.assertTrue( ProductAttribute.objects.filter(attribute_type=attribute_type, data__value=7000)) with self.subTest("unit is None"): attribute_type_1: AttributeType = mommy.make(AttributeType, unit=None) attribute_type_2: AttributeType = mommy.make(AttributeType, unit=None) self.assertIsNone( attribute_type_1.convert_unit(attribute_type_2.unit).unit) with self.subTest("mismatch units"): litre: Unit = mommy.make(Unit, name="litre", widget=get_dotted_path(FloatInput)) mommy.make(ProductAttribute, attribute_type=attribute_type, data={'value': 7}) with self.assertRaises(Exception) as context: attribute_type.convert_unit(litre) self.assertEqual( str(context.exception), "Cannot convert from 'gram' ([mass]) to 'liter' ([length] ** 3)" ) self.assertTrue( ProductAttribute.objects.filter(attribute_type=attribute_type, attribute_type__unit=gram, data__value=7)) with self.subTest("text conversion attempt"): mg: Unit = mommy.make(Unit, name="mg", widget=get_dotted_path(FloatInput)) mommy.make(ProductAttribute, attribute_type=attribute_type, data={'value': 'test'}) with self.assertRaises(Exception) as context: attribute_type.convert_unit(mg) self.assertEqual(str(context.exception), "'test' is not defined in the unit registry") self.assertTrue( ProductAttribute.objects.filter(attribute_type=attribute_type, attribute_type__unit=gram, data__value='test')) with self.subTest("adding new unit"): kg: Unit = mommy.make(Unit, name="kg", widget=get_dotted_path(FloatInput)) attribute_type: AttributeType = mommy.make(AttributeType, unit=None) mommy.make(ProductAttribute, attribute_type=attribute_type, data={'value': '700'}) attribute_type.convert_unit(kg) self.assertEqual( AttributeType.objects.get(pk=attribute_type.pk).unit, kg) self.assertTrue( ProductAttribute.objects.filter(attribute_type=attribute_type, data__value=700.0))
def setUpClass(cls) -> None: super().setUpClass() cls.website: Website = mommy.make(Website, name="test_website", currency__name="€", currency__widget=get_dotted_path(FloatInput)) cls.category: Category = mommy.make(Category, name="washing machines") cls.product: Product = mommy.make(Product, model="model_number", category=cls.category) cls.energy_label_pdf_url = "https://whirlpool-cdn.thron.com/static/7UO8OG_NEL859991596350_9DDFJI.pdf"
def set_up_websites(): currency, _ = Unit.objects.get_or_create(name="€", alternate_names=["euro"], widget=get_dotted_path(FloatInput), repeat=HOURLY) harvey_norman, _ = Website.objects.get_or_create(name="harvey_norman", domain="harveynorman.ie", currency=currency) laundry, _ = Category.objects.get_or_create(name="laundry") cooling, _ = Category.objects.get_or_create(name="cooling") washing_machines, _ = Category.objects.get_or_create(name="washing machines", parent=laundry, alternate_names=["washers", "front loaders"]) fridges, _ = Category.objects.get_or_create(name="fridges", parent=cooling) EprelCategory.objects.get_or_create(category=washing_machines, name="washingmachines2019") EprelCategory.objects.get_or_create(category=washing_machines, name="washingmachines") Url.objects.get_or_create(url="https://www.harveynorman.ie/home-appliances/appliances/washing-machines/", url_type=CATEGORY, website=harvey_norman, category=washing_machines) table_selector, _ = Selector.objects.get_or_create(selector_type=TABLE, css_selector="#content_features table.table-product-features tr", website=harvey_norman) Selector.objects.get_or_create(selector_type=TABLE_LABEL_COLUMN, css_selector="th strong::text", website=harvey_norman, parent=table_selector) Selector.objects.get_or_create(selector_type=TABLE_VALUE_COLUMN, css_selector="td::text", website=harvey_norman, parent=table_selector) Selector.objects.get_or_create(selector_type=PRICE, css_selector=".price-num:nth-child(2)::text", website=harvey_norman) Selector.objects.get_or_create(selector_type=MODEL, css_selector=".product-id.meta::text", website=harvey_norman) Selector.objects.get_or_create(selector_type=LINK, css_selector=".product-info a", website=harvey_norman) Selector.objects.get_or_create(selector_type=PAGINATION, css_selector="li a.next", website=harvey_norman) Selector.objects.get_or_create(selector_type=IMAGE, css_selector='.cm-image-previewer.image-magnifier-image::attr(href)', website=harvey_norman)