diff --git a/README.rst b/README.rst index 175e1568a..82e13520c 100644 --- a/README.rst +++ b/README.rst @@ -311,7 +311,7 @@ Scrapers available for: - `https://zeit.de/ (wochenmarkt) `_ - `https://zenbelly.com/ `_ -(*) offline saved files only +(*) offline saved files only. Page requires login Contribute ---------- diff --git a/recipe_scrapers/__init__.py b/recipe_scrapers/__init__.py index e2a42d5ae..dd492c17d 100644 --- a/recipe_scrapers/__init__.py +++ b/recipe_scrapers/__init__.py @@ -216,6 +216,8 @@ from .vegolosi import Vegolosi from .vegrecipesofindia import VegRecipesOfIndia from .watchwhatueat import WatchWhatUEat +from .weightwatchers import WeightWatchers +from .weightwatcherspublic import WeightWatchersPublic from .whatsgabycooking import WhatsGabyCooking from .wholefoods import WholeFoods from .wikicookbook import WikiCookbook @@ -452,6 +454,8 @@ VegRecipesOfIndia.host(): VegRecipesOfIndia, Vegolosi.host(): Vegolosi, WatchWhatUEat.host(): WatchWhatUEat, + WeightWatchers.host(): WeightWatchers, + WeightWatchersPublic.host(): WeightWatchersPublic, WhatsGabyCooking.host(): WhatsGabyCooking, WholeFoods.host(): WholeFoods, WholeFoods.host(domain="co.uk"): WholeFoods, diff --git a/recipe_scrapers/weightwatchers.py b/recipe_scrapers/weightwatchers.py new file mode 100644 index 000000000..5b0c64514 --- /dev/null +++ b/recipe_scrapers/weightwatchers.py @@ -0,0 +1,160 @@ +# mypy: allow-untyped-defs + +import re + +from ._abstract import AbstractScraper +from ._utils import get_minutes, get_yields, normalize_string + + +class WeightWatchers(AbstractScraper): + @classmethod + def host(cls): + return "www.weightwatchers.com" + + def author(self): + return "WeightWatchers" + + def title(self): + return self.soup.find("h1").get_text().strip() + + def category(self): + return "WeightWatchers" + + # cooking times, yield, difficulty are in a common div in public and non-public recipes + # but class of that block and sub elements are different + # so finding the block and extracting a value will be overridden in class for public recipes, + # but picking the data item based on order is don in this base class (total_time(), cook_time() and so on) + def _findDataContainer(self): + return self.soup.find("div", {"class": "styles_container__3N3E8"}) + + def _extractItemField(self, item): + return item.contents[1] + + def total_time(self): + return get_minutes( + self._extractItemField(self._findDataContainer().contents[0]) + ) + + def prep_time(self): + return get_minutes( + self._extractItemField(self._findDataContainer().contents[1]) + ) + + def cook_time(self): + return get_minutes( + self._extractItemField(self._findDataContainer().contents[2]) + ) + + def yields(self): + return get_yields(self._extractItemField(self._findDataContainer().contents[3])) + + def difficulty(self): + return self._extractItemField(self._findDataContainer().contents[4]).get_text() + + # Alternative way to extract data based on description instead of position + # def total_time(self): + # return get_minutes( + # self.__findDataContainer() + # .find("div", string=re.compile(r"minutes Total Time")) + # .previous_sibling + # ) + + def image(self): + backgroundImgStyle = self.soup.find("div", {"class": "styles_image__2dnNm"})[ + "style" + ] + + if backgroundImgStyle: + return ( + re.search(r'url\("(?P\S*)"\);', backgroundImgStyle) + .groupdict() + .get("imgurl") + ) + + return None + + def _findIngridientTags(self): + return self.soup.find( + "h3", {"id": "food-detail-recipe-ingredients-header"} + ).parent.find_all("div", {"class": "styles_name__1OYVU"}) + + def _extractIngridientName(self, ingridient): + return normalize_string( + ingridient.find("div", {"class": "styles_ingredientName__1Vffd"}) + .find("div") + .get_text() + ) + + def _extractPortionParts(self, ingridient): + tags = ingridient.find("div", {"class": "styles_portion__2NQyq"}).find_all( + "span" + ) + try: + return ( + normalize_string(tags[0].get_text()), + normalize_string(tags[1].get_text()), + normalize_string(tags[2].get_text().replace(", ", "")) + if tags[2] + else None, + ) + except IndexError: + return ( + normalize_string(tags[0].get_text()), + normalize_string(tags[1].get_text()), + None, + ) + + def __parseIngridient(self, ingridient): + ingridientName = self._extractIngridientName(ingridient) + amount, unit, comment = self._extractPortionParts(ingridient) + + if comment: + return f"{amount} {unit} {ingridientName}; {comment}" + else: + return f"{amount} {unit} {ingridientName}" + + def ingredients(self): + return [ + self.__parseIngridient(ingridient) + for ingridient in self._findIngridientTags() + ] + + def _getInstructions(self, headertag, headerattribute, headervalue, instructiontag): + instructions = self.soup.find( + headertag, {headerattribute: headervalue} + ).parent.find("ol") + return "\n".join( + [ + normalize_string(instruction.get_text()) + for instruction in instructions.find_all(instructiontag) + ] + ) + + def instructions(self): + return self._getInstructions( + "h3", "id", "food-detail-recipe-instruction-header", "div" + ) + + def description(self): + return self.soup.find("div", {"class": "copy-1"}).get_text().strip() + + def nutrients(self): + result = {} + + result["personal points"] = ( + self.soup.find("div", {"class": "styles_points__2gv9n"}) + .find("div", {"class": "styles_container__2p-YG"}) + .get_text() + ) + + veggiepoints = self.soup.find( + "div", {"class": "styles_vegetableServings__2YSPy"} + ) + if veggiepoints: + result["positive points"] = normalize_string( + veggiepoints.find( + "div", {"class": "styles_container__2p-YG"} + ).next_sibling.get_text() + ) + + return result diff --git a/recipe_scrapers/weightwatcherspublic.py b/recipe_scrapers/weightwatcherspublic.py new file mode 100644 index 000000000..4f40e7e06 --- /dev/null +++ b/recipe_scrapers/weightwatcherspublic.py @@ -0,0 +1,66 @@ +# mypy: allow-untyped-defs + +from ._utils import normalize_string +from .weightwatchers import WeightWatchers + + +# collect the differences between public and non-public weightwatcher recipes in this class +class WeightWatchersPublic(WeightWatchers): + @classmethod + def host(cls): + return "www.weightwatchers.com" + + def _findDataContainer(self): + return self.soup.find("div", {"class": "HorizontalList_list__GESs0"}) + + def _extractItemField(self, item): + return item.find("div", {"data-e2e-name": "attribute_item_value"}) + + def image(self): + return self.soup.find("img", {"class": "FoodMasthead_heroImage__BjVdZ"})["src"] + + def nutrients(self): + return { + "points": self.soup.find("div", {"class": "Coin_text__3UOb0"})["aria-label"] + } + + def description(self): + return normalize_string( + self.soup.find("div", {"data-e2e-name": "food_masthead_detail_description"}) + .find("div", {"class": "ReadMoreLess_collapsed__IAzxP"}) + .get_text() + ) + + def instructions(self): + return self._getInstructions( + "h2", "class", "InstructionsFood_headline__vw7cn", "span" + ) + + def _findIngridientTags(self): + return ( + self.soup.find("div", {"class": "IngredientsCard_card__VSY4x"}) + .find("div", {"data-e2e-name": "vertical_list_items"}) + .find_all("div", recursive=False) + ) + + def _extractIngridientName(self, ingridient): + return normalize_string( + ingridient.find("p", {"data-e2e-name": "ingredient_name"}).get_text() + ) + + def _extractPortionParts(self, ingridient): + tags = ingridient.find( + "p", {"data-e2e-name": "ingredient_description"} + ).find_all("span") + + comment = None + unit = None + if len(tags) > 2: + comment = normalize_string(tags[2].get_text().replace(", ", "", 1)) + unit = normalize_string(tags[1].get_text()) + else: + descriptionParts = normalize_string(tags[1].get_text()).split(", ", 1) + unit = descriptionParts[0] + comment = descriptionParts[1] if len(descriptionParts) > 1 else None + + return (normalize_string(tags[0].get_text()), unit, comment) diff --git a/tests/test_data/weightwatchers.testhtml b/tests/test_data/weightwatchers.testhtml new file mode 100644 index 000000000..1549d1506 --- /dev/null +++ b/tests/test_data/weightwatchers.testhtml @@ -0,0 +1,191 @@ + + +Details | Tagebuch

