mirror of
https://github.com/shouptech/humulus.git
synced 2026-02-03 15:59:43 +00:00
parent
966999e93f
commit
7cccb8fe84
6 changed files with 393 additions and 22 deletions
|
|
@ -37,7 +37,7 @@ bp = Blueprint('recipes', __name__, url_prefix='/recipes')
|
||||||
class FermentableForm(Form):
|
class FermentableForm(Form):
|
||||||
"""Form for fermentables.
|
"""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.
|
because it is never used by itself.
|
||||||
"""
|
"""
|
||||||
name = StringField('Name', validators=[DataRequired()])
|
name = StringField('Name', validators=[DataRequired()])
|
||||||
|
|
@ -67,7 +67,7 @@ class FermentableForm(Form):
|
||||||
class HopForm(Form):
|
class HopForm(Form):
|
||||||
"""Form for hops.
|
"""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.
|
because it is never used by itself.
|
||||||
"""
|
"""
|
||||||
name = StringField('Name', validators=[DataRequired()])
|
name = StringField('Name', validators=[DataRequired()])
|
||||||
|
|
@ -96,7 +96,7 @@ class HopForm(Form):
|
||||||
class YeastForm(Form):
|
class YeastForm(Form):
|
||||||
"""Form for yeast.
|
"""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.
|
because it is never used by itself.
|
||||||
"""
|
"""
|
||||||
name = StringField('Name', validators=[Optional()])
|
name = StringField('Name', validators=[Optional()])
|
||||||
|
|
@ -148,6 +148,63 @@ class YeastForm(Form):
|
||||||
return yeast
|
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('Step Name', validators=[DataRequired()])
|
||||||
|
type = SelectField('Type',
|
||||||
|
choices=[(c, c) for c in ['Infusion',
|
||||||
|
'Temperature',
|
||||||
|
'Decoction']])
|
||||||
|
temp = DecimalField('Temperature (°F)', validators=[DataRequired()])
|
||||||
|
time = DecimalField('Time (min)', validators=[DataRequired()])
|
||||||
|
amount = DecimalField('Water Amount (gal)')
|
||||||
|
|
||||||
|
@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('Mash 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):
|
class RecipeForm(FlaskForm):
|
||||||
"""Form for recipes."""
|
"""Form for recipes."""
|
||||||
name = StringField('Name', validators=[DataRequired()])
|
name = StringField('Name', validators=[DataRequired()])
|
||||||
|
|
@ -171,6 +228,7 @@ class RecipeForm(FlaskForm):
|
||||||
max_entries=20
|
max_entries=20
|
||||||
)
|
)
|
||||||
yeast = FormField(YeastForm)
|
yeast = FormField(YeastForm)
|
||||||
|
mash = FormField(MashForm)
|
||||||
style = SelectField('Style', choices=[], validators=[Optional()])
|
style = SelectField('Style', choices=[], validators=[Optional()])
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
@ -197,6 +255,8 @@ class RecipeForm(FlaskForm):
|
||||||
self.yeast.doc['high_attenuation'] != "None"
|
self.yeast.doc['high_attenuation'] != "None"
|
||||||
):
|
):
|
||||||
recipe['yeast'] = self.yeast.doc
|
recipe['yeast'] = self.yeast.doc
|
||||||
|
if self.mash.doc['name']:
|
||||||
|
recipe['mash'] = self.mash.doc
|
||||||
return recipe
|
return recipe
|
||||||
|
|
||||||
def copyfrom(self, data):
|
def copyfrom(self, data):
|
||||||
|
|
@ -227,35 +287,52 @@ class RecipeForm(FlaskForm):
|
||||||
})
|
})
|
||||||
|
|
||||||
if 'yeast' in data:
|
if 'yeast' in data:
|
||||||
yeast = data['yeast']
|
self.yeast.form.name.data = data['yeast']['name']
|
||||||
self.yeast.form.name.data = yeast['name']
|
|
||||||
self.yeast.form.low_attenuation.data = (
|
self.yeast.form.low_attenuation.data = (
|
||||||
Decimal(yeast['low_attenuation'])
|
Decimal(data['yeast']['low_attenuation'])
|
||||||
)
|
)
|
||||||
self.yeast.form.high_attenuation.data = (
|
self.yeast.form.high_attenuation.data = (
|
||||||
Decimal(yeast['high_attenuation'])
|
Decimal(data['yeast']['high_attenuation'])
|
||||||
)
|
)
|
||||||
if 'type' in yeast:
|
if 'type' in data['yeast']:
|
||||||
self.yeast.form.type.data = yeast['type']
|
self.yeast.form.type.data = data['yeast']['type']
|
||||||
if 'lab' in yeast:
|
if 'lab' in data['yeast']:
|
||||||
self.yeast.form.lab.data = yeast['lab']
|
self.yeast.form.lab.data = data['yeast']['lab']
|
||||||
if 'code' in yeast:
|
if 'code' in data['yeast']:
|
||||||
self.yeast.form.code.data = yeast['code']
|
self.yeast.form.code.data = data['yeast']['code']
|
||||||
if 'flocculation' in yeast:
|
if 'flocculation' in data['yeast']:
|
||||||
self.yeast.form.flocculation.data = yeast['flocculation']
|
self.yeast.form.flocculation.data = (
|
||||||
if 'min_temperature' in yeast:
|
data['yeast']['flocculation']
|
||||||
|
)
|
||||||
|
if 'min_temperature' in data['yeast']:
|
||||||
self.yeast.form.min_temperature.data = (
|
self.yeast.form.min_temperature.data = (
|
||||||
Decimal(yeast['min_temperature'])
|
Decimal(data['yeast']['min_temperature'])
|
||||||
)
|
)
|
||||||
if 'max_temperature' in yeast:
|
if 'max_temperature' in data['yeast']:
|
||||||
self.yeast.form.max_temperature.data = (
|
self.yeast.form.max_temperature.data = (
|
||||||
Decimal(yeast['max_temperature'])
|
Decimal(data['yeast']['max_temperature'])
|
||||||
)
|
)
|
||||||
if 'abv_tolerance' in yeast:
|
if 'abv_tolerance' in data['yeast']:
|
||||||
self.yeast.form.abv_tolerance.data = (
|
self.yeast.form.abv_tolerance.data = (
|
||||||
Decimal(yeast['abv_tolerance'])
|
Decimal(data['yeast']['abv_tolerance'])
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if 'mash' in data:
|
||||||
|
if 'name' in data['mash']:
|
||||||
|
self.mash.form.name.data = data['mash']['name']
|
||||||
|
if 'steps' in data['mash']:
|
||||||
|
for step in data['mash']['steps']:
|
||||||
|
new_step = {
|
||||||
|
'name': step['name'],
|
||||||
|
'type': step['type'],
|
||||||
|
'temp': Decimal(step['temp']),
|
||||||
|
'time': Decimal(step['time'])
|
||||||
|
}
|
||||||
|
if 'amount' in step:
|
||||||
|
new_step['amount'] = Decimal(step['amount'])
|
||||||
|
print(new_step)
|
||||||
|
self.mash.steps.append_entry(new_step)
|
||||||
|
|
||||||
|
|
||||||
class ImportForm(FlaskForm):
|
class ImportForm(FlaskForm):
|
||||||
upload = FileField(validators=[FileRequired()])
|
upload = FileField(validators=[FileRequired()])
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,11 @@ function removeHop() {
|
||||||
removeForm($(this), '.hop-form', '#hops');
|
removeForm($(this), '.hop-form', '#hops');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove a mash step
|
||||||
|
function removeMashStep() {
|
||||||
|
removeForm($(this), '.mash-form', '#mash');
|
||||||
|
}
|
||||||
|
|
||||||
// Add a fermentable
|
// Add a fermentable
|
||||||
function addFerm() {
|
function addFerm() {
|
||||||
var $fermsDiv = $('#ferms');
|
var $fermsDiv = $('#ferms');
|
||||||
|
|
@ -212,6 +217,58 @@ function addHop() {
|
||||||
rebindChangeEvents();
|
rebindChangeEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add a new mash step
|
||||||
|
function addMashStep() {
|
||||||
|
var $mashDiv = $('#mash');
|
||||||
|
var stepsLength = $mashDiv.data('length');
|
||||||
|
if (stepsLength == 20) {
|
||||||
|
window.alert("Can't have more than 20 mash steps.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var newStep = `<div class="border pl-2 pr-2 pt-1 pb-1 mash-form" data-index="${stepsLength}">` +
|
||||||
|
'<div class="row"><div class="col-sm-8"><div class="form-group">' +
|
||||||
|
// Step Name Field
|
||||||
|
`<label for="mash-steps-${stepsLength}-name">Step Name</label>` +
|
||||||
|
`<input class="form-control form-control-sm" id="mash-steps-${stepsLength}-name" ` +
|
||||||
|
`name="mash-steps-${stepsLength}-name" required type="text" value="">` +
|
||||||
|
'</div></div>' + // End Step Name field
|
||||||
|
// Type field
|
||||||
|
'<div class="col-sm-4"><div class="form-group">' +
|
||||||
|
`<label for="mash-steps-${stepsLength}-type">Type</label>` +
|
||||||
|
`<select class="custom-select custom-select-sm" id="mash-steps-${stepsLength}-type" ` +
|
||||||
|
`name="mash-steps-${stepsLength}-type">` +
|
||||||
|
'<option value="Infusion">Infusion</option>' +
|
||||||
|
'<option value="Temperature">Temperature</option>' +
|
||||||
|
'<option value="Decoction">Decoction</option></select>' +
|
||||||
|
'</div></div></div>' + // End Type field
|
||||||
|
// Temperature field
|
||||||
|
'<div class="row"><div class="col-sm"><div class="form-group">' +
|
||||||
|
`<label for="mash-steps-${stepsLength}-temp">Temperature (°F)</label>` +
|
||||||
|
`<input class="form-control form-control-sm" id="mash-steps-${stepsLength}-temp" ` +
|
||||||
|
`name="mash-steps-${stepsLength}-temp" required type="text" value="">` +
|
||||||
|
'</div></div>' + // End temperature field
|
||||||
|
//Time field
|
||||||
|
'<div class="col-sm"><div class="form-group">' +
|
||||||
|
`<label for="mash-steps-${stepsLength}-time">Time (min)</label>` +
|
||||||
|
`<input class="form-control form-control-sm" id="mash-steps-${stepsLength}-time" ` +
|
||||||
|
`name="mash-steps-${stepsLength}-time" required type="text" value="">` +
|
||||||
|
'</div></div>' + // End time field
|
||||||
|
// Amount field
|
||||||
|
'<div class="col-sm"><div class="form-group">' +
|
||||||
|
`<label for="mash-steps-${stepsLength}-amount">Water Amount (gal)</label>` +
|
||||||
|
`<input class="form-control form-control-sm" id="mash-steps-${stepsLength}-amount" ` +
|
||||||
|
`name="mash-steps-${stepsLength}-amount" type="text" value="">` +
|
||||||
|
'</div></div></div>' + // End amount field
|
||||||
|
'<div class="row"><div class="col">' +
|
||||||
|
'<button type="button" class="float-right btn btn-sm btn-outline-danger rem-step">Remove Step</button>' +
|
||||||
|
'</div></div></div>';
|
||||||
|
|
||||||
|
$mashDiv.append(newStep);
|
||||||
|
$('.rem-step').unbind('click');
|
||||||
|
$('.rem-step').click(removeMashStep);
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate recipe's original gravity
|
// Calculate recipe's original gravity
|
||||||
function calculateOG() {
|
function calculateOG() {
|
||||||
var fermsLength = $('#ferms').data('length');
|
var fermsLength = $('#ferms').data('length');
|
||||||
|
|
@ -414,6 +471,8 @@ $(document).ready(function() {
|
||||||
$('.rem-ferm').click(removeFerm);
|
$('.rem-ferm').click(removeFerm);
|
||||||
$('#add-hop').click(addHop);
|
$('#add-hop').click(addHop);
|
||||||
$('.rem-hop').click(removeHop);
|
$('.rem-hop').click(removeHop);
|
||||||
|
$('#add-step').click(addMashStep);
|
||||||
|
$('.rem-step').click(removeMashStep);
|
||||||
|
|
||||||
// Register change events
|
// Register change events
|
||||||
rebindChangeEvents();
|
rebindChangeEvents();
|
||||||
|
|
|
||||||
|
|
@ -130,6 +130,36 @@ function getSpecsURL() {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{#-
|
||||||
|
Mash & Steps
|
||||||
|
-#}
|
||||||
|
<div class="row"><div class="col"><h3>Mash</h3></div></div>
|
||||||
|
<div id="mash" data-length="{{ form.mash.form.steps|length }}">
|
||||||
|
{{ render_field_with_errors(form.mash.form.name, 'form-control-sm') }}
|
||||||
|
{% for step in form.mash.form.steps %}
|
||||||
|
<div class="border pl-2 pr-2 pt-1 pb-1 mash-form" data-index="{{ loop.index0 }}"">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-8">{{ render_field_with_errors(step.form.name, 'form-control-sm') }}</div>
|
||||||
|
<div class="col-sm-4">{{ render_field_with_errors(step.form.type, 'custom-select-sm', base_class='custom-select') }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm">{{ render_field_with_errors(step.form.temp, 'form-control-sm') }}</div>
|
||||||
|
<div class="col-sm">{{ render_field_with_errors(step.form.time, 'form-control-sm') }}</div>
|
||||||
|
<div class="col-sm">{{ render_field_with_errors(step.form.amount, 'form-control-sm') }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<button type="button" class="float-right btn btn-sm btn-outline-danger rem-step">Remove Step</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
<div class="row pt-1 pb-1">
|
||||||
|
<div class="col">
|
||||||
|
<button type="button" id="add-step" class="btn btn-secondary btn-sm">Add mash step</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{#-
|
{#-
|
||||||
Recipe Notes
|
Recipe Notes
|
||||||
-#}
|
-#}
|
||||||
|
|
|
||||||
|
|
@ -200,11 +200,41 @@
|
||||||
</table>
|
</table>
|
||||||
</div></div>
|
</div></div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if recipe.mash and recipe.mash.name %}
|
||||||
|
<div class="row border-top"><h2>Mash</h2></div>
|
||||||
|
<div class="row">{{ recipe.mash.name }}</div>
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-hover table-sm">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>#</th>
|
||||||
|
<th>Step Name</th>
|
||||||
|
<th>Type</th>
|
||||||
|
<th>Temp</th>
|
||||||
|
<th>Time</th>
|
||||||
|
<th>Amount</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
{% for step in recipe.mash.steps %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ loop.index }}</td>
|
||||||
|
<td>{{ step.name }}</td>
|
||||||
|
<td>{{ step.type }}</td>
|
||||||
|
<td>{% if step.temp %}{{ step.temp }} °F{% endif %}</td>
|
||||||
|
<td>{% if step.time %}{{ step.time }} min.{% endif %}</td>
|
||||||
|
<td>{% if step.amount %}{{ step.amount }} gal.{% endif %}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
{#-
|
{#-
|
||||||
Recipe Notes
|
Recipe Notes
|
||||||
-#}
|
-#}
|
||||||
|
{% if recipe.notes %}
|
||||||
<div class="row border-top"><h2>Recipe Notes</h2></div>
|
<div class="row border-top"><h2>Recipe Notes</h2></div>
|
||||||
<div class="row"><div class="col">{{ recipe.notes }}</div></div>
|
<div class="row"><div class="col">{{ recipe.notes }}</div></div>
|
||||||
|
{% endif %}
|
||||||
{#-
|
{#-
|
||||||
Buttons to do things
|
Buttons to do things
|
||||||
-#}
|
-#}
|
||||||
|
|
|
||||||
|
|
@ -123,6 +123,16 @@ def app():
|
||||||
'min_temperature': '60',
|
'min_temperature': '60',
|
||||||
'max_temperature': '72',
|
'max_temperature': '72',
|
||||||
'abv_tolerance': '10'
|
'abv_tolerance': '10'
|
||||||
|
},
|
||||||
|
'mash': {
|
||||||
|
'name': 'Single Infusion',
|
||||||
|
'steps': [{
|
||||||
|
'name': 'Infusion',
|
||||||
|
'type': 'Infusion',
|
||||||
|
'temp': '152',
|
||||||
|
'time': '60',
|
||||||
|
'amount': '3.5'
|
||||||
|
}]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,8 @@ from decimal import Decimal
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
|
||||||
from humulus.couch import get_doc
|
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):
|
def test_index(client):
|
||||||
|
|
@ -247,6 +248,30 @@ def test_info_json(client):
|
||||||
assert response.get_json()['name'] == 'Awesome Lager'
|
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):
|
def test_yeast_form_doc(app):
|
||||||
"""Evaluates conditionals in generation of doc from a yeast form."""
|
"""Evaluates conditionals in generation of doc from a yeast form."""
|
||||||
yeast = YeastForm()
|
yeast = YeastForm()
|
||||||
|
|
@ -329,8 +354,19 @@ def test_recipe_form_doc(app):
|
||||||
yeast.low_attenuation.data = '70'
|
yeast.low_attenuation.data = '70'
|
||||||
yeast.high_attenuation.data = '75'
|
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.fermentables = [ferm]
|
||||||
recipe.hops = [hop]
|
recipe.hops = [hop]
|
||||||
|
recipe.mash = mash
|
||||||
recipe.yeast = yeast
|
recipe.yeast = yeast
|
||||||
|
|
||||||
assert recipe.doc == {
|
assert recipe.doc == {
|
||||||
|
|
@ -359,6 +395,16 @@ def test_recipe_form_doc(app):
|
||||||
'name': 'Test',
|
'name': 'Test',
|
||||||
'low_attenuation': '70',
|
'low_attenuation': '70',
|
||||||
'high_attenuation': '75'
|
'high_attenuation': '75'
|
||||||
|
},
|
||||||
|
'mash': {
|
||||||
|
'name': 'Single Infusion',
|
||||||
|
'steps': [{
|
||||||
|
'name': 'Test Mash Step',
|
||||||
|
'type': 'Infusion',
|
||||||
|
'temp': '152',
|
||||||
|
'time': '60',
|
||||||
|
'amount': '3.5'
|
||||||
|
}]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -404,3 +450,122 @@ def test_recipe_create_json(client, sample_recipes, auth):
|
||||||
response = client.post('/recipes/create/json', buffered=True,
|
response = client.post('/recipes/create/json', buffered=True,
|
||||||
content_type='multipart/form-data', data=data)
|
content_type='multipart/form-data', data=data)
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
|
||||||
|
def test_copyfrom(app, sample_recipes):
|
||||||
|
recipe = {
|
||||||
|
'name': 'Test',
|
||||||
|
'type': 'All-Grain',
|
||||||
|
'efficiency': '65',
|
||||||
|
'volume': '5.5',
|
||||||
|
'notes': 'Notes',
|
||||||
|
'style': '18A',
|
||||||
|
'fermentables': [{
|
||||||
|
'name': 'Test',
|
||||||
|
'type': 'Grain',
|
||||||
|
'amount': '1',
|
||||||
|
'ppg': '36',
|
||||||
|
'color': '4'
|
||||||
|
}],
|
||||||
|
'hops': [{
|
||||||
|
'name': 'Test',
|
||||||
|
'use': 'Boil',
|
||||||
|
'alpha': '5.5',
|
||||||
|
'duration': '30',
|
||||||
|
'amount': '1'
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
|
||||||
|
with app.app_context():
|
||||||
|
form = RecipeForm()
|
||||||
|
form.copyfrom(recipe)
|
||||||
|
assert form.name.data == recipe['name']
|
||||||
|
assert form.type.data == recipe['type']
|
||||||
|
assert form.efficiency.data == Decimal(recipe['efficiency'])
|
||||||
|
assert form.volume.data == Decimal(recipe['volume'])
|
||||||
|
assert form.notes.data == recipe['notes']
|
||||||
|
assert len(form.fermentables) == len(recipe['fermentables'])
|
||||||
|
assert form.fermentables[0].form.name.data == \
|
||||||
|
recipe['fermentables'][0]['name']
|
||||||
|
assert form.fermentables[0].form.type.data == \
|
||||||
|
recipe['fermentables'][0]['type']
|
||||||
|
assert form.fermentables[0].form.amount.data == \
|
||||||
|
Decimal(recipe['fermentables'][0]['amount'])
|
||||||
|
assert form.fermentables[0].form.ppg.data == \
|
||||||
|
Decimal(recipe['fermentables'][0]['ppg'])
|
||||||
|
assert form.fermentables[0].form.color.data == \
|
||||||
|
Decimal(recipe['fermentables'][0]['color'])
|
||||||
|
assert len(form.hops) == len(recipe['hops'])
|
||||||
|
assert form.hops[0].form.name.data == recipe['hops'][0]['name']
|
||||||
|
assert form.hops[0].form.use.data == recipe['hops'][0]['use']
|
||||||
|
assert form.hops[0].form.alpha.data == Decimal(recipe['hops'][0]['alpha'])
|
||||||
|
assert form.hops[0].form.duration.data == \
|
||||||
|
Decimal(recipe['hops'][0]['duration'])
|
||||||
|
assert form.hops[0].form.amount.data == \
|
||||||
|
Decimal(recipe['hops'][0]['amount'])
|
||||||
|
|
||||||
|
recipe['yeast'] = {
|
||||||
|
'name': 'Test', 'low_attenuation': '65', 'high_attenuation': '68'
|
||||||
|
}
|
||||||
|
recipe['mash'] = {}
|
||||||
|
with app.app_context():
|
||||||
|
form = RecipeForm()
|
||||||
|
form.copyfrom(recipe)
|
||||||
|
assert form.yeast.form.name.data == recipe['yeast']['name']
|
||||||
|
assert form.yeast.form.low_attenuation.data == \
|
||||||
|
Decimal(recipe['yeast']['low_attenuation'])
|
||||||
|
assert form.yeast.form.high_attenuation.data == \
|
||||||
|
Decimal(recipe['yeast']['high_attenuation'])
|
||||||
|
|
||||||
|
recipe['yeast'].update({
|
||||||
|
'type': 'Liquid',
|
||||||
|
'lab': 'Test',
|
||||||
|
'code': 'Test',
|
||||||
|
'flocculation': 'Low',
|
||||||
|
'min_temperature': '65',
|
||||||
|
'max_temperature': '68',
|
||||||
|
'abv_tolerance': '15'
|
||||||
|
})
|
||||||
|
with app.app_context():
|
||||||
|
form = RecipeForm()
|
||||||
|
form.copyfrom(recipe)
|
||||||
|
assert form.yeast.form.type.data == recipe['yeast']['type']
|
||||||
|
assert form.yeast.form.lab.data == recipe['yeast']['lab']
|
||||||
|
assert form.yeast.form.code.data == recipe['yeast']['code']
|
||||||
|
assert form.yeast.form.flocculation.data == recipe['yeast']['flocculation']
|
||||||
|
assert form.yeast.form.min_temperature.data == \
|
||||||
|
Decimal(recipe['yeast']['min_temperature'])
|
||||||
|
assert form.yeast.form.max_temperature.data == \
|
||||||
|
Decimal(recipe['yeast']['max_temperature'])
|
||||||
|
assert form.yeast.form.abv_tolerance.data == \
|
||||||
|
Decimal(recipe['yeast']['abv_tolerance'])
|
||||||
|
|
||||||
|
recipe['mash'] = {
|
||||||
|
'name': 'Test',
|
||||||
|
'steps': [{
|
||||||
|
'name': 'Infusion',
|
||||||
|
'type': 'Infusion',
|
||||||
|
'temp': '152',
|
||||||
|
'time': '60'
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
with app.app_context():
|
||||||
|
form = RecipeForm()
|
||||||
|
form.copyfrom(recipe)
|
||||||
|
assert form.mash.form.name.data == recipe['mash']['name']
|
||||||
|
assert len(form.mash.form.steps) == len(recipe['mash']['steps'])
|
||||||
|
assert form.mash.form.steps[0].form.name.data == \
|
||||||
|
recipe['mash']['steps'][0]['name']
|
||||||
|
assert form.mash.form.steps[0].form.type.data == \
|
||||||
|
recipe['mash']['steps'][0]['type']
|
||||||
|
assert form.mash.form.steps[0].form.temp.data == \
|
||||||
|
Decimal(recipe['mash']['steps'][0]['temp'])
|
||||||
|
assert form.mash.form.steps[0].form.time.data == \
|
||||||
|
Decimal(recipe['mash']['steps'][0]['time'])
|
||||||
|
|
||||||
|
recipe['mash']['steps'][0]['amount'] = '3.5'
|
||||||
|
with app.app_context():
|
||||||
|
form = RecipeForm()
|
||||||
|
form.copyfrom(recipe)
|
||||||
|
assert form.mash.form.steps[0].form.amount.data == \
|
||||||
|
Decimal(recipe['mash']['steps'][0]['amount'])
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue