Skip to content
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
8 changes: 3 additions & 5 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
name: Test

on:
push:
branches: [ "**" ]
pull_request:
branches: [ "**" ]

Expand Down Expand Up @@ -30,12 +28,12 @@ jobs:
python-version: "3.13"

- name: Start MySQL
run: docker compose -f docker-compose.test.yml up -d --wait
run: docker compose -f docker-compose.yml up -d --wait

# ── fastapi_startkit package ──────────────────────────────────────────
- name: Install dependencies (fastapi_startkit)
working-directory: fastapi_startkit
run: uv sync --group dev
run: uv sync --group dev --extra database --extra sqlite

- name: Run tests (fastapi_startkit)
working-directory: fastapi_startkit
Expand All @@ -61,4 +59,4 @@ jobs:

- name: Stop MySQL
if: always()
run: docker compose -f docker-compose.test.yml down
run: docker compose -f docker-compose.yml down
1 change: 1 addition & 0 deletions fastapi_startkit/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ dev = [
"dumpdie>=1.5.0",
"pytest>=9.0.3",
"pytest-asyncio>=1.3.0",
"ruff>=0.9.0",
"twine>=6.2.0",
]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def limit(self, limit: int) -> "QueryBuilder":
return self

async def find(self, primary_key: str | int, columns=None):
return await self.where(self._model.primary_key, primary_key).first(columns)
return await self.where(self._model.__primary_key__, primary_key).first(columns)

async def first(self, columns=None):
if not columns:
Expand Down Expand Up @@ -195,3 +195,10 @@ def where(self, column, *args):
else:
self._wheres += ((QueryExpression(column, operator, value, "value")),)
return self

def or_where(self, column, *args) -> "QueryBuilder":
operator, value = self._extract_operator_value(*args)
self._wheres += (
(QueryExpression(column, operator, value, "value", keyword="or")),
)
return self
15 changes: 15 additions & 0 deletions fastapi_startkit/src/fastapi_startkit/masoniteorm/schema/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,21 @@ async def rename(self, table: str, new_name: str) -> None:
)
await self._connection.run(sql, ())

async def truncate(self, table: str, foreign_keys: bool = False) -> None:
connection = self.get_connection()
sql = self.platform().compile_truncate(table, foreign_keys=foreign_keys)
if isinstance(sql, list):
for q in sql:
await connection.statement(q, ())
else:
await connection.statement(sql, ())

async def has_column(self, table: str, column: str) -> bool:
connection = self.get_connection()
sql = self.platform().compile_column_exists(table, column)
result = await connection.select(sql, ())
return bool(result)

async def disable_foreign_key_constraints(self) -> None:
connection = self.get_connection()
sql = connection.get_default_platform()().disable_foreign_key_constraints()
Expand Down
15 changes: 0 additions & 15 deletions fastapi_startkit/src/fastapi_startkit/tests/test_case.py

This file was deleted.

Empty file.
7 changes: 7 additions & 0 deletions fastapi_startkit/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import pytest
from fastapi_startkit.application import Application


@pytest.fixture(scope="session", autouse=True)
def init_app():
Application(env="testing")
Empty file.
Empty file.
Empty file.
Original file line number Diff line number Diff line change
@@ -1,57 +1,21 @@
import os
import unittest

from fastapi_startkit.masoniteorm.factories import Factory as factory
from fastapi_startkit.masoniteorm.tests.integrations.config.database import DATABASES
from fastapi_startkit.masoniteorm.tests.User import User

from fastapi_startkit.masoniteorm.collection import Collection
from fastapi_startkit.masoniteorm.models import Model
from fastapi_startkit.masoniteorm.schema import Schema
from fastapi_startkit.masoniteorm.schema.platforms import SQLitePlatform


class TestCollection(unittest.IsolatedAsyncioTestCase):
async def asyncSetUp(self):
# Set config path for Schema.on() to work in tests
os.environ["DB_CONFIG_PATH"] = (
"fastapi_startkit.masoniteorm.tests.integrations.config.database"
)
from fastapi_startkit.masoniteorm.models.model import Model

