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
16 changes: 15 additions & 1 deletion tests/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@
# Test Setup
# Tests

## Running tests

There is a pdm script which runs tests with code coverage `pdm run test`. Any additional parameters will be passed through to pytest.

The -k parameter filters tests. Some useful examples:
```
pdm run test -k "Integration"
pdm run test --pg-host 172.17.0.3 -k "postgres and not Integration"
pdm run test -k "drop_tables and not postgres"
pdm run test -k "duckdb"
```

## Test Setup

Duckdb tests "just work".
Postgres tests will be skipped unless you set them up first.
Expand Down
25 changes: 25 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import contextlib
from collections.abc import Callable

import psycopg
import pytest
from httpx_folio.auth import FolioParams
from psycopg import sql


def pytest_addoption(parser: pytest.Parser) -> None:
Expand All @@ -24,3 +29,23 @@ def folio_params(pytestconfig: pytest.Config) -> tuple[bool, FolioParams]:
pytestconfig.getoption("folio_password") or "admin",
),
)


@pytest.fixture(scope="session")
def pg_dsn(pytestconfig: pytest.Config) -> None | Callable[[str], str]:
host = pytestconfig.getoption("pg_host")
if host is None:
return None

def setup(db: str) -> str:
base_dsn = f"host={host} user=ldlite password=ldlite"
with contextlib.closing(psycopg.connect(base_dsn)) as base_conn:
base_conn.autocommit = True
with base_conn.cursor() as curr:
curr.execute(
sql.SQL("CREATE DATABASE {db};").format(db=sql.Identifier(db)),
)

return base_dsn + f" dbname={db}"

return setup
76 changes: 76 additions & 0 deletions tests/mock_response_case.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import json
from dataclasses import dataclass
from functools import cached_property
from typing import TYPE_CHECKING
from unittest.mock import MagicMock
from uuid import uuid4

if TYPE_CHECKING:
import ldlite


@dataclass(frozen=True)
class Call:
prefix: str
returns: "ldlite._jsonx.Json | list[ldlite._jsonx.Json]"

# duplicate of LDLite.query default params
query: str | dict[str, str] | None = None
json_depth: int = 3
limit: int | None = None
keep_raw: bool = True

@property
def returns_list(self) -> list["ldlite._jsonx.Json"]:
if isinstance(self.returns, list):
return self.returns

return [self.returns]


@dataclass(frozen=True)
class MockedResponseTestCase:
calls: Call | list[Call]

@property
def calls_list(self) -> list[Call]:
if isinstance(self.calls, list):
return self.calls

return [self.calls]

@cached_property
def db(self) -> str:
db = "db" + str(uuid4()).split("-")[0]
print(db) # noqa: T201
return db

def patch_request_get(
self,
ld: "ldlite.LDLite",
httpx_post_mock: MagicMock,
client_get_mock: MagicMock,
) -> None:
# leave tqdm out of it
ld.quiet(enable=True)

httpx_post_mock.return_value.cookies.__getitem__.return_value = "token"

side_effects = []
for call in self.calls_list:
key = next(iter(call.returns_list[0].keys()))
total_mock = MagicMock()
total_mock.text = f'{{"{key}": [{{"id": ""}}], "totalRecords": 100000}}'

value_mocks = []
for v in call.returns_list:
value_mock = MagicMock()
value_mock.text = json.dumps(v)
value_mocks.append(value_mock)

end_mock = MagicMock()
end_mock.text = f'{{"{key}": [] }}'

side_effects.extend([total_mock, *value_mocks, end_mock])

client_get_mock.side_effect = side_effects
160 changes: 78 additions & 82 deletions tests/test___init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,78 +7,6 @@
from pytest_cases import parametrize_with_cases


def test_ok_legacy(folio_params: tuple[bool, FolioParams]) -> None:
from ldlite import LDLite as uut

ld = uut()
ld.connect_folio(*astuple(folio_params[1]))
ld.connect_db()
ld.query(table="g", path="/groups", query="cql.allRecords=1 sortby id")
ld.select(table="g__t")


def test_ok_limit(folio_params: tuple[bool, FolioParams]) -> None:
from ldlite import LDLite as uut

ld = uut()
db = ld.connect_db()

ld.connect_folio(*astuple(folio_params[1]))
ld.page_size = 2
ld.query(table="g", path="/groups", query="cql.allRecords=1 sortby id", limit=5)

db.execute("SELECT COUNT(DISTINCT COLUMNS(*)) FROM g__t;")
actual = cast("tuple[int]", db.fetchone())[0]
assert actual == 5


