Skip to content
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
051bd9f
introducing contract testing
matusdrobuliak66 Feb 5, 2025
d27aab3
Merge branch 'master' into pact-broker-experiment
matusdrobuliak66 Feb 27, 2025
4d80ec9
introduce pact testing
matusdrobuliak66 Feb 28, 2025
f5adb63
openapi specs
matusdrobuliak66 Feb 28, 2025
b2f764e
add pact-tests github job
matusdrobuliak66 Feb 28, 2025
e701dfa
add secrets
matusdrobuliak66 Feb 28, 2025
70df54f
Merge branch 'master' into pact-broker-experiment
matusdrobuliak66 Mar 3, 2025
ea04200
review @sanderegg
matusdrobuliak66 Mar 3, 2025
c785f5e
review @sanderegg
matusdrobuliak66 Mar 3, 2025
5557d72
Merge branch 'master' into pact-broker-experiment
matusdrobuliak66 Mar 3, 2025
883daa9
review @pcrespov
matusdrobuliak66 Mar 3, 2025
e88cf91
review
matusdrobuliak66 Mar 3, 2025
e84c8af
fix
matusdrobuliak66 Mar 3, 2025
e5e41fa
modify ci github actions
matusdrobuliak66 Mar 3, 2025
09de0ba
modify ci github actions
matusdrobuliak66 Mar 3, 2025
b782956
modify ci github actions
matusdrobuliak66 Mar 3, 2025
21d3eaf
modify ci github actions
matusdrobuliak66 Mar 3, 2025
b02e802
review @sanderegg
matusdrobuliak66 Mar 3, 2025
a66634d
review @pcrespov
matusdrobuliak66 Mar 3, 2025
ea88a5c
fix
matusdrobuliak66 Mar 3, 2025
e2043f7
Merge branch 'master' into pact-broker-experiment
matusdrobuliak66 Mar 4, 2025
38026a5
fix
matusdrobuliak66 Mar 4, 2025
dff6235
small refactor
matusdrobuliak66 Mar 4, 2025
196d0fb
Merge branch 'master' into pact-broker-experiment
matusdrobuliak66 Mar 4, 2025
806c923
fix
matusdrobuliak66 Mar 4, 2025
034063e
Merge branch 'master' into pact-broker-experiment
matusdrobuliak66 Mar 4, 2025
e63caf2
introduce checkout release contract
matusdrobuliak66 Mar 4, 2025
37c9016
introduce checkout release contract
matusdrobuliak66 Mar 4, 2025
ff45929
Merge branch 'master' into pact-broker-experiment-2
matusdrobuliak66 Mar 4, 2025
85262df
introduce checkout release contract
matusdrobuliak66 Mar 4, 2025
febb49e
review @pcrespov
matusdrobuliak66 Mar 4, 2025
3f2c25d
Merge branch 'master' into pact-broker-experiment-2
matusdrobuliak66 Mar 4, 2025
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
1 change: 1 addition & 0 deletions .github/workflows/ci-pact-master.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,5 @@ jobs:
make devenv
source .venv/bin/activate
cd services/api-server
make install-ci
make test-pacts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
{
"consumer": {
"name": "Sim4Life"
},
"provider": {
"name": "OsparcApiServerCheckoutRelease"
},
"interactions": [
{
"description": "Checkout one license",
"request": {
"method": "POST",
"path": "/v0/wallets/35/licensed-items/99580844-77fa-41bb-ad70-02dfaf1e3965/checkout",
"headers": {
"Accept": "application/json",
"Content-Type": "application/json"
},
"body": {
"number_of_seats": 1,
"service_run_id": "1740149365_21a9352a-1d46-41f9-9a9b-42ac888f5afb"
}
},
"response": {
"status": 200,
"headers": {
"Content-Length": "294",
"Content-Type": "application/json",
"Server": "uvicorn"
},
"body": {
"key": "MODEL_IX_HEAD",
"licensed_item_checkout_id": "25262183-392c-4268-9311-3c4256c46012",
"licensed_item_id": "99580844-77fa-41bb-ad70-02dfaf1e3965",
"num_of_seats": 1,
"product_name": "s4l",
"started_at": "2025-02-21T15:04:47.673828Z",
"stopped_at": null,
"user_id": 425,
"version": "1.0.0",
"wallet_id": 35
}
}
},
{
"description": "Release item",
"request": {
"method": "POST",
"path": "/v0/licensed-items/99580844-77fa-41bb-ad70-02dfaf1e3965/checked-out-items/25262183-392c-4268-9311-3c4256c46012/release",
"headers": {
"Accept": "application/json",
"Content-Type": "application/json"
}
},
"response": {
"status": 200,
"headers": {
"Content-Length": "319",
"Content-Type": "application/json",
"Server": "uvicorn"
},
"body": {
"key": "MODEL_IX_HEAD",
"licensed_item_checkout_id": "25262183-392c-4268-9311-3c4256c46012",
"licensed_item_id": "99580844-77fa-41bb-ad70-02dfaf1e3965",
"num_of_seats": 1,
"product_name": "s4l",
"started_at": "2025-02-21T15:04:47.673828Z",
"stopped_at": "2025-02-21T15:04:47.901169Z",
"user_id": 425,
"version": "1.0.0",
"wallet_id": 35
}
}
}
],
"metadata": {
"pactSpecification": {
"version": "3.0.0"
}
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"consumer": {
"name": "XOsparcApiClient"
"name": "Sim4Life"
},
"provider": {
"name": "OsparcApiProvider"
"name": "OsparcApiServerLicensedItems"
},
"interactions": [
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
# pylint: disable=redefined-outer-name
# pylint: disable=unused-argument
# pylint: disable=unused-variable
# pylint: disable=too-many-arguments


import os

import pytest
from fastapi import FastAPI
from models_library.api_schemas_webserver.licensed_items_checkouts import (
LicensedItemCheckoutRpcGet,
)
from pact.v3 import Verifier
from pytest_mock import MockerFixture
from simcore_service_api_server._meta import API_VERSION
from simcore_service_api_server.api.dependencies.authentication import (
Identity,
)
from simcore_service_api_server.api.dependencies.resource_usage_tracker_rpc import (
get_resource_usage_tracker_client,
)
from simcore_service_api_server.api.dependencies.webserver_rpc import (
get_wb_api_rpc_client,
)
from simcore_service_api_server.services_rpc.resource_usage_tracker import (
ResourceUsageTrackerClient,
)
from simcore_service_api_server.services_rpc.wb_api_server import WbApiRpcClient


def mock_get_current_identity() -> Identity:
return Identity(user_id=1, product_name="osparc", email="[email protected]")


# Fake response based on values from 01_checkout_release.json
EXPECTED_CHECKOUT = LicensedItemCheckoutRpcGet.model_validate(
{
"key": "MODEL_IX_HEAD",
"licensed_item_checkout_id": "25262183-392c-4268-9311-3c4256c46012",
"licensed_item_id": "99580844-77fa-41bb-ad70-02dfaf1e3965",
"num_of_seats": 1,
"product_name": "s4l",
"started_at": "2025-02-21T15:04:47.673828Z",
"stopped_at": None,
"user_id": 425,
"version": "1.0.0",
"wallet_id": 35,
}
)
assert EXPECTED_CHECKOUT.stopped_at is None


EXPECTED_RELEASE = LicensedItemCheckoutRpcGet.model_validate(
{
"key": "MODEL_IX_HEAD",
"licensed_item_checkout_id": "25262183-392c-4268-9311-3c4256c46012",
"licensed_item_id": "99580844-77fa-41bb-ad70-02dfaf1e3965",
"num_of_seats": 1,
"product_name": "s4l",
"started_at": "2025-02-21T15:04:47.673828Z",
"stopped_at": "2025-02-21T15:04:47.901169Z",
"user_id": 425,
"version": "1.0.0",
"wallet_id": 35,
}
)
assert EXPECTED_RELEASE.stopped_at is not None


class DummyRpcClient:
pass


@pytest.fixture
async def mock_wb_api_server_rpc(app: FastAPI, mocker: MockerFixture) -> MockerFixture:

app.dependency_overrides[get_wb_api_rpc_client] = lambda: WbApiRpcClient(
_client=DummyRpcClient()
)

mocker.patch(
"simcore_service_api_server.services_rpc.wb_api_server._checkout_licensed_item_for_wallet",
return_value=EXPECTED_CHECKOUT,
)

mocker.patch(
"simcore_service_api_server.services_rpc.wb_api_server._release_licensed_item_for_wallet",
return_value=EXPECTED_RELEASE,
)

return mocker


@pytest.fixture
async def mock_rut_server_rpc(app: FastAPI, mocker: MockerFixture) -> MockerFixture:

app.dependency_overrides[get_resource_usage_tracker_client] = (
lambda: ResourceUsageTrackerClient(_client=DummyRpcClient())
)

mocker.patch(
"simcore_service_api_server.services_rpc.resource_usage_tracker._get_licensed_item_checkout",
return_value=EXPECTED_CHECKOUT,
)

return mocker


@pytest.mark.skipif(
not os.getenv("PACT_BROKER_URL"),
reason="This test runs only if PACT_BROKER_URL is provided",
)
def test_provider_against_pact(
pact_broker_credentials: tuple[str, str, str],
mock_wb_api_server_rpc: MockerFixture,
mock_rut_server_rpc: MockerFixture,
run_test_server: str,
) -> None:
"""
Use the Pact Verifier to check the real provider
against the generated contract.
"""
broker_url, broker_username, broker_password = pact_broker_credentials

broker_builder = (
Verifier("OsparcApiServerCheckoutRelease")
.add_transport(url=run_test_server)
.broker_source(
broker_url,
username=broker_username,
password=broker_password,
selector=True,
)
)

# NOTE: If you want to filter/test against specific contract use tags
verifier = broker_builder.consumer_tags(
"checkout_release" # <-- Here you define which pact to verify
).build()

# Set API version and run verification
verifier.set_publish_options(version=API_VERSION, tags=None, branch=None)
verifier.verify()
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ def test_provider_against_pact(
broker_url, broker_username, broker_password = pact_broker_credentials

broker_builder = (
Verifier("OsparcApiProvider")
Verifier("OsparcApiServerLicensedItems")
.add_transport(url=run_test_server)
.broker_source(
broker_url,
Expand Down
Loading