self.schema = Schema(
connection="dev",
connection_details=DATABASES,
platform=SQLitePlatform,
dry=False,
).on("dev")
from ..fixtures.model import User
from ..sqlite.test_case import TestCase

# Ensure fresh table
await self.schema.drop_table_if_exists("users")

# Create users table
async with await self.schema.create("users") as blueprint:
blueprint.increments("id")
blueprint.string("name")
blueprint.string("email").unique()
blueprint.string("password")
blueprint.timestamps()

# Switch User connection to dev for tests
self._original_connection = User.__connection__
User.__connection__ = "dev"

# Seed data
await User.create(
{"name": "Joe", "email": "joe@example.com", "password": "password"}
)
class TestCollection(TestCase):
async def test_serialize_with_model_appends(self):
users = (await User.all()).serialize()
self.assertTrue(isinstance(users, list))
self.assertTrue(len(users) > 0)

async def asyncTearDown(self):
# Drop table while still on 'dev' connection
await self.schema.drop_table_if_exists("users")
# Restore connection
User.__connection__ = self._original_connection
# Clean up env
os.environ.pop("DB_CONFIG_PATH", None)
async def test_serialize_with_on_the_fly_appends(self):
users = await User.all()
serialized = users.serialize()
self.assertTrue(isinstance(serialized, list))
self.assertTrue(len(serialized) > 0)

def test_take(self):
collection = Collection([1, 2, 3, 4])
Expand All @@ -75,8 +39,11 @@ def test_pluck(self):
self.assertEqual(collection.pluck("name", "id"), {1: "Joe", 2: "Bob"})

def test_pluck_with_models(self):
factory.register(Model, lambda faker: {"id": 1, "batch": 1})
collection = factory(Model, 5).make()
class BatchModel(Model):
batch: int

instances = [BatchModel(batch=1) for _ in range(5)]
collection = Collection(instances)
self.assertEqual(collection.pluck("batch"), [1, 1, 1, 1, 1])

def test_where(self):
Expand Down Expand Up @@ -690,7 +657,6 @@ def test_group_by(self):

grouped = collection.group_by("age")

self.assertIsInstance(grouped, Collection)
self.assertEqual(
grouped,
{
Expand All @@ -699,15 +665,6 @@ def test_group_by(self):
},
)

async def test_serialize_with_model_appends(self):
User.__appends__ = ["meta"]
users = (await User.all()).serialize()
self.assertTrue(users[0].get("meta"))

async def test_serialize_with_on_the_fly_appends(self):
users = (await User.all()).set_appends(["meta"]).serialize()
self.assertTrue(users[0].get("meta"))

def test_random(self):
collection = Collection([1, 2, 3, 4])
item = collection.random()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from unittest.mock import MagicMock, patch
from fastapi_startkits.configuration import Configuration
from fastapi_startkit.configuration import Configuration


class TestConfiguration:
Expand Down
Empty file.
14 changes: 8 additions & 6 deletions fastapi_startkit/tests/masoniteorm/fixtures/db.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
from fastapi_startkit.orm.connections.factory import ConnectionFactory
from fastapi_startkit.orm.connections.manager import DatabaseManager
from fastapi_startkit.orm.models.model import Model
from fastapi_startkit.masoniteorm.connections.factory import ConnectionFactory
from fastapi_startkit.masoniteorm.connections.manager import DatabaseManager
from fastapi_startkit.masoniteorm.models.model import Model

