Skip to content

Commit

Permalink
added unit tests!
Browse files Browse the repository at this point in the history
  • Loading branch information
patx committed Jan 20, 2025
1 parent 65d43ce commit 710250b
Showing 1 changed file with 230 additions and 0 deletions.
230 changes: 230 additions & 0 deletions tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
import unittest
import uuid
import time
from io import BytesIO
from unittest.mock import patch
from MicroPie import Server


class TestMicroPie(unittest.TestCase):
def setUp(self):
"""
Create a fresh instance of the Server for each test and define some
sample endpoints on the fly.
"""
self.server = Server()

# Define a simple default endpoint
def index():
return "Hello from index!"

# Define an endpoint that greets the user by name
def greet(name="World"):
return f"Hello, {name}!"

# Define an endpoint that triggers a redirect
def go_away():
return self.server.redirect("/gone")

# Define an endpoint for testing template rendering (requires a
# templates/greet.html file in your project for a real test).
def greet_template(name="World"):
return self.server.render_template("greet.html", name=name)

# Attach the functions to the server instance
self.server.index = index
self.server.greet = greet
self.server.go_away = go_away
self.server.greet_template = greet_template

def _start_response(self, status, headers):
"""
Helper method to capture the status and headers from wsgi_app calls.
"""
self._wsgi_status = status
self._wsgi_headers = headers

def test_index_get(self):
"""
Ensure that accessing '/' via GET calls the 'index' function and
returns the correct body.
"""
environ = {
"REQUEST_METHOD": "GET",
"PATH_INFO": "/", # Access root
"QUERY_STRING": "",
"wsgi.input": BytesIO(b""),
"CONTENT_LENGTH": "0",
}
response = self.server.wsgi_app(environ, self._start_response)
body = b"".join(response).decode()

self.assertEqual(self._wsgi_status, "200 OK")
self.assertIn("Hello from index!", body)

def test_custom_endpoint_get(self):
"""
Ensure that a custom endpoint (greet) can accept query parameters
through GET and return the correct response.
"""
environ = {
"REQUEST_METHOD": "GET",
"PATH_INFO": "/greet",
"QUERY_STRING": "name=Alice",
"wsgi.input": BytesIO(b""),
"CONTENT_LENGTH": "0",
}
response = self.server.wsgi_app(environ, self._start_response)
body = b"".join(response).decode()

self.assertEqual(self._wsgi_status, "200 OK")
self.assertIn("Hello, Alice!", body)

def test_custom_endpoint_path_param(self):
"""
Test that path parameters are used if present. For example, accessing
'/greet/Bob' should call greet("Bob").
"""
environ = {
"REQUEST_METHOD": "GET",
"PATH_INFO": "/greet/Bob",
"QUERY_STRING": "",
"wsgi.input": BytesIO(b""),
"CONTENT_LENGTH": "0",
}
response = self.server.wsgi_app(environ, self._start_response)
body = b"".join(response).decode()

self.assertEqual(self._wsgi_status, "200 OK")
self.assertIn("Hello, Bob!", body)

def test_endpoint_not_found(self):
"""
Access a path that does not map to a defined method. Expect 404.
"""
environ = {
"REQUEST_METHOD": "GET",
"PATH_INFO": "/does_not_exist",
"QUERY_STRING": "",
"wsgi.input": BytesIO(b""),
"CONTENT_LENGTH": "0",
}
response = self.server.wsgi_app(environ, self._start_response)
body = b"".join(response).decode()

self.assertEqual(self._wsgi_status, "404 Not Found")
self.assertIn("404 Not Found", body)

def test_post_request(self):
"""
Test handling of a POST request with form data in the body.
"""
post_body = "name=Charlie"
environ = {
"REQUEST_METHOD": "POST",
"PATH_INFO": "/greet",
"QUERY_STRING": "",
"wsgi.input": BytesIO(post_body.encode("utf-8")),
"CONTENT_LENGTH": str(len(post_body)),
}
response = self.server.wsgi_app(environ, self._start_response)
body = b"".join(response).decode()

self.assertEqual(self._wsgi_status, "200 OK")
self.assertIn("Hello, Charlie!", body)

def test_redirect(self):
"""
Test that an endpoint can return a 302 redirect.
"""
environ = {
"REQUEST_METHOD": "GET",
"PATH_INFO": "/go_away", # Calls the go_away function
"QUERY_STRING": "",
"wsgi.input": BytesIO(b""),
"CONTENT_LENGTH": "0",
}
response = self.server.wsgi_app(environ, self._start_response)
body = b"".join(response).decode()

# MicroPie returns (302, <html>...) so we expect status to be "302 Found"
self.assertEqual(self._wsgi_status, "302 Found")
self.assertIn("url=/gone", body) # Basic check that the redirect body is correct

def test_session_creation(self):
"""
Test that a session is created if no session cookie is present.
"""
environ = {
"REQUEST_METHOD": "GET",
"PATH_INFO": "/",
"QUERY_STRING": "",
"wsgi.input": BytesIO(b""),
"CONTENT_LENGTH": "0",
# No HTTP_COOKIE -> expect new session
}
response = self.server.wsgi_app(environ, self._start_response)
_ = b"".join(response).decode()

# Find the Set-Cookie header among the WSGI headers
set_cookie_headers = [h for h in self._wsgi_headers if h[0] == 'Set-Cookie']
self.assertTrue(set_cookie_headers, "Expected a Set-Cookie header for new session.")

# The session should be stored in self.server.sessions
cookie_value = set_cookie_headers[0][1]
session_id = cookie_value.split("=")[1].split(";")[0]
self.assertIn(session_id, self.server.sessions)

def test_session_usage(self):
"""
Test that an existing session is reused if a valid session_id is provided.
"""
# Create a session manually
session_id = str(uuid.uuid4())
self.server.sessions[session_id] = {"last_access": time.time()}

environ = {
"REQUEST_METHOD": "GET",
"PATH_INFO": "/",
"QUERY_STRING": "",
"wsgi.input": BytesIO(b""),
"CONTENT_LENGTH": "0",
"HTTP_COOKIE": f"session_id={session_id}",
}
response = self.server.wsgi_app(environ, self._start_response)
_ = b"".join(response).decode()

# We should not receive a new Set-Cookie; we should reuse existing one.
set_cookie_headers = [h for h in self._wsgi_headers if h[0] == 'Set-Cookie']
self.assertFalse(set_cookie_headers, "Did not expect a new Set-Cookie header.")

# Ensure we didn't lose the session
self.assertIn(session_id, self.server.sessions, "Existing session should still be present.")

@unittest.skip("Requires a valid 'greet.html' in the 'templates' folder to work.")
def test_template_rendering(self):
"""
Optional test for verifying a Jinja2 template render. This test will
require a 'templates/greet.html' file that references a variable 'name'.
Example 'greet.html' content:
<h1>Hello {{ name }}!</h1>
"""
environ = {
"REQUEST_METHOD": "GET",
"PATH_INFO": "/greet_template",
"QUERY_STRING": "name=Tester",
"wsgi.input": BytesIO(b""),
"CONTENT_LENGTH": "0",
}
response = self.server.wsgi_app(environ, self._start_response)
body = b"".join(response).decode()

self.assertEqual(self._wsgi_status, "200 OK")
self.assertIn("<h1>Hello Tester!</h1>", body)


if __name__ == '__main__':
unittest.main()

0 comments on commit 710250b

Please sign in to comment.