* feat(67): add support for 'spec' using Python HTTP API source template and stripe as an example * chore(67): add sample state and config * feat(67): add check functionality for paystack source by fetching first customer * feat(67): add support for discover and read customer stream * feat(67): add paystack source connector to UI * feat(67): update source definitions to use 0.1.0 * Hacktoberfest 67 paystack source (#1) * feat(67): add support for 'spec' using Python HTTP API source template and stripe as an example * chore(67): add sample state and config * feat(67): add check functionality for paystack source by fetching first customer * feat(67): add support for discover and read customer stream * feat(67): add paystack source connector to UI * feat(67): update source definitions to use 0.1.0 Co-authored-by: Foluso Ogunlana <foluso_ogunlana@stearsng.com> * feat(67): update stream state cursor field to be integer and to match API record field name * chore(67): add unit tests for source and streams * chore(67): store formatted date time in state to match type of catalog * chore(67): add configuration for acceptance integration tests * docs(67): update docs and summary with paystack * chore(67): add essential schemas to be catalogued for new streams * feat(67): add support for critical streams - transactions subscriptions transfers refunds settlements * docs(67): update image and bootstrap * chore(67): update builds.md to include paystack badge * docs(67): add changelog and source definition JSON file * docs(67): add paystack to integrations readme * chore(67): update check_connection to airbyte standard * refactor to simplify streams and remove constants file * fix(67): correct "null, null" values in schemas * chore(67): update file formatting with gradle format Co-authored-by: Foluso <5675998+foogunlana@users.noreply.github.com>
112 lines
4.3 KiB
Python
112 lines
4.3 KiB
Python
#
|
|
# Copyright (c) 2021 Airbyte, Inc., all rights reserved.
|
|
#
|
|
|
|
import math
|
|
import uuid
|
|
|
|
import pytest
|
|
from pytest import fixture
|
|
from source_paystack.streams import IncrementalPaystackStream
|
|
|
|
START_DATE = "2020-08-01T00:00:00Z"
|
|
|
|
|
|
@fixture
|
|
def patch_incremental_base_class(mocker):
|
|
# Mock abstract methods to enable instantiating abstract class
|
|
mocker.patch.object(IncrementalPaystackStream, "path", "v0/example_endpoint")
|
|
mocker.patch.object(IncrementalPaystackStream, "primary_key", "test_primary_key")
|
|
mocker.patch.object(IncrementalPaystackStream, "__abstractmethods__", set())
|
|
mocker.patch.object(IncrementalPaystackStream, "cursor_field", str(uuid.uuid4()))
|
|
|
|
|
|
def test_get_updated_state_uses_timestamp_of_latest_record(patch_incremental_base_class):
|
|
stream = IncrementalPaystackStream(start_date=START_DATE)
|
|
inputs = {"current_stream_state": {stream.cursor_field: "2021-08-01"}, "latest_record": {stream.cursor_field: "2021-08-02T00:00:00Z"}}
|
|
|
|
updated_state = stream.get_updated_state(**inputs)
|
|
|
|
assert updated_state == {stream.cursor_field: "2021-08-02T00:00:00Z"}
|
|
|
|
|
|
def test_get_updated_state_returns_current_state_for_old_records(patch_incremental_base_class):
|
|
stream = IncrementalPaystackStream(start_date=START_DATE)
|
|
current_state = {stream.cursor_field: "2021-08-03"}
|
|
inputs = {"current_stream_state": current_state, "latest_record": {stream.cursor_field: "2021-08-02T00:00:00Z"}}
|
|
|
|
updated_state = stream.get_updated_state(**inputs)
|
|
|
|
assert updated_state == current_state
|
|
|
|
|
|
def test_get_updated_state_uses_timestamp_of_latest_record_when_no_current_state_exists(patch_incremental_base_class):
|
|
stream = IncrementalPaystackStream(start_date=START_DATE)
|
|
inputs = {"current_stream_state": {}, "latest_record": {stream.cursor_field: "2021-08-02T00:00:00Z"}}
|
|
|
|
updated_state = stream.get_updated_state(**inputs)
|
|
|
|
assert updated_state == {stream.cursor_field: "2021-08-02T00:00:00Z"}
|
|
|
|
|
|
def test_request_params_includes_incremental_start_point(patch_incremental_base_class):
|
|
stream = IncrementalPaystackStream(start_date=START_DATE)
|
|
inputs = {
|
|
"stream_slice": None,
|
|
"next_page_token": {"page": 37},
|
|
"stream_state": {stream.cursor_field: "2021-09-02"},
|
|
}
|
|
|
|
params = stream.request_params(**inputs)
|
|
|
|
assert params == {"perPage": 200, "page": 37, "from": "2021-09-02T00:00:00Z"}
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"lookback_window_days, current_state, expected, message",
|
|
[
|
|
(None, "2021-08-30", "2021-08-30T00:00:00Z", "if lookback_window_days is not set should not affect cursor value"),
|
|
(0, "2021-08-30", "2021-08-30T00:00:00Z", "if lookback_window_days is not set should not affect cursor value"),
|
|
(10, "2021-08-30", "2021-08-20T00:00:00Z", "Should calculate cursor value as expected"),
|
|
(-10, "2021-08-30", "2021-08-20T00:00:00Z", "Should not care for the sign, use the module"),
|
|
],
|
|
)
|
|
def test_request_params_incremental_start_point_applies_lookback_window(
|
|
patch_incremental_base_class, lookback_window_days, current_state, expected, message
|
|
):
|
|
stream = IncrementalPaystackStream(start_date=START_DATE, lookback_window_days=lookback_window_days)
|
|
inputs = {
|
|
"stream_slice": None,
|
|
"next_page_token": None,
|
|
"stream_state": {stream.cursor_field: current_state},
|
|
}
|
|
|
|
params = stream.request_params(**inputs)
|
|
|
|
assert params["perPage"] == 200
|
|
assert params["from"] == expected, message
|
|
|
|
|
|
def test_request_params_incremental_start_point_defaults_to_start_date(patch_incremental_base_class):
|
|
stream = IncrementalPaystackStream(start_date=START_DATE)
|
|
inputs = {"stream_slice": None, "next_page_token": None, "stream_state": None}
|
|
|
|
params = stream.request_params(**inputs)
|
|
|
|
assert params == {"perPage": 200, "from": "2020-08-01T00:00:00Z"}
|
|
|
|
|
|
def test_supports_incremental(patch_incremental_base_class):
|
|
stream = IncrementalPaystackStream(start_date=START_DATE)
|
|
assert stream.supports_incremental
|
|
|
|
|
|
def test_source_defined_cursor(patch_incremental_base_class):
|
|
stream = IncrementalPaystackStream(start_date=START_DATE)
|
|
assert stream.source_defined_cursor
|
|
|
|
|
|
def test_stream_checkpoint_interval(patch_incremental_base_class):
|
|
stream = IncrementalPaystackStream(start_date=START_DATE)
|
|
assert stream.state_checkpoint_interval == math.inf
|