DB = DatabaseManager(
ConnectionFactory(),
{
"default": "sqlite",
"sqlite": {
"driver": "sqlite",
"url": "sqlite+aiosqlite:///masonite.sqlite3",
"connections": {
"sqlite": {
"driver": "sqlite",
"url": "sqlite+aiosqlite:///masonite.sqlite3",
},
},
},
)
Expand Down
5 changes: 2 additions & 3 deletions fastapi_startkit/tests/masoniteorm/fixtures/model.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
from fastapi_startkit.carbon.carbon import Carbon
from fastapi_startkit.masoniteorm import Field
from fastapi_startkit.masoniteorm.models.fields import DateTimeField
from fastapi_startkit.masoniteorm.models.fields import Field, DateTimeField
from fastapi_startkit.masoniteorm.relationships import (
HasOne,
BelongsTo,
HasMany,
BelongsToMany,
)
from fastapi_startkit.orm.models.model import Model
from fastapi_startkit.masoniteorm.models.model import Model


class User(Model):
Expand Down
Empty file.
14 changes: 8 additions & 6 deletions fastapi_startkit/tests/masoniteorm/models/test_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,21 @@

from fastapi_startkit.carbon import Carbon
from fastapi_startkit.masoniteorm.models.fields import DateTimeField
from fastapi_startkit.orm.connections.factory import ConnectionFactory
from fastapi_startkit.orm.connections.manager import DatabaseManager
from fastapi_startkit.orm.models.model import Model
from fastapi_startkit.masoniteorm.connections.factory import ConnectionFactory
from fastapi_startkit.masoniteorm.connections.manager import DatabaseManager
from fastapi_startkit.masoniteorm.models.model import Model

# ---------------------------------------------------------------------------
# Shared fixtures
# ---------------------------------------------------------------------------

SQLITE_CONFIG = {
"default": "sqlite",
"sqlite": {
"driver": "sqlite",
"url": "sqlite+aiosqlite:///:memory:",
"connections": {
"sqlite": {
"driver": "sqlite",
"url": "sqlite+aiosqlite:///:memory:",
},
},
}

Expand Down
28 changes: 16 additions & 12 deletions fastapi_startkit/tests/masoniteorm/models/test_model_attributes.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

from fastapi_startkit.carbon import Carbon
from fastapi_startkit.masoniteorm.models.fields import DateTimeField
from fastapi_startkit.orm.connections.factory import ConnectionFactory
from fastapi_startkit.orm.connections.manager import DatabaseManager
from fastapi_startkit.orm.models.model import Model
from fastapi_startkit.masoniteorm.connections.factory import ConnectionFactory
from fastapi_startkit.masoniteorm.connections.manager import DatabaseManager
from fastapi_startkit.masoniteorm.models.model import Model


# ---------------------------------------------------------------------------
Expand All @@ -15,9 +15,11 @@

SQLITE_CONFIG = {
"default": "sqlite",
"sqlite": {
"driver": "sqlite",
"url": "sqlite+aiosqlite:///:memory:",
"connections": {
"sqlite": {
"driver": "sqlite",
"url": "sqlite+aiosqlite:///:memory:",
},
},
}

Expand Down Expand Up @@ -66,8 +68,8 @@ def test_build_url_constructs_from_parts(self):

def test_make_returns_sqlite_connection(self):
factory = ConnectionFactory()
conn = factory.make(SQLITE_CONFIG["sqlite"], "sqlite")
from fastapi_startkit.orm.connections.sqlite_connection import SQliteConnection
conn = factory.make(SQLITE_CONFIG["connections"]["sqlite"], "sqlite")
from fastapi_startkit.masoniteorm.connections.sqlite_connection import SQliteConnection

assert isinstance(conn, SQliteConnection)

Expand All @@ -88,13 +90,15 @@ def test_connection_raises_for_missing_driver(self):
# the "Unsupported driver" branch in ConnectionFactory.make().
factory = ConnectionFactory()
bad_config = {
"default": "mysql",
"mysql": {"driver": "mysql", "host": "localhost", "database": "db"},
"default": "mssql",
"connections": {
"mssql": {"driver": "mssql", "host": "localhost", "database": "db"},
},
}
dm = DatabaseManager(factory, bad_config)
with patch.object(ConnectionFactory, "create_engine", return_value=MagicMock()):
with pytest.raises(ValueError, match="Unsupported driver"):
dm.connection("mysql")
dm.connection("mssql")


# ---------------------------------------------------------------------------
Expand Down Expand Up @@ -188,7 +192,7 @@ def test_observers_are_registered_on_model(self, UserModel):

class TestModelQuery:
def test_query_returns_query_builder(self, UserModel):
from fastapi_startkit.orm.models.builder import QueryBuilder
from fastapi_startkit.masoniteorm.models.builder import QueryBuilder

builder = UserModel.query()
assert isinstance(builder, QueryBuilder)
Expand Down
Empty file.
Empty file.
Loading
Loading