Würstchengulasch mit Nudeln

earn 12 personal points
You'll earn
+2 Punkte von 2 Portion(en) Gemüse
0:25 minutes Total Time
0:25 minutes Preparation Time
- minutes Cook Time
Serves 2 people
Difficulty Level: Leicht
18 Uhr und alle haben Hunger? Dann koche rasch das Würstchengulasch und alle sind happy.
Portion(en)
Tageszeit
Datum

Zutaten

Geflügelwürstchen
2Stück
8 personal points
Zwiebel/n
1Stück, klein
0 personal points
Champignons, frisch
200g, braun
earn 0 personal points
Nudeln, trocken, jede Sorte
120g, Spiralnudeln
13 personal points
Salz/Jodsalz
1Prise(n)
0 personal points
Pflanzenöl, Rapsöl/Sonnenblumenöl
2TL
3 personal points
Tomaten, passiert
400g
earn 0 personal points
Pfeffer
1Prise(n)
0 personal points
Paprikapulver
12TL
0 personal points

Anleitung

  1. Würstchen in Scheiben schneiden. Zwiebel schälen und würfeln. Champignons trocken abreiben und vierteln. Nudeln nach Packungsanweisung in Salzwasser garen.
  2. Öl in einem Topf erhitzen und Zwiebelwürfel darin andünsten. Würstchenscheiben und Champignonviertel zufügen und ca. 3 Minuten anbraten. Mit Tomaten ablöschen, aufkochen und ca. 5 Minuten köcheln lassen. Würstchengulasch mit Salz, Pfeffer und Paprikapulver würzen. Nudeln abgießen, untermischen und in einer Frischhaltedose transportieren. Würstchengulasch erwärmen und servieren.
