Test alembic automigration with add and drop table and column. Args: tmp_working_dir: directory where database and migrations are stored monkeypatch: pytest fixture to overwrite attributes model_registry: clean reflex ModelRegistry
(
tmp_working_dir: Path,
monkeypatch: pytest.MonkeyPatch,
model_registry: type[ModelRegistry],
)
| 78 | "ignore:This declarative base already contains a class with the same class name", |
| 79 | ) |
| 80 | def test_automigration( |
| 81 | tmp_working_dir: Path, |
| 82 | monkeypatch: pytest.MonkeyPatch, |
| 83 | model_registry: type[ModelRegistry], |
| 84 | ): |
| 85 | """Test alembic automigration with add and drop table and column. |
| 86 | |
| 87 | Args: |
| 88 | tmp_working_dir: directory where database and migrations are stored |
| 89 | monkeypatch: pytest fixture to overwrite attributes |
| 90 | model_registry: clean reflex ModelRegistry |
| 91 | """ |
| 92 | import sqlalchemy.exc |
| 93 | import sqlmodel |
| 94 | |
| 95 | alembic_ini = tmp_working_dir / "alembic.ini" |
| 96 | versions = tmp_working_dir / "alembic" / "versions" |
| 97 | monkeypatch.setattr(reflex.constants, "ALEMBIC_CONFIG", str(alembic_ini)) |
| 98 | |
| 99 | config_mock = mock.Mock() |
| 100 | config_mock.db_url = f"sqlite:///{tmp_working_dir}/reflex.db" |
| 101 | monkeypatch.setattr(reflex.model, "get_config", mock.Mock(return_value=config_mock)) |
| 102 | |
| 103 | alembic_init() |
| 104 | assert alembic_ini.exists() |
| 105 | assert versions.exists() |
| 106 | |
| 107 | # initial table |
| 108 | class AlembicThing(Model, table=True): # pyright: ignore [reportRedeclaration] |
| 109 | t1: str |
| 110 | |
| 111 | with get_engine().connect() as connection: |
| 112 | assert alembic_autogenerate(connection=connection, message="Initial Revision") |
| 113 | assert migrate() |
| 114 | version_scripts = list(versions.glob("*.py")) |
| 115 | assert len(version_scripts) == 1 |
| 116 | assert version_scripts[0].name.endswith("initial_revision.py") |
| 117 | |
| 118 | with reflex.model.session() as session: |
| 119 | session.add(AlembicThing(id=None, t1="foo")) |
| 120 | session.commit() |
| 121 | |
| 122 | model_registry.get_metadata().clear() |
| 123 | |
| 124 | # Create column t2, mark t1 as optional with default |
| 125 | class AlembicThing(Model, table=True): # pyright: ignore [reportRedeclaration] |
| 126 | t1: str | None = "default" |
| 127 | t2: str = "bar" |
| 128 | |
| 129 | assert migrate(autogenerate=True) |
| 130 | assert len(list(versions.glob("*.py"))) == 2 |
| 131 | |
| 132 | with reflex.model.session() as session: |
| 133 | session.add(AlembicThing(t2="baz")) |
| 134 | session.commit() |
| 135 | result = session.exec(sqlmodel.select(AlembicThing)).all() |
| 136 | assert len(result) == 2 |
| 137 | assert result[0].t1 == "foo" |
nothing calls this directly
no test coverage detected