diff --git a/src/humulus/recipes.py b/src/humulus/recipes.py index 525f16c..8d569b9 100644 --- a/src/humulus/recipes.py +++ b/src/humulus/recipes.py @@ -37,7 +37,7 @@ bp = Blueprint('recipes', __name__, url_prefix='/recipes') class FermentableForm(Form): """Form for fermentables. - CSRF is disabled for this form.yeast.form (using `Form as parent class) + CSRF is disabled for this form (using `Form as parent class) because it is never used by itself. """ name = StringField('Name', validators=[DataRequired()]) @@ -67,7 +67,7 @@ class FermentableForm(Form): class HopForm(Form): """Form for hops. - CSRF is disabled for this form.yeast.form (using `Form as parent class) + CSRF is disabled for this form (using `Form as parent class) because it is never used by itself. """ name = StringField('Name', validators=[DataRequired()]) @@ -96,7 +96,7 @@ class HopForm(Form): class YeastForm(Form): """Form for yeast. - CSRF is disabled for this form.yeast.form (using `Form as parent class) + CSRF is disabled for this form (using `Form as parent class) because it is never used by itself. """ name = StringField('Name', validators=[Optional()]) @@ -148,6 +148,63 @@ class YeastForm(Form): return yeast +class MashStepForm(Form): + """Form for mash steps. + + CSRF is disabled for this form (using `Form as parent class) + because it is never used by itself. + """ + name = StringField('Name', validators=[DataRequired()]) + type = SelectField('Type', + choices=[(c, c) for c in ['Infusion', + 'Temperature', + 'Decoction']]) + temp = DecimalField('Temperature', validators=[DataRequired()]) + time = DecimalField('Time', validators=[DataRequired()]) + amount = DecimalField('Water Amount') + + @property + def doc(self): + """Returns a dictionary that can be deserialized into JSON. + + Used for putting into CouchDB. + """ + step = { + 'name': self.name.data, + 'type': self.type.data, + 'temp': str(self.temp.data), + 'time': str(self.time.data), + } + if self.amount.data: + step['amount'] = str(self.amount.data) + return step + + +class MashForm(Form): + """Form for mash. + + CSRF is disabled for this form (using `Form as parent class) + because it is never used by itself. + """ + name = StringField('Name', validators=[Optional()]) + steps = FieldList( + FormField(MashStepForm), + min_entries=0, + max_entries=20 + ) + + @property + def doc(self): + """Returns a dictionary that can be deserialized into JSON. + + Used for putting into CouchDB. + """ + return { + 'name': self.name.data, + 'steps': [s.doc for s in self.steps] + } + + class RecipeForm(FlaskForm): """Form for recipes.""" name = StringField('Name', validators=[DataRequired()]) @@ -171,6 +228,7 @@ class RecipeForm(FlaskForm): max_entries=20 ) yeast = FormField(YeastForm) + mash = FormField(MashForm) style = SelectField('Style', choices=[], validators=[Optional()]) @property @@ -197,6 +255,8 @@ class RecipeForm(FlaskForm): self.yeast.doc['high_attenuation'] != "None" ): recipe['yeast'] = self.yeast.doc + if self.mash.doc['name']: + recipe['mash'] = self.mash.doc return recipe def copyfrom(self, data): diff --git a/tests/test_recipes.py b/tests/test_recipes.py index b1c69f1..1d97d7b 100644 --- a/tests/test_recipes.py +++ b/tests/test_recipes.py @@ -17,7 +17,8 @@ from decimal import Decimal from io import BytesIO from humulus.couch import get_doc -from humulus.recipes import FermentableForm, HopForm, RecipeForm, YeastForm +from humulus.recipes import (FermentableForm, HopForm, RecipeForm, YeastForm, + MashForm, MashStepForm) def test_index(client): @@ -247,6 +248,30 @@ def test_info_json(client): assert response.get_json()['name'] == 'Awesome Lager' +def test_step_form_doc(app): + """Evaluates conditionals in generation of doc from a step form.""" + step = MashStepForm() + step.name.data = 'Test Mash Step' + step.type.data = 'Infusion' + step.temp.data = Decimal('152') + step.time.data = Decimal('60') + assert step.doc == { + 'name': 'Test Mash Step', + 'type': 'Infusion', + 'temp': '152', + 'time': '60' + } + + step.amount.data = Decimal('3.5') + assert step.doc == { + 'name': 'Test Mash Step', + 'type': 'Infusion', + 'temp': '152', + 'time': '60', + 'amount': '3.5' + } + + def test_yeast_form_doc(app): """Evaluates conditionals in generation of doc from a yeast form.""" yeast = YeastForm() @@ -329,8 +354,19 @@ def test_recipe_form_doc(app): yeast.low_attenuation.data = '70' yeast.high_attenuation.data = '75' + step = MashStepForm() + step.name.data = 'Test Mash Step' + step.type.data = 'Infusion' + step.temp.data = Decimal('152') + step.time.data = Decimal('60') + step.amount.data = Decimal('3.5') + mash = MashForm() + mash.name.data = 'Single Infusion' + mash.steps = [step] + recipe.fermentables = [ferm] recipe.hops = [hop] + recipe.mash = mash recipe.yeast = yeast assert recipe.doc == { @@ -359,6 +395,16 @@ def test_recipe_form_doc(app): 'name': 'Test', 'low_attenuation': '70', 'high_attenuation': '75' + }, + 'mash': { + 'name': 'Single Infusion', + 'steps': [{ + 'name': 'Test Mash Step', + 'type': 'Infusion', + 'temp': '152', + 'time': '60', + 'amount': '3.5' + }] } }