+ + + +
+ + + + + + +
\ No newline at end of file diff --git a/tests/test_data/weightwatchers_2.testhtml b/tests/test_data/weightwatchers_2.testhtml new file mode 100644 index 000000000..c95ba0fcb --- /dev/null +++ b/tests/test_data/weightwatchers_2.testhtml @@ -0,0 +1,191 @@ + + +Details | Tagebuch

Hackbraten Stroganoff

10 personal points
1:05 minutes Total Time
0:40 minutes Preparation Time
0:25 minutes Cook Time
Serves 4 people
Difficulty Level: Mittel
Wenn das mal keine mutige Abwandlung des beliebten Klassiker ist. Schmeckt übrigens ganz vorzüglich!
Portion(en)
Tageszeit
Datum

Zutaten

Champignons, frisch
125g
earn 0 personal points
Cornichons
5Stück
1 personal points
Frühlingszwiebeln/Lauchzwiebeln
1Bund
earn 0 personal points
Tatar, roh
600g
13 personal points
Paniermehl/Semmelbrösel
2EL
2 personal points
Eier, Hühnereier
1Stück, Gewichtsklasse M
0 personal points
Senf, klassisch
4TL
0 personal points
Salz/Jodsalz
1Prise(n)
0 personal points
Pfeffer
1Prise(n)
0 personal points
Kartoffeln
600g, festkochend
10 personal points
Halbfettmargarine, 39 % Fett
2TL
2 personal points
Weizenmehl
1EL
1 personal points
Gemüsebouillon/Gemüsebrühe, zubereitet
300ml(2 TL Instantpulver)
0 personal points
Crème légère
3EL
4 personal points
Petersilie
2EL, gehackt
0 personal points
Rote Bete (Konserve)
430g, entspricht 1 Glas
7 personal points

Anleitung

  1. Backofen auf 200° C (Gas: Stufe 3, Umluft: 180° C) vorheizen. Champignons trocken abreiben und mit Cornichons in feine Würfel schneiden. Frühlingszwiebeln waschen und in Ringe schneiden. Champignon-, Cornichonwürfel und Frühlingszwiebelringe mit Tatar, Paniermehl, Ei, 1 Teelöffel Senf, Salz und Pfeffer verkneten und zu einem Braten formen.
  2. Hackbraten in eine Kastenform (Länge 30 cm) geben und im Backofen auf unterer Schiene ca. 45 Minuten garen. Kartoffeln schälen, halbieren und in Salzwasser ca. 20 Minuten garen. Für die Sauce Margarine in einem Topf schmelzen, Mehl darin hellgelb anschwitzen, unter Rühren mit Brühe ablöschen, ca. 4 Minuten köcheln lassen. Mit Créme légère verfeinern und mit Salz, Pfeffer, restlichem Senf und Petersilie würzen. Kartoffeln abgießen und Rote Bete abtropfen lassen. Hackbraten mit Senfsauce, Salzkartoffeln und Rote Bete servieren.
+ + + +
+ + + + + + +
\ No newline at end of file diff --git a/tests/test_data/weightwatcherspublic.testhtml b/tests/test_data/weightwatcherspublic.testhtml new file mode 100644 index 000000000..bb6265d50 --- /dev/null +++ b/tests/test_data/weightwatcherspublic.testhtml @@ -0,0 +1,29 @@ + + + Kartoffelgulasch Rezept | WW Deutschland + + + + + + +
Foto Kartoffelgulasch von WW

Kartoffelgulasch

10 - 13
PersonalPoints™ pro Portion
Gesamtzeit
40 min
Zubereitungsdauer
40 min
Garzeit
0 min
Portion(en)
4
Schwierigkeitsgrad
Leicht
Das Rezept zaubert ein saftiges, würziges Gericht auf den Tisch und schmeckt garantiert.

Zutaten

Kartoffeln

800 g, vorwiegend festkochend

Zwiebel/n

2 Stück, mittelgroß

Paprika

2 Stück, rot

Paprika

2 Stück, grün

Petersilie

1 EL, gehackt

Paprika

2 Stück, gelb

Tomaten, frisch

250 g

Wiener Würstchen

4 Stück

Pflanzenöl, Rapsöl/Sonnenblumenöl

2 TL

Tomatenmark

2 EL

Gemüsebouillon/Gemüsebrühe, zubereitet

250 ml, (1 TL Instantpulver)

Oregano

1 TL, gehackt

Paprikapulver

1 TL

Salz/Jodsalz

1 Prise(n)

Pfeffer

1 Prise(n)

Schmand, 24 % Fett

2 EL

Anleitung

  1. Kartoffeln und Zwiebeln schälen. Kartoffeln würfeln und Zwiebeln in Streifen schneiden. Paprika waschen, entkernen und in Stücke schneiden. Tomaten waschen und in Spalten schneiden. Würstchen in Scheiben schneiden.
  2. Öl in einem Topf erhitzen, Kartoffelwürfel und Zwiebelstreifen darin ca. 5 Minuten anbraten. Paprikastücke zufügen, Tomatenmark einrühren und kurz mitbraten. Mit Brühe ablöschen und zugedeckt ca. 15 Minuten garen.
  3. Kartoffelgulasch mit Oregano, Paprikapulver, Salz und Pfeffer würzen. Würstchenscheiben und Tomatenspalten zufügen und weitere ca. 5 Minuten garen. Kartoffelgulasch mit Salz und Pfeffer abschmecken. Mit einem Klecks Schmand und Petersilie bestreut servieren.
