mirror of
https://github.com/shouptech/humulus.git
synced 2026-02-03 13:49:41 +00:00
247 lines
7.1 KiB
Python
247 lines
7.1 KiB
Python
# 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.
|
|
|
|
import xml.etree.ElementTree as ET
|
|
|
|
from humulus.styles import import_styles, sub_to_doc, get_styles_list
|
|
|
|
COMPLETE_STYLE = """<subcategory id="1A">
|
|
<name>Test Style</name>
|
|
<aroma>Smelly</aroma>
|
|
<appearance>Good looking</appearance>
|
|
<flavor>Good tasting</flavor>
|
|
<mouthfeel>Good feeling</mouthfeel>
|
|
<impression>Refreshing</impression>
|
|
<comments>Comments</comments>
|
|
<history>Old</history>
|
|
<ingredients>Grains, Hops, and Water</ingredients>
|
|
<comparison>Comparison</comparison>
|
|
<examples>Examples</examples>
|
|
<tags>one, two</tags>
|
|
<stats>
|
|
<ibu flexible="false">
|
|
<low>1</low>
|
|
<high>2</high>
|
|
</ibu>
|
|
<og flexible="false">
|
|
<low>1.010</low>
|
|
<high>1.020</high>
|
|
</og>
|
|
<fg flexible="false">
|
|
<low>1.000</low>
|
|
<high>1.010</high>
|
|
</fg>
|
|
<srm flexible="false">
|
|
<low>1</low>
|
|
<high>2</high>
|
|
</srm>
|
|
<abv flexible="false">
|
|
<low>1</low>
|
|
<high>2</high>
|
|
</abv>
|
|
</stats>
|
|
</subcategory>
|
|
"""
|
|
|
|
INCOMPLETE_STYLE = """<subcategory id="2B">
|
|
<name>Test Style</name>
|
|
<aroma>Smelly</aroma>
|
|
<appearance>Good looking</appearance>
|
|
<flavor>Good tasting</flavor>
|
|
<mouthfeel>Good feeling</mouthfeel>
|
|
<impression>Refreshing</impression>
|
|
</subcategory>
|
|
"""
|
|
|
|
TEST_XML = """<?xml version="1.0" encoding="UTF-8"?>
|
|
<styleguide>
|
|
<class type="beer">
|
|
<category id="1">
|
|
<subcategory id="1A">
|
|
<name>Test Style</name>
|
|
<aroma>Smelly</aroma>
|
|
<appearance>Good looking</appearance>
|
|
<flavor>Good tasting</flavor>
|
|
<mouthfeel>Good feeling</mouthfeel>
|
|
<impression>Refreshing</impression>
|
|
</subcategory>
|
|
</category>
|
|
</class>
|
|
</styleguide>
|
|
"""
|
|
|
|
|
|
def test_sub_to_doc():
|
|
assert sub_to_doc(ET.fromstring(COMPLETE_STYLE)) == {
|
|
"_id": "1A",
|
|
"$type": "style",
|
|
"name": "Test Style",
|
|
"aroma": "Smelly",
|
|
"appearance": "Good looking",
|
|
"flavor": "Good tasting",
|
|
"mouthfeel": "Good feeling",
|
|
"impression": "Refreshing",
|
|
"comments": "Comments",
|
|
"history": "Old",
|
|
"ingredients": "Grains, Hops, and Water",
|
|
"comparison": "Comparison",
|
|
"examples": "Examples",
|
|
"tags": ["one", "two"],
|
|
"ibu": {"low": "1", "high": "2"},
|
|
"og": {"low": "1.010", "high": "1.020"},
|
|
"fg": {"low": "1.000", "high": "1.010"},
|
|
"srm": {"low": "1", "high": "2"},
|
|
"abv": {"low": "1", "high": "2"},
|
|
}
|
|
|
|
assert sub_to_doc(ET.fromstring(INCOMPLETE_STYLE)) == {
|
|
"_id": "2B",
|
|
"$type": "style",
|
|
"name": "Test Style",
|
|
"aroma": "Smelly",
|
|
"appearance": "Good looking",
|
|
"flavor": "Good tasting",
|
|
"mouthfeel": "Good feeling",
|
|
"impression": "Refreshing",
|
|
"ibu": {"low": "0", "high": "100"},
|
|
"og": {"low": "1.0", "high": "1.2"},
|
|
"fg": {"low": "1.0", "high": "1.2"},
|
|
"srm": {"low": "0", "high": "100"},
|
|
"abv": {"low": "0", "high": "100"},
|
|
}
|
|
|
|
|
|
def test_import_styles(monkeypatch):
|
|
class PutRecorder:
|
|
doc = None
|
|
|
|
class MockDB:
|
|
db = {}
|
|
|
|
def fake_get_db():
|
|
return MockDB.db
|
|
|
|
def fake_put_doc(doc):
|
|
PutRecorder.doc = doc
|
|
|
|
def fake_requests_get(url):
|
|
class TestXML:
|
|
text = TEST_XML
|
|
|
|
return TestXML
|
|
|
|
monkeypatch.setattr("requests.get", fake_requests_get)
|
|
monkeypatch.setattr("humulus.styles.get_db", fake_get_db)
|
|
monkeypatch.setattr("humulus.styles.put_doc", fake_put_doc)
|
|
|
|
import_styles(None)
|
|
assert PutRecorder.doc == {
|
|
"$type": "style",
|
|
"_id": "1A",
|
|
"abv": {"high": "100", "low": "0"},
|
|
"appearance": "Good looking",
|
|
"aroma": "Smelly",
|
|
"fg": {"high": "1.2", "low": "1.0"},
|
|
"flavor": "Good tasting",
|
|
"ibu": {"high": "100", "low": "0"},
|
|
"impression": "Refreshing",
|
|
"mouthfeel": "Good feeling",
|
|
"name": "Test Style",
|
|
"og": {"high": "1.2", "low": "1.0"},
|
|
"srm": {"high": "100", "low": "0"},
|
|
}
|
|
|
|
MockDB.db = {"1A": ""}
|
|
PutRecorder.doc = None
|
|
import_styles(None)
|
|
assert PutRecorder.doc is None
|
|
|
|
|
|
def test_import_command(runner, monkeypatch):
|
|
class Recorder:
|
|
called = False
|
|
|
|
def fake_import_styles(url):
|
|
Recorder.called = True
|
|
|
|
monkeypatch.setattr("humulus.styles.import_styles", fake_import_styles)
|
|
result = runner.invoke(args=["import-styles"])
|
|
assert Recorder.called
|
|
assert "Imported BJCP styles." in result.output
|
|
|
|
|
|
def test_get_styles_choices(app):
|
|
"""Test success in getting list of styles."""
|
|
with app.app_context():
|
|
styles = get_styles_list()
|
|
assert styles == [["", ""], ["1A", "1A Test Style"]]
|
|
|
|
|
|
def test_index(auth, client):
|
|
"""Test success in retrieving index."""
|
|
# Test not logged in
|
|
response = client.get("/styles/")
|
|
assert response.status_code == 302
|
|
|
|
# Login and test get
|
|
auth.login()
|
|
response = client.get("/styles/")
|
|
assert response.status_code == 200
|
|
assert b"1A" in response.data
|
|
assert b"Test Style" in response.data
|
|
|
|
# Test for bad request
|
|
response = client.get("/styles/?sort_by=foobar")
|
|
assert response.status_code == 400
|
|
|
|
|
|
def test_info(auth, client):
|
|
"""Test success in retrieving a style's info page"""
|
|
# Test not logged in
|
|
response = client.get("/styles/info/1A")
|
|
assert response.status_code == 302
|
|
|
|
# Login and test
|
|
auth.login()
|
|
response = client.get("/styles/info/1A")
|
|
assert response.status_code == 200
|
|
assert b"1A" in response.data
|
|
assert b"Test Style" in response.data
|
|
|
|
|
|
def test_recipes(client):
|
|
"""Test success in retrieving list of recipes matching style."""
|
|
response = client.get("/styles/info/1A/recipes")
|
|
assert response.status_code == 200
|
|
assert b"Awesome Beer" in response.data
|
|
|
|
|
|
def test_info_json(auth, client):
|
|
"""Test success in retrieving a style's json document."""
|
|
# Test not logged in
|
|
response = client.get("/styles/info/1A/json")
|
|
assert response.status_code == 302
|
|
|
|
# Login and test
|
|
auth.login()
|
|
response = client.get("/styles/info/1A/json")
|
|
assert response.status_code == 200
|
|
assert response.is_json
|
|
assert response.get_json()["name"] == "Test Style"
|
|
|
|
# Test for specs only
|
|
response = client.get("/styles/info/1A/json?specs=y")
|
|
assert response.status_code == 200
|
|
assert response.is_json
|
|
assert "name" not in response.get_json()
|