Skip to content

Implement method tag for creating input hidden with PUT or DELETE value #48

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Nov 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions mvc_flask/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from flask.blueprints import Blueprint

from .router import Router
from .middlewares.html import HTMLMiddleware
from .middlewares.http_method_override import (
HTTPMethodOverrideMiddleware,
CustomRequest,
Expand All @@ -23,8 +24,13 @@ def init_app(self, app: Flask = None, path="app"):
app.request_class = CustomRequest
app.wsgi_app = HTTPMethodOverrideMiddleware(app.wsgi_app)

# register blueprint
self.register_blueprint(app)

@app.context_processor
def inject_stage_and_region():
return dict(method=HTMLMiddleware().method)

def register_blueprint(self, app: Flask):
# load routes defined from users
import_module(f"{self.path}.routes")
Expand Down
2 changes: 1 addition & 1 deletion mvc_flask/__version__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "2.7.2"
__version__ = "2.8.1"
62 changes: 62 additions & 0 deletions mvc_flask/middlewares/html.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import markupsafe


class HTMLMiddleware:
"""
A middleware class for handling HTML-related operations, specifically for creating hidden input fields
with specific methods (like PUT and DELETE) that are not natively supported by HTML forms.

Methods:
- _input_html: Private method to generate HTML input element.
- _put: Private method to generate a hidden input field for the PUT method.
- _delete: Private method to generate a hidden input field for the DELETE method.
- method: Public method to handle the generation of appropriate HTML based on a given string.
"""

def _input_html(self, input_method):
"""
Generates a hidden HTML input element.

Args:
- input_method (str): The HTTP method to be used (e.g., 'put', 'delete').

Returns:
- str: An HTML string for a hidden input element with the specified method.
"""
return f"<input type='hidden' name='_method' value={input_method.upper()}>"

def _put(self):
"""
Generates a hidden input field for the PUT method.

Returns:
- str: An HTML string for a hidden input element for the PUT method.
"""
return self._input_html("put")

def _delete(self):
"""
Generates a hidden input field for the DELETE method.

Returns:
- str: An HTML string for a hidden input element for the DELETE method.
"""
return self._input_html("delete")

def method(self, string):
"""
Determines the appropriate HTML string to return based on the given method string.

Args:
- string (str): The method string (e.g., 'put', 'delete').

Returns:
- Markup: A markupsafe.Markup object containing the appropriate HTML string.
This object is safe to render directly in templates.
"""
result = {
"put": self._put(),
"delete": self._delete(),
}[string.lower()]

return markupsafe.Markup(result)
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "mvc-flask"
version = "2.7.2"
version = "2.8.1"
description = "turn standard Flask into mvc"
authors = ["Marcus Pereira <marcus@negros.dev>"]

Expand Down
2 changes: 1 addition & 1 deletion tests/app/views/messages/edit.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
{% block content %}

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

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

Expand Down
2 changes: 1 addition & 1 deletion tests/app/views/messages/show.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
{% block content %}

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

<input type="submit" value="delete">
</form>
Expand Down
10 changes: 10 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import pytest
from splinter import Browser

from tests.app.models.message import Message
from tests.app import create_app
from tests.app import db

Expand All @@ -10,6 +11,7 @@ def test_client():
app.testing = True
app_context = app.test_request_context()
app_context.push()

return app


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

message = Message(title="Message One")
db.session.add(message)
db.session.commit()

yield client

db.session.remove()
Expand All @@ -33,6 +39,10 @@ def browser():
with app.test_client():
db.create_all()

message = Message(title="Message One")
db.session.add(message)
db.session.commit()

yield Browser("flask", app=app)

db.session.remove()
Expand Down
16 changes: 6 additions & 10 deletions tests/messages_direct_request_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,21 @@
def test_create_a_message(client):
headers = {"Content-Type": "application/json"}
data = json.dumps({"title": "hello"})
expected = "hello"

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

assert res.status_code == 201
assert res.json["title"] == expected
assert Message.query.first().title == expected
assert res.json["title"] == "hello"


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

db.session.add(message)
db.session.commit()
res = client.put(
url_for("messages.update", id=message.id), data=data, headers=headers
url_for("messages.update", id=message.id),
data=json.dumps({"title": "hello updated"}),
headers={"Content-Type": "application/json"},
)

assert res.json["title"] == "hello updated"
assert Message.query.first().title == "hello updated"
assert message.title == "hello updated"
26 changes: 20 additions & 6 deletions tests/messages_form_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,26 @@
from tests.app import db


def test_must_have_put_input_hidden(browser):
message = Message.query.filter_by(title="Message One").first()

browser.visit(url_for("messages.edit", id=message.id))

assert browser.is_element_present_by_name("_method")
assert browser.is_element_present_by_value("PUT")


def test_must_have_put_input_hidden(browser):
message = Message.query.filter_by(title="Message One").first()

browser.visit(url_for("messages.show", id=message.id))

assert browser.is_element_present_by_name("_method")
assert browser.is_element_present_by_value("DELETE")


def test_update_message_using_put_http_method(browser):
message = Message(title="Message One")
db.session.add(message)
db.session.commit()
message = Message.query.filter_by(title="Message One").first()

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


def test_delete_message_using_put_http_method(browser):
message = Message(title="Message One")
db.session.add(message)
db.session.commit()
message = Message.query.filter_by(title="Message One").first()

browser.visit(url_for("messages.show", id=message.id))
browser.find_by_value("delete").click()
Expand Down
2 changes: 1 addition & 1 deletion tests/version_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@


def test_mvc_flask_currently_version():
__version__ == "2.7.2"
__version__ == "2.8.1"