def test_ok_trailing_slash(folio_params: tuple[bool, FolioParams]) -> None:
if folio_params[0]:
pytest.skip("Specify an okapi environment with --folio-base-url to run")

from ldlite import LDLite as uut

ld = uut()
params = astuple(folio_params[1])
ld.connect_folio(*[params[0] + "/", *params[1:]])
ld.connect_db()
ld.query(table="g", path="/groups")
ld.select(table="g__t")


def test_ok(folio_params: tuple[bool, FolioParams]) -> None:
from ldlite import LDLite as uut

ld = uut()
ld.connect_folio(*astuple(folio_params[1]))
ld.connect_db()
ld.query(table="g", path="/groups")
ld.select(table="g__t")


def test_no_connect_folio() -> None:
from ldlite import LDLite as uut

ld = uut()
ld.connect_db()
with pytest.raises(RuntimeError):
ld.query(table="g", path="/groups")


def test_no_connect_db() -> None:
from ldlite import LDLite as uut

ld = uut()
ld.connect_folio(
url="https://folio-etesting-snapshot-kong.ci.folio.org",
tenant="diku",
user="diku_admin",
password="admin",
)
with pytest.raises(RuntimeError):
ld.query(table="g", path="/groups")


@dataclass(frozen=True)
class FolioConnectionCase:
expected: type[Exception]
Expand Down Expand Up @@ -116,14 +44,82 @@ def case_password(self) -> FolioConnectionCase:
)


@parametrize_with_cases("tc", cases=FolioConnectionCases)
def test_bad_folio_connection(
folio_params: tuple[bool, FolioParams],
tc: FolioConnectionCase,
) -> None:
from ldlite import LDLite as uut
class TestIntegration:
def test_ok_legacy(self, folio_params: tuple[bool, FolioParams]) -> None:
from ldlite import LDLite as uut

ld = uut()
ld.connect_folio(*astuple(folio_params[1]))
ld.connect_db()
ld.query(table="g", path="/groups", query="cql.allRecords=1 sortby id")
ld.select(table="g__t")

def test_ok_limit(self, folio_params: tuple[bool, FolioParams]) -> None:
from ldlite import LDLite as uut

ld = uut()
db = ld.connect_db()

ld.connect_folio(*astuple(folio_params[1]))
ld.page_size = 2
ld.query(table="g", path="/groups", query="cql.allRecords=1 sortby id", limit=5)

db.execute("SELECT COUNT(DISTINCT COLUMNS(*)) FROM g__t;")
actual = cast("tuple[int]", db.fetchone())[0]
assert actual == 5

def test_ok_trailing_slash(self, folio_params: tuple[bool, FolioParams]) -> None:
if folio_params[0]:
pytest.skip("Specify an okapi environment with --folio-base-url to run")

from ldlite import LDLite as uut

ld = uut()
params = astuple(folio_params[1])
with pytest.raises(tc.expected):
ld.connect_folio(*[*params[: tc.index], tc.value, *params[tc.index + 1 :]])
ld = uut()
params = astuple(folio_params[1])
ld.connect_folio(*[params[0] + "/", *params[1:]])
ld.connect_db()
ld.query(table="g", path="/groups")
ld.select(table="g__t")

def test_ok(self, folio_params: tuple[bool, FolioParams]) -> None:
from ldlite import LDLite as uut

ld = uut()
ld.connect_folio(*astuple(folio_params[1]))
ld.connect_db()
ld.query(table="g", path="/groups")
ld.select(table="g__t")

def test_no_connect_folio(self) -> None:
from ldlite import LDLite as uut

ld = uut()
ld.connect_db()
with pytest.raises(RuntimeError):
ld.query(table="g", path="/groups")

def test_no_connect_db(self) -> None:
from ldlite import LDLite as uut

ld = uut()
ld.connect_folio(
url="https://folio-etesting-snapshot-kong.ci.folio.org",
tenant="diku",
user="diku_admin",
password="admin",
)
with pytest.raises(RuntimeError):
ld.query(table="g", path="/groups")

@parametrize_with_cases("tc", cases=FolioConnectionCases)
def test_bad_folio_connection(
self,
folio_params: tuple[bool, FolioParams],
tc: FolioConnectionCase,
) -> None:
from ldlite import LDLite as uut

ld = uut()
params = astuple(folio_params[1])
with pytest.raises(tc.expected):
ld.connect_folio(*[*params[: tc.index], tc.value, *params[tc.index + 1 :]])
59 changes: 0 additions & 59 deletions tests/test_cases/base.py

This file was deleted.

Loading
Loading