\ No newline at end of file diff --git a/tests/test_weightwatchers.py b/tests/test_weightwatchers.py new file mode 100644 index 000000000..5c741cc9f --- /dev/null +++ b/tests/test_weightwatchers.py @@ -0,0 +1,83 @@ +# mypy: allow-untyped-defs + +from recipe_scrapers.weightwatchers import WeightWatchers +from tests import ScraperTest + + +class TestWeightwatchersScraper(ScraperTest): + + # Test-Url: + # https://cmx.weightwatchers.de/details/WWRECIPE:5667ab72a29713e4335bb342 + + scraper_class = WeightWatchers + + def test_host(self): + self.assertEqual("www.weightwatchers.com", self.harvester_class.host()) + + def test_author(self): + self.assertEqual("WeightWatchers", self.harvester_class.author()) + + def test_title(self): + self.assertEqual(self.harvester_class.title(), "Würstchengulasch mit Nudeln") + + def test_category(self): + self.assertEqual("WeightWatchers", self.harvester_class.category()) + + def test_total_time(self): + self.assertEqual(25, self.harvester_class.total_time()) + + def test_cook_time(self): + self.assertEqual(0, self.harvester_class.cook_time()) + + def test_prep_time(self): + self.assertEqual(25, self.harvester_class.prep_time()) + + def test_yields(self): + self.assertEqual("2 servings", self.harvester_class.yields()) + + def test_image(self): + self.assertEqual( + "https://cmx.weightwatchers.com/assets-proxy/weight-watchers/image/upload/t_WINE_EXTRALARGE/i34cskr1hxegmxqukawd.jpg", + self.harvester_class.image(), + ) + + def test_ingredients(self): + self.assertEqual( + [ + "2 Stück Geflügelwürstchen", + "1 Stück, klein Zwiebel/n", + "200 g Champignons, frisch; braun", + "120 g Nudeln, trocken, jede Sorte; Spiralnudeln", + "1 Prise(n) Salz/Jodsalz", + "2 TL Pflanzenöl, Rapsöl/Sonnenblumenöl", + "400 g Tomaten, passiert", + "1 Prise(n) Pfeffer", + "1⁄2 TL Paprikapulver", + ], + self.harvester_class.ingredients(), + ) + + def test_ingredientsCount(self): + self.assertEqual(9, len(self.harvester_class.ingredients())) + + def test_instructions(self): + self.assertEqual( + "Würstchen in Scheiben schneiden. Zwiebel schälen und würfeln. Champignons trocken abreiben und vierteln. Nudeln nach Packungsanweisung in Salzwasser garen.\nÖl in einem Topf erhitzen und Zwiebelwürfel darin andünsten. Würstchenscheiben und Champignonviertel zufügen und ca. 3 Minuten anbraten. Mit Tomaten ablöschen, aufkochen und ca. 5 Minuten köcheln lassen. Würstchengulasch mit Salz, Pfeffer und Paprikapulver würzen. Nudeln abgießen, untermischen und in einer Frischhaltedose transportieren. Würstchengulasch erwärmen und servieren.", + self.harvester_class.instructions(), + ) + + def test_description(self): + self.assertEqual( + "18 Uhr und alle haben Hunger? Dann koche rasch das Würstchengulasch und alle sind happy.", + self.harvester_class.description(), + ) + + def test_difficulty(self): + self.assertEqual("Leicht", self.harvester_class.difficulty()) + + def test_nutrients(self): + expected_nutrients = { + "personal points": "earn 12 personal points", + "positive points": "+2 Punkte von 2 Portion(en) Gemüse", + } + self.assertEqual(self.harvester_class.nutrients(), expected_nutrients) diff --git a/tests/test_weightwatchers_2.py b/tests/test_weightwatchers_2.py new file mode 100644 index 000000000..424cec068 --- /dev/null +++ b/tests/test_weightwatchers_2.py @@ -0,0 +1,88 @@ +# mypy: allow-untyped-defs + +from recipe_scrapers.weightwatchers import WeightWatchers +from tests import ScraperTest + + +class TestWeightwatchersScraper(ScraperTest): + + # Test-Url: + # https://cmx.weightwatchers.de/details/WWRECIPE:562a9bc8a43e6bde2cf369df + + scraper_class = WeightWatchers + test_file_name = "weightwatchers_2" + + def test_host(self): + self.assertEqual("www.weightwatchers.com", self.harvester_class.host()) + + def test_author(self): + self.assertEqual("WeightWatchers", self.harvester_class.author()) + + def test_title(self): + self.assertEqual(self.harvester_class.title(), "Hackbraten Stroganoff") + + def test_category(self): + self.assertEqual("WeightWatchers", self.harvester_class.category()) + + def test_total_time(self): + self.assertEqual(65, self.harvester_class.total_time()) + + def test_cook_time(self): + self.assertEqual(25, self.harvester_class.cook_time()) + + def test_prep_time(self): + self.assertEqual(40, self.harvester_class.prep_time()) + + def test_yields(self): + self.assertEqual("4 servings", self.harvester_class.yields()) + + def test_image(self): + self.assertEqual( + "https://cmx.weightwatchers.com/assets-proxy/weight-watchers/image/upload/t_WINE_EXTRALARGE/vziguy9ale25vtx7spgl.jpg", + self.harvester_class.image(), + ) + + def test_ingredients(self): + self.assertEqual( + [ + "125 g Champignons, frisch", + "5 Stück Cornichons", + "1 Bund Frühlingszwiebeln/Lauchzwiebeln", + "600 g Tatar, roh", + "2 EL Paniermehl/Semmelbrösel", + "1 Stück, Gewichtsklasse M Eier, Hühnereier", + "4 TL Senf, klassisch", + "1 Prise(n) Salz/Jodsalz", + "1 Prise(n) Pfeffer", + "600 g Kartoffeln; festkochend", + "2 TL Halbfettmargarine, 39 % Fett", + "1 EL Weizenmehl", + "300 ml Gemüsebouillon/Gemüsebrühe, zubereitet; (2 TL Instantpulver)", + "3 EL Crème légère", + "2 EL, gehackt Petersilie", + "430 g Rote Bete (Konserve); entspricht 1 Glas", + ], + self.harvester_class.ingredients(), + ) + + def test_ingredientsCount(self): + self.assertEqual(16, len(self.harvester_class.ingredients())) + + def test_instructions(self): + self.assertEqual( + "Backofen auf 200° C (Gas: Stufe 3, Umluft: 180° C) vorheizen. Champignons trocken abreiben und mit Cornichons in feine Würfel schneiden. Frühlingszwiebeln waschen und in Ringe schneiden. Champignon-, Cornichonwürfel und Frühlingszwiebelringe mit Tatar, Paniermehl, Ei, 1 Teelöffel Senf, Salz und Pfeffer verkneten und zu einem Braten formen.\nHackbraten in eine Kastenform (Länge 30 cm) geben und im Backofen auf unterer Schiene ca. 45 Minuten garen. Kartoffeln schälen, halbieren und in Salzwasser ca. 20 Minuten garen. Für die Sauce Margarine in einem Topf schmelzen, Mehl darin hellgelb anschwitzen, unter Rühren mit Brühe ablöschen, ca. 4 Minuten köcheln lassen. Mit Créme légère verfeinern und mit Salz, Pfeffer, restlichem Senf und Petersilie würzen. Kartoffeln abgießen und Rote Bete abtropfen lassen. Hackbraten mit Senfsauce, Salzkartoffeln und Rote Bete servieren.", + self.harvester_class.instructions(), + ) + + def test_description(self): + self.assertEqual( + "Wenn das mal keine mutige Abwandlung des beliebten Klassiker ist. Schmeckt übrigens ganz vorzüglich!", + self.harvester_class.description(), + ) + + def test_difficulty(self): + self.assertEqual("Mittel", self.harvester_class.difficulty()) + + def test_nutrients(self): + expected_nutrients = {"personal points": "10 personal points"} + self.assertEqual(self.harvester_class.nutrients(), expected_nutrients) diff --git a/tests/test_weightwatcherspublic.py b/tests/test_weightwatcherspublic.py new file mode 100644 index 000000000..5d1120a23 --- /dev/null +++ b/tests/test_weightwatcherspublic.py @@ -0,0 +1,89 @@ +# mypy: allow-untyped-defs + +from recipe_scrapers.weightwatcherspublic import WeightWatchersPublic +from tests import ScraperTest + + +class TestweightwatchersPublicScraper(ScraperTest): + + scraper_class = WeightWatchersPublic + + # Test-Url: + # https://www.weightwatchers.com/de/rezept/kartoffelgulasch/562a9b02873e1afb2a3c4c13 + + def test_host(self): + self.assertEqual("www.weightwatchers.com", self.harvester_class.host()) + + def test_author(self): + self.assertEqual("WeightWatchers", self.harvester_class.author()) + + def test_title(self): + self.assertEqual(self.harvester_class.title(), "Kartoffelgulasch") + + def test_category(self): + self.assertEqual("WeightWatchers", self.harvester_class.category()) + + def test_total_time(self): + self.assertEqual(40, self.harvester_class.total_time()) + + def test_cook_time(self): + self.assertEqual(0, self.harvester_class.cook_time()) + + def test_prep_time(self): + self.assertEqual(40, self.harvester_class.prep_time()) + + def test_yields(self): + self.assertEqual("4 servings", self.harvester_class.yields()) + + def test_image(self): + self.assertEqual( + "https://cmx.weightwatchers.com/assets-proxy/weight-watchers/image/upload/q_auto/h7wo0hbnwcleucj30sbw.jpg?auto=webp", + self.harvester_class.image(), + ) + + def test_ingredients(self): + self.assertEqual( + [ + "800 g Kartoffeln; vorwiegend festkochend", + "2 Stück Zwiebel/n; mittelgroß", + "2 Stück Paprika; rot", + "2 Stück Paprika; grün", + "1 EL Petersilie; gehackt", + "2 Stück Paprika; gelb", + "250 g Tomaten, frisch", + "4 Stück Wiener Würstchen", + "2 TL Pflanzenöl, Rapsöl/Sonnenblumenöl", + "2 EL Tomatenmark", + "250 ml Gemüsebouillon/Gemüsebrühe, zubereitet; (1 TL Instantpulver)", + "1 TL Oregano; gehackt", + "1 TL Paprikapulver", + "1 Prise(n) Salz/Jodsalz", + "1 Prise(n) Pfeffer", + "2 EL Schmand, 24 % Fett", + ], + self.harvester_class.ingredients(), + ) + + def test_ingredientsCount(self): + self.assertEqual(16, len(self.harvester_class.ingredients())) + + def test_instructions(self): + self.assertEqual( + "Kartoffeln und Zwiebeln schälen. Kartoffeln würfeln und Zwiebeln in Streifen schneiden. Paprika waschen, entkernen und in Stücke schneiden. Tomaten waschen und in Spalten schneiden. Würstchen in Scheiben schneiden.\nÖl in einem Topf erhitzen, Kartoffelwürfel und Zwiebelstreifen darin ca. 5 Minuten anbraten. Paprikastücke zufügen, Tomatenmark einrühren und kurz mitbraten. Mit Brühe ablöschen und zugedeckt ca. 15 Minuten garen.\nKartoffelgulasch mit Oregano, Paprikapulver, Salz und Pfeffer würzen. Würstchenscheiben und Tomatenspalten zufügen und weitere ca. 5 Minuten garen. Kartoffelgulasch mit Salz und Pfeffer abschmecken. Mit einem Klecks Schmand und Petersilie bestreut servieren.", + self.harvester_class.instructions(), + ) + + def test_description(self): + self.assertEqual( + "Das Rezept zaubert ein saftiges, würziges Gericht auf den Tisch und schmeckt garantiert.", + self.harvester_class.description(), + ) + + def test_difficulty(self): + self.assertEqual("Leicht", self.harvester_class.difficulty()) + + def test_nutrients(self): + expected_nutrients = { + "points": "10 bis 13 PersonalPoints", + } + self.assertEqual(self.harvester_class.nutrients(), expected_nutrients)