mirror of
https://github.com/shouptech/humulus.git
synced 2026-02-03 14:49:42 +00:00
Add complete recipe update capability
This commit is contained in:
parent
6233b089cf
commit
5f7639232c
5 changed files with 290 additions and 141 deletions
|
|
@ -30,7 +30,7 @@ bp = Blueprint('recipes', __name__, url_prefix='/recipes')
|
|||
class FermentableForm(Form):
|
||||
"""Form for fermentables.
|
||||
|
||||
CSRF is disabled for this subform (using `Form as parent class) because it
|
||||
CSRF is disabled for this form.yeast.form (using `Form as parent class) because it
|
||||
is never used by itself.
|
||||
"""
|
||||
name = StringField('Name', validators=[DataRequired()])
|
||||
|
|
@ -60,7 +60,7 @@ class FermentableForm(Form):
|
|||
class HopForm(Form):
|
||||
"""Form for hops.
|
||||
|
||||
CSRF is disabled for this subform (using `Form as parent class) because it
|
||||
CSRF is disabled for this form.yeast.form (using `Form as parent class) because it
|
||||
is never used by itself.
|
||||
"""
|
||||
name = StringField('Name', validators=[DataRequired()])
|
||||
|
|
@ -89,7 +89,7 @@ class HopForm(Form):
|
|||
class YeastForm(Form):
|
||||
"""Form for yeast.
|
||||
|
||||
CSRF is disabled for this subform (using `Form as parent class) because it
|
||||
CSRF is disabled for this form.yeast.form (using `Form as parent class) because it
|
||||
is never used by itself.
|
||||
"""
|
||||
name = StringField('Name', validators=[Optional()])
|
||||
|
|
@ -173,10 +173,8 @@ class RecipeForm(FlaskForm):
|
|||
'notes': self.notes.data
|
||||
}
|
||||
|
||||
if len(self.fermentables) > 0:
|
||||
recipe['fermentables'] = [f.doc for f in self.fermentables]
|
||||
if len(self.hops) > 0:
|
||||
recipe['hops'] = [h.doc for h in self.hops]
|
||||
recipe['fermentables'] = [f.doc for f in self.fermentables]
|
||||
recipe['hops'] = [h.doc for h in self.hops]
|
||||
if self.yeast.doc['name']:
|
||||
recipe['yeast'] = self.yeast.doc
|
||||
return recipe
|
||||
|
|
@ -208,9 +206,8 @@ def delete(id):
|
|||
@bp.route('/update/<id>', methods=('GET', 'POST'))
|
||||
def update(id):
|
||||
# Get the recipe from the database and validate it is the same revision
|
||||
recipe = get_doc_or_404(id)
|
||||
|
||||
form = RecipeForm()
|
||||
recipe = get_doc_or_404(id)
|
||||
if form.validate_on_submit():
|
||||
if recipe['_rev'] != request.args.get('rev', None):
|
||||
flash(
|
||||
|
|
@ -218,7 +215,7 @@ def update(id):
|
|||
'Update conflict for recipe: {}. '
|
||||
'Your changes have been lost.'.format(recipe['name'])
|
||||
),
|
||||
'error'
|
||||
'danger'
|
||||
)
|
||||
return redirect(url_for('recipes.info', id=id))
|
||||
# Copy values from submitted form to the existing recipe and save
|
||||
|
|
@ -228,5 +225,61 @@ def update(id):
|
|||
|
||||
flash('Updated recipe: {}'.format(form.name.data), 'success')
|
||||
return redirect(url_for('recipes.info', id=id))
|
||||
else:
|
||||
# Copy the recipe's data into the form.
|
||||
# Is there an easier way to do this?
|
||||
form.name.data = recipe['name']
|
||||
form.efficiency.data = Decimal(recipe['efficiency'])
|
||||
form.volume.data = Decimal(recipe['volume'])
|
||||
form.notes.data = recipe['notes']
|
||||
|
||||
return render_template('recipes/update.html', form=form)
|
||||
for fermentable in recipe['fermentables']:
|
||||
form.fermentables.append_entry({
|
||||
'name': fermentable['name'],
|
||||
'type': fermentable['type'],
|
||||
'amount': Decimal(fermentable['amount']),
|
||||
'ppg': Decimal(fermentable['ppg']),
|
||||
'color': Decimal(fermentable['color'])
|
||||
})
|
||||
|
||||
for hop in recipe['hops']:
|
||||
form.hops.append_entry({
|
||||
'name': hop['name'],
|
||||
'use': hop['use'],
|
||||
'alpha': Decimal(hop['alpha']),
|
||||
'duration': Decimal(hop['duration']),
|
||||
'amount': Decimal(hop['amount']),
|
||||
})
|
||||
|
||||
if 'yeast' in recipe:
|
||||
yeast = recipe['yeast']
|
||||
form.yeast.form.name.data = yeast['name']
|
||||
form.yeast.form.low_attenuation.data = (
|
||||
Decimal(yeast['low_attenuation'])
|
||||
)
|
||||
form.yeast.form.high_attenuation.data = (
|
||||
Decimal(yeast['high_attenuation'])
|
||||
)
|
||||
if 'type' in yeast:
|
||||
form.yeast.form.type.data = yeast['type']
|
||||
if 'lab' in yeast:
|
||||
form.yeast.form.lab.data = yeast['lab']
|
||||
if 'code' in yeast:
|
||||
form.yeast.form.code.data = yeast['code']
|
||||
if 'flocculation' in yeast:
|
||||
form.yeast.form.flocculation.data = yeast['flocculation']
|
||||
if 'min_temperature' in yeast:
|
||||
form.yeast.form.min_temperature.data = (
|
||||
Decimal(yeast['min_temperature'])
|
||||
)
|
||||
if 'max_temperature' in yeast:
|
||||
form.yeast.form.max_temperature.data = (
|
||||
Decimal(yeast['max_temperature'])
|
||||
)
|
||||
if 'abv_tolerance' in yeast:
|
||||
form.yeast.form.abv_tolerance.data = (
|
||||
Decimal(yeast['abv_tolerance'])
|
||||
)
|
||||
|
||||
return render_template('recipes/update.html', form=form,
|
||||
id=id, rev=recipe['_rev'])
|
||||
|
|
|
|||
130
src/humulus/templates/recipes/_macros.html
Normal file
130
src/humulus/templates/recipes/_macros.html
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
{#-
|
||||
Copyright 2019 Mike Shoup
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-#}
|
||||
{% from "_macros.html" import render_field_with_errors %}
|
||||
|
||||
{#
|
||||
Used to render a form for creating/updating a recipe
|
||||
#}
|
||||
{% macro render_recipe_form(form, action_url, button_content) %}
|
||||
<form method="POST" action="{{ action_url }}">
|
||||
{{ form.hidden_tag() }}
|
||||
{#-
|
||||
Recipe Details
|
||||
-#}
|
||||
<div class="row">
|
||||
<div class="col-sm-6">{{ render_field_with_errors(form.name) }}</div>
|
||||
<div class="col-sm-3">{{ render_field_with_errors(form.efficiency) }}</div>
|
||||
<div class="col-sm-3">{{ render_field_with_errors(form.volume) }}</div>
|
||||
</div>
|
||||
{#-
|
||||
Fermentable Ingredients
|
||||
-#}
|
||||
<div class="row"><div class="col"><h3>Fermentables</h3></div></div>
|
||||
<div id="ferms" data-length="{{ form.fermentables|length }}">
|
||||
{% for fermentable in form.fermentables %}
|
||||
<div class="border pl-2 pr-2 pt-1 pb-1 ferm-form" data-index="{{ loop.index0 }}">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
{{ render_field_with_errors(fermentable.form.name, 'form-control-sm') }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm">{{ render_field_with_errors(fermentable.form.type, 'form-control-sm') }}</div>
|
||||
<div class="col-sm">{{ render_field_with_errors(fermentable.form.amount, 'form-control-sm') }}</div>
|
||||
<div class="col-sm">{{ render_field_with_errors(fermentable.form.ppg, 'form-control-sm') }}</div>
|
||||
<div class="col-sm">{{ render_field_with_errors(fermentable.form.color, 'form-control-sm') }}</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<button type="button" class="float-right btn btn-sm btn-outline-danger rem-ferm">Remove fermentable</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="row pt-1 pb-1">
|
||||
<div class="col">
|
||||
<button type="button" id="add-ferm" class="btn btn-secondary btn-sm">Add a fermentable</button>
|
||||
</div>
|
||||
</div>
|
||||
{#-
|
||||
Hop ingredients
|
||||
-#}
|
||||
<div class="row"><div class="col"><h3>Hops</h3></div></div>
|
||||
<div id="hops" data-length="{{ form.hops|length }}">
|
||||
{% for hop in form.hops %}
|
||||
<div class="border pl-2 pr-2 pt-1 pb-1 hop-form" data-index="{{ loop.index0 }}">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
{{ render_field_with_errors(hop.form.name, 'form-control-sm') }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm">{{ render_field_with_errors(hop.form.use, 'form-control-sm') }}</div>
|
||||
<div class="col-sm">{{ render_field_with_errors(hop.form.alpha, 'form-control-sm') }}</div>
|
||||
<div class="col-sm">{{ render_field_with_errors(hop.form.duration, 'form-control-sm') }}</div>
|
||||
<div class="col-sm">{{ render_field_with_errors(hop.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-hop">Remove Hop</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="row pt-1 pb-1">
|
||||
<div class="col">
|
||||
<button type="button" id="add-hop" class="btn btn-secondary btn-sm">Add a hop</button>
|
||||
</div>
|
||||
</div>
|
||||
{#-
|
||||
Recipe Yeast
|
||||
-#}
|
||||
<div class="row"><div class="col"><h3>Yeast</h3></div></div>
|
||||
<div id="yeast">
|
||||
<div class="border pl-2 pr-2 pt-1 pb-1 yeast-form">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">{{ render_field_with_errors(form.yeast.form.name, 'form-control-sm') }}</div>
|
||||
<div class="col-sm-2">{{ render_field_with_errors(form.yeast.form.type, 'form-control-sm') }}</div>
|
||||
<div class="col-sm-2">{{ render_field_with_errors(form.yeast.form.lab, 'form-control-sm') }}</div>
|
||||
<div class="col-sm-2">{{ render_field_with_errors(form.yeast.form.code, 'form-control-sm') }}</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm">{{ render_field_with_errors(form.yeast.form.low_attenuation, 'form-control-sm') }}</div>
|
||||
<div class="col-sm">{{ render_field_with_errors(form.yeast.form.high_attenuation, 'form-control-sm') }}</div>
|
||||
<div class="col-sm">{{ render_field_with_errors(form.yeast.form.flocculation, 'form-control-sm') }}</div>
|
||||
<div class="col-sm">{{ render_field_with_errors(form.yeast.form.min_temperature, 'form-control-sm') }}</div>
|
||||
<div class="col-sm">{{ render_field_with_errors(form.yeast.form.max_temperature, 'form-control-sm') }}</div>
|
||||
<div class="col-sm">{{ render_field_with_errors(form.yeast.form.abv_tolerance, 'form-control-sm') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{#-
|
||||
Recipe Notes
|
||||
-#}
|
||||
<div class="row">
|
||||
<div class="col">{{ render_field_with_errors(form.notes) }}</div>
|
||||
</div>
|
||||
{#-
|
||||
Submit recipe
|
||||
-#}
|
||||
<div class="row">
|
||||
<div class="col"><button type="submit" class="btn btn-primary">{{ button_content }}</button></div>
|
||||
</div>
|
||||
</form>
|
||||
<script src="{{ url_for('static', filename='recipes.js') }}"></script>
|
||||
{% endmacro %}
|
||||
|
|
@ -13,119 +13,12 @@
|
|||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-#}
|
||||
{% from "_macros.html" import render_field_with_errors %}
|
||||
{% from "recipes/_macros.html" import render_recipe_form %}
|
||||
|
||||
{% extends '_base.html' %}
|
||||
{% block title %}Create Recipe{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="row"><h1>Create a new recipe</h1></div>
|
||||
<form method="POST" action="{{ url_for('recipes.create') }}">
|
||||
{{ form.hidden_tag() }}
|
||||
{#-
|
||||
Recipe Details
|
||||
-#}
|
||||
<div class="row">
|
||||
<div class="col-sm-6">{{ render_field_with_errors(form.name) }}</div>
|
||||
<div class="col-sm-3">{{ render_field_with_errors(form.efficiency) }}</div>
|
||||
<div class="col-sm-3">{{ render_field_with_errors(form.volume) }}</div>
|
||||
</div>
|
||||
{#-
|
||||
Fermentable Ingredients
|
||||
-#}
|
||||
<div class="row"><div class="col"><h3>Fermentables</h3></div></div>
|
||||
<div id="ferms" data-length="{{ form.fermentables|length }}">
|
||||
{% for fermentable in form.fermentables %}
|
||||
<div class="border pl-2 pr-2 pt-1 pb-1 ferm-form" data-index="{{ loop.index0 }}">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
{{ render_field_with_errors(fermentable.form.name, 'form-control-sm') }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm">{{ render_field_with_errors(fermentable.form.type, 'form-control-sm') }}</div>
|
||||
<div class="col-sm">{{ render_field_with_errors(fermentable.form.amount, 'form-control-sm') }}</div>
|
||||
<div class="col-sm">{{ render_field_with_errors(fermentable.form.ppg, 'form-control-sm') }}</div>
|
||||
<div class="col-sm">{{ render_field_with_errors(fermentable.form.color, 'form-control-sm') }}</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<button type="button" class="float-right btn btn-sm btn-outline-danger rem-ferm">Remove fermentable</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="row pt-1 pb-1">
|
||||
<div class="col">
|
||||
<button type="button" id="add-ferm" class="btn btn-secondary btn-sm">Add a fermentable</button>
|
||||
</div>
|
||||
</div>
|
||||
{#-
|
||||
Hop ingredients
|
||||
-#}
|
||||
<div class="row"><div class="col"><h3>Hops</h3></div></div>
|
||||
<div id="hops" data-length="{{ form.hops|length }}">
|
||||
{% for hop in form.hops %}
|
||||
<div class="border pl-2 pr-2 pt-1 pb-1 hop-form" data-index="{{ loop.index0 }}">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
{{ render_field_with_errors(hop.form.name, 'form-control-sm') }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm">{{ render_field_with_errors(hop.form.use, 'form-control-sm') }}</div>
|
||||
<div class="col-sm">{{ render_field_with_errors(hop.form.alpha, 'form-control-sm') }}</div>
|
||||
<div class="col-sm">{{ render_field_with_errors(hop.form.duration, 'form-control-sm') }}</div>
|
||||
<div class="col-sm">{{ render_field_with_errors(hop.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-hop">Remove Hop</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="row pt-1 pb-1">
|
||||
<div class="col">
|
||||
<button type="button" id="add-hop" class="btn btn-secondary btn-sm">Add a hop</button>
|
||||
</div>
|
||||
</div>
|
||||
{#-
|
||||
Recipe Yeast
|
||||
-#}
|
||||
<div class="row"><div class="col"><h3>Yeast</h3></div></div>
|
||||
<div id="yeast">
|
||||
<div class="border pl-2 pr-2 pt-1 pb-1 yeast-form">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">{{ render_field_with_errors(form.yeast.form.name, 'form-control-sm') }}</div>
|
||||
<div class="col-sm-2">{{ render_field_with_errors(form.yeast.form.type, 'form-control-sm') }}</div>
|
||||
<div class="col-sm-2">{{ render_field_with_errors(form.yeast.form.lab, 'form-control-sm') }}</div>
|
||||
<div class="col-sm-2">{{ render_field_with_errors(form.yeast.form.code, 'form-control-sm') }}</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm">{{ render_field_with_errors(form.yeast.form.low_attenuation, 'form-control-sm') }}</div>
|
||||
<div class="col-sm">{{ render_field_with_errors(form.yeast.form.high_attenuation, 'form-control-sm') }}</div>
|
||||
<div class="col-sm">{{ render_field_with_errors(form.yeast.form.flocculation, 'form-control-sm') }}</div>
|
||||
<div class="col-sm">{{ render_field_with_errors(form.yeast.form.min_temperature, 'form-control-sm') }}</div>
|
||||
<div class="col-sm">{{ render_field_with_errors(form.yeast.form.max_temperature, 'form-control-sm') }}</div>
|
||||
<div class="col-sm">{{ render_field_with_errors(form.yeast.form.abv_tolerance, 'form-control-sm') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{#-
|
||||
Recipe Notes
|
||||
-#}
|
||||
<div class="row">
|
||||
<div class="col">{{ render_field_with_errors(form.notes) }}</div>
|
||||
</div>
|
||||
{#-
|
||||
Submit recipe
|
||||
-#}
|
||||
<div class="row">
|
||||
<div class="col"><button type="submit" class="btn btn-primary">Create Recipe</button></div>
|
||||
</div>
|
||||
</form>
|
||||
<script src="{{ url_for('static', filename='recipes.js') }}"></script>
|
||||
{{ render_recipe_form(form, url_for('recipes.create'), 'Create recipe') }}
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
{#-
|
||||
Copyright 2019 Mike Shoup
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-#}
|
||||
{% from "recipes/_macros.html" import render_recipe_form %}
|
||||
|
||||
{% extends '_base.html' %}
|
||||
{% block title %}Update | {{ form.name.data }}{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="row"><h1>{{ form.name.data }}</h1></div>
|
||||
{{ render_recipe_form(form, url_for('recipes.update', id=id, rev=rev), 'Update recipe') }}
|
||||
{% endblock %}
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
from decimal import Decimal
|
||||
|
||||
from humulus.couch import get_db, get_doc
|
||||
from humulus.couch import get_db, get_doc, put_doc
|
||||
from humulus.recipes import FermentableForm, HopForm, RecipeForm, YeastForm
|
||||
|
||||
|
||||
|
|
@ -45,37 +45,84 @@ def test_create(client, app):
|
|||
|
||||
def test_update(client, app):
|
||||
"""Test success in updating a recipe document."""
|
||||
# Test GET
|
||||
id = 'awesome-lager'
|
||||
response = client.get('/recipes/update/{}'.format(id))
|
||||
|
||||
# Get the doc, test a change, then post the update
|
||||
with app.app_context():
|
||||
data = get_doc(id)
|
||||
# Remove values that should not be posted with the data
|
||||
rev = data.pop('_rev') # Save the revision, will be used later
|
||||
data.pop('_id')
|
||||
# Make a change to the data
|
||||
data['name'] = '{} TEST'.format(data['name'])
|
||||
doc = put_doc({
|
||||
'_id': 'test-update',
|
||||
'name': 'Test Update',
|
||||
'efficiency': '60',
|
||||
'volume': '5.5',
|
||||
'notes': 'This is a test',
|
||||
'fermentables': [],
|
||||
'hops': []
|
||||
})
|
||||
|
||||
# Test valid response
|
||||
response = client.post('/recipes/update/{}'.format(id),
|
||||
query_string={'rev': rev}, data=data)
|
||||
# Test GET
|
||||
response = client.get('/recipes/update/test-update')
|
||||
assert response.status_code == 200
|
||||
assert b'Test Update' in response.data
|
||||
|
||||
# Make a change to the doc
|
||||
data = {
|
||||
'name': 'New Name',
|
||||
'efficiency': '60',
|
||||
'volume': '5.5',
|
||||
'notes': 'This is a test'
|
||||
}
|
||||
response = client.post('/recipes/update/test-update',
|
||||
query_string={'rev': doc['_rev']}, data=data)
|
||||
assert response.status_code == 302
|
||||
with client.session_transaction() as session:
|
||||
flash_message = dict(session['_flashes']).get('error')
|
||||
flash_message = dict(session['_flashes']).pop('danger', None)
|
||||
assert flash_message is None
|
||||
# Validate document update
|
||||
with app.app_context():
|
||||
updated = get_doc(id)
|
||||
assert updated['name'] == data['name']
|
||||
updated = get_doc('test-update')
|
||||
assert updated['name'] == 'New Name'
|
||||
|
||||
# Test form is filled correctly with ingredients
|
||||
with app.app_context():
|
||||
doc = put_doc({
|
||||
'_id': 'test-update-1',
|
||||
'name': 'Test Update With Ingredients',
|
||||
'efficiency': '60',
|
||||
'volume': '5.5',
|
||||
'notes': 'This is a test',
|
||||
'fermentables': [{
|
||||
'name': '2-row',
|
||||
'type': 'Grain',
|
||||
'amount': '5',
|
||||
'ppg': '37',
|
||||
'color': '1.8'
|
||||
}],
|
||||
'hops': [{
|
||||
'name': 'Nugget',
|
||||
'use': 'Boil',
|
||||
'alpha': '5.5',
|
||||
'duration': '60',
|
||||
'amount': '1'
|
||||
}],
|
||||
'yeast': {
|
||||
'name': 'California Ale',
|
||||
'low_attenuation': '70',
|
||||
'high_attenuation': '80',
|
||||
'type': 'Liquid',
|
||||
'lab': 'Inland Island',
|
||||
'code': 'INIS-001',
|
||||
'flocculation': 'Medium',
|
||||
'min_temperature': '60',
|
||||
'max_temperature': '70',
|
||||
'abv_tolerance': '15'
|
||||
}
|
||||
})
|
||||
response = client.get('/recipes/update/test-update-1')
|
||||
assert b'Test Update With Ingredients' in response.data
|
||||
|
||||
|
||||
# Test response without valid/conflicted rev
|
||||
response = client.post('/recipes/update/{}'.format(id),
|
||||
response = client.post('/recipes/update/test-update',
|
||||
query_string={'rev': ''}, data=data)
|
||||
assert response.status_code == 302
|
||||
with client.session_transaction() as session:
|
||||
flash_message = dict(session['_flashes']).get('error')
|
||||
flash_message = dict(session['_flashes']).pop('danger', None)
|
||||
assert 'Update conflict' in flash_message
|
||||
|
||||
|
||||
|
|
@ -145,6 +192,8 @@ def test_recipe_form_doc(app):
|
|||
'efficiency': '65',
|
||||
'volume': '5.5',
|
||||
'notes': 'This is a test',
|
||||
'fermentables': [],
|
||||
'hops': [],
|
||||
}
|
||||
|
||||
ferm = FermentableForm()
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue