Skip to content

Commit fba5dd0

Browse files
authored
Implement method tag for creating input hidden with PUT or DELETE value (#48)
* fix(__init__.py): import HTMLMiddleware and add method to inject hidden input fields for PUT and DELETE HTTP methods feat(html.py): add HTMLMiddleware class to generate hidden input fields for PUT and DELETE HTTP methods fix(edit.html): replace hidden input field with method('PUT') to inject hidden input field for PUT HTTP method fix(show.html): replace hidden input field with method('DELETE') to inject hidden input field for DELETE HTTP method fix(conftest.py): add message creation and commit to test_client and browser fixtures fix(messages_direct_request_test.py): remove unnecessary expected variable and assert message title directly fix(messages_direct_request_test.py): remove unnecessary message creation and commit, query message by title instead fix(messages_form_test.py): add test to check for presence of hidden input field for PUT HTTP method in edit page fix(messages_form_test.py): add test to check for presence of hidden input field for DELETE HTTP method in show page fix(messages_form_test.py): remove unnecessary message creation and commit, query message by title instead fix(messages_form_test.py): fix test name duplication and update message title in update test fix(messages_form_test.py): fix test name duplication and update message title in delete test * chore: bump version from 2.7.2 to 2.8.1 in __version__.py, pyproject.toml, and version_test.py The version number in the `__version__.py` file, `pyproject.toml` file, and `version_test.py` test case has been updated from 2.7.2 to 2.8.1. This change is made to reflect the new version of the `mvc-flask` package. * refactor(html.py): improve code readability and add docstrings for HTMLMiddleware class and its methods feat(html.py): add method to handle the generation of appropriate HTML based on a given string
1 parent 50b28e3 commit fba5dd0

File tree

10 files changed

+109
-21
lines changed

10 files changed

+109
-21
lines changed

mvc_flask/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from flask.blueprints import Blueprint
55

66
from .router import Router
7+
from .middlewares.html import HTMLMiddleware
78
from .middlewares.http_method_override import (
89
HTTPMethodOverrideMiddleware,
910
CustomRequest,
@@ -23,8 +24,13 @@ def init_app(self, app: Flask = None, path="app"):
2324
app.request_class = CustomRequest
2425
app.wsgi_app = HTTPMethodOverrideMiddleware(app.wsgi_app)
2526

27+
# register blueprint
2628
self.register_blueprint(app)
2729

30+
@app.context_processor
31+
def inject_stage_and_region():
32+
return dict(method=HTMLMiddleware().method)
33+
2834
def register_blueprint(self, app: Flask):
2935
# load routes defined from users
3036
import_module(f"{self.path}.routes")

mvc_flask/__version__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "2.7.2"
1+
__version__ = "2.8.1"

mvc_flask/middlewares/html.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import markupsafe
2+
3+
4+
class HTMLMiddleware:
5+
"""
6+
A middleware class for handling HTML-related operations, specifically for creating hidden input fields
7+
with specific methods (like PUT and DELETE) that are not natively supported by HTML forms.
8+
9+
Methods:
10+
- _input_html: Private method to generate HTML input element.
11+
- _put: Private method to generate a hidden input field for the PUT method.
12+
- _delete: Private method to generate a hidden input field for the DELETE method.
13+
- method: Public method to handle the generation of appropriate HTML based on a given string.
14+
"""
15+
16+
def _input_html(self, input_method):
17+
"""
18+
Generates a hidden HTML input element.
19+
20+
Args:
21+
- input_method (str): The HTTP method to be used (e.g., 'put', 'delete').
22+
23+
Returns:
24+
- str: An HTML string for a hidden input element with the specified method.
25+
"""
26+
return f"<input type='hidden' name='_method' value={input_method.upper()}>"
27+
28+
def _put(self):
29+
"""
30+
Generates a hidden input field for the PUT method.
31+
32+
Returns:
33+
- str: An HTML string for a hidden input element for the PUT method.
34+
"""
35+
return self._input_html("put")
36+
37+
def _delete(self):
38+
"""
39+
Generates a hidden input field for the DELETE method.
40+
41+
Returns:
42+
- str: An HTML string for a hidden input element for the DELETE method.
43+
"""
44+
return self._input_html("delete")
45+
46+
def method(self, string):
47+
"""
48+
Determines the appropriate HTML string to return based on the given method string.
49+
50+
Args:
51+
- string (str): The method string (e.g., 'put', 'delete').
52+
53+
Returns:
54+
- Markup: A markupsafe.Markup object containing the appropriate HTML string.
55+
This object is safe to render directly in templates.
56+
"""
57+
result = {
58+
"put": self._put(),
59+
"delete": self._delete(),
60+
}[string.lower()]
61+
62+
return markupsafe.Markup(result)

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "mvc-flask"
3-
version = "2.7.2"
3+
version = "2.8.1"
44
description = "turn standard Flask into mvc"
55
authors = ["Marcus Pereira <marcus@negros.dev>"]
66

tests/app/views/messages/edit.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
{% block content %}
44

55
<form action="{{ url_for('messages.update', id=1) }}" method="POST">
6-
<input type="hidden" name="_method" value="put">
6+
{{ method('PUT') }}
77

88
<input type="text" name="title" id="title">
99

tests/app/views/messages/show.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
{% block content %}
44

55
<form action="{{ url_for('messages.delete', id=1) }}" method="post">
6-
<input type="hidden" name="_method" value="delete">
6+
{{ method('DELETE') }}
77

88
<input type="submit" value="delete">
99
</form>

tests/conftest.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import pytest
22
from splinter import Browser
33

4+
from tests.app.models.message import Message
45
from tests.app import create_app
56
from tests.app import db
67

@@ -10,6 +11,7 @@ def test_client():
1011
app.testing = True
1112
app_context = app.test_request_context()
1213
app_context.push()
14+
1315
return app
1416

1517

@@ -20,6 +22,10 @@ def client():
2022
with app.test_client() as client:
2123
db.create_all()
2224

25+
message = Message(title="Message One")
26+
db.session.add(message)
27+
db.session.commit()
28+
2329
yield client
2430

2531
db.session.remove()
@@ -33,6 +39,10 @@ def browser():
3339
with app.test_client():
3440
db.create_all()
3541

42+
message = Message(title="Message One")
43+
db.session.add(message)
44+
db.session.commit()
45+
3646
yield Browser("flask", app=app)
3747

3848
db.session.remove()

tests/messages_direct_request_test.py

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,21 @@
99
def test_create_a_message(client):
1010
headers = {"Content-Type": "application/json"}
1111
data = json.dumps({"title": "hello"})
12-
expected = "hello"
1312

1413
res = client.post(url_for("messages.create"), data=data, headers=headers)
1514

1615
assert res.status_code == 201
17-
assert res.json["title"] == expected
18-
assert Message.query.first().title == expected
16+
assert res.json["title"] == "hello"
1917

2018

2119
def test_update_a_message(client):
22-
headers = {"Content-Type": "application/json"}
23-
data = json.dumps({"title": "hello updated"})
24-
message = Message(title="Message One")
20+
message = Message.query.filter_by(title="Message One").first()
2521

26-
db.session.add(message)
27-
db.session.commit()
2822
res = client.put(
29-
url_for("messages.update", id=message.id), data=data, headers=headers
23+
url_for("messages.update", id=message.id),
24+
data=json.dumps({"title": "hello updated"}),
25+
headers={"Content-Type": "application/json"},
3026
)
3127

3228
assert res.json["title"] == "hello updated"
33-
assert Message.query.first().title == "hello updated"
29+
assert message.title == "hello updated"

tests/messages_form_test.py

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,26 @@
44
from tests.app import db
55

66

7+
def test_must_have_put_input_hidden(browser):
8+
message = Message.query.filter_by(title="Message One").first()
9+
10+
browser.visit(url_for("messages.edit", id=message.id))
11+
12+
assert browser.is_element_present_by_name("_method")
13+
assert browser.is_element_present_by_value("PUT")
14+
15+
16+
def test_must_have_put_input_hidden(browser):
17+
message = Message.query.filter_by(title="Message One").first()
18+
19+
browser.visit(url_for("messages.show", id=message.id))
20+
21+
assert browser.is_element_present_by_name("_method")
22+
assert browser.is_element_present_by_value("DELETE")
23+
24+
725
def test_update_message_using_put_http_method(browser):
8-
message = Message(title="Message One")
9-
db.session.add(message)
10-
db.session.commit()
26+
message = Message.query.filter_by(title="Message One").first()
1127

1228
browser.visit(url_for("messages.edit", id=message.id))
1329
browser.fill("title", "Message updated")
@@ -17,9 +33,7 @@ def test_update_message_using_put_http_method(browser):
1733

1834

1935
def test_delete_message_using_put_http_method(browser):
20-
message = Message(title="Message One")
21-
db.session.add(message)
22-
db.session.commit()
36+
message = Message.query.filter_by(title="Message One").first()
2337

2438
browser.visit(url_for("messages.show", id=message.id))
2539
browser.find_by_value("delete").click()

tests/version_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22

33

44
def test_mvc_flask_currently_version():
5-
__version__ == "2.7.2"
5+
__version__ == "2.8.1"

0 commit comments

Comments
 (0)