1
0
mirror of synced 2026-01-07 09:05:45 -05:00
Files
airbyte/airbyte-integrations/connectors/source-appsflyer/unit_tests/test_incremental_streams.py
Cole Snodgrass 2e099acc52 update headers from 2022 -> 2023 (#22594)
* It's 2023!

* 2022 -> 2023

---------

Co-authored-by: evantahler <evan@airbyte.io>
2023-02-08 13:01:16 -08:00

176 lines
7.1 KiB
Python

#
# Copyright (c) 2023 Airbyte, Inc., all rights reserved.
#
import pendulum
import pytest
from airbyte_cdk.models import SyncMode
from pytest import fixture, raises
from source_appsflyer import fields
from source_appsflyer.source import (
DailyReport,
GeoReport,
InAppEvents,
IncrementalAppsflyerStream,
Installs,
PartnersReport,
RetargetingConversions,
RetargetingDailyReport,
RetargetingGeoReport,
RetargetingInAppEvents,
RetargetingPartnersReport,
UninstallEvents,
)
@fixture
def patch_incremental_base_class(mocker):
# Mock abstract methods to enable instantiating abstract class
mocker.patch.object(IncrementalAppsflyerStream, "path", "v0/example_endpoint")
mocker.patch.object(IncrementalAppsflyerStream, "primary_key", "test_primary_key")
mocker.patch.object(IncrementalAppsflyerStream, "__abstractmethods__", set())
@pytest.mark.parametrize(
("class_", "expected_cursor_field"),
[
(IncrementalAppsflyerStream, []),
(InAppEvents, "event_time"),
(RetargetingInAppEvents, "event_time"),
(UninstallEvents, "event_time"),
(Installs, "install_time"),
(RetargetingConversions, "install_time"),
(PartnersReport, "date"),
(DailyReport, "date"),
(GeoReport, "date"),
(RetargetingPartnersReport, "date"),
(RetargetingDailyReport, "date"),
(RetargetingGeoReport, "date"),
],
)
def test_cursor_field(patch_incremental_base_class, mocker, class_, expected_cursor_field):
mocker.patch.object(class_, "__init__", lambda x: None)
stream = class_()
assert stream.cursor_field == expected_cursor_field
@pytest.mark.parametrize(
("class_", "cursor_field", "date_only", "additional_fields", "retargeting", "currency"),
[
(InAppEvents, "event_time", False, fields.raw_data.additional_fields, None, "preferred"),
(RetargetingInAppEvents, "event_time", False, fields.raw_data.additional_fields, True, "preferred"),
(UninstallEvents, "event_time", False, fields.uninstall_events.additional_fields, None, "preferred"),
(Installs, "install_time", False, fields.raw_data.additional_fields, None, "preferred"),
(RetargetingConversions, "install_time", False, fields.raw_data.additional_fields, True, "preferred"),
(PartnersReport, "date", True, None, None, None),
(DailyReport, "date", True, None, None, None),
(GeoReport, "date", True, None, None, None),
(RetargetingPartnersReport, "date", True, None, True, None),
(RetargetingDailyReport, "date", True, None, True, None),
(RetargetingGeoReport, "date", True, None, True, None),
],
)
def test_request_params(mocker, class_, cursor_field, date_only, additional_fields, retargeting, currency):
timezone = "UTC"
def __init__(self):
self.api_token = "secret"
self.timezone = pendulum.timezone("UTC")
self.start_date = pendulum.yesterday(timezone)
self.end_date = pendulum.today(timezone)
mocker.patch.object(class_, "__init__", __init__)
mocker.patch.object(class_, "cursor_field", cursor_field)
stream = class_()
start = pendulum.yesterday(timezone)
end = pendulum.today(timezone)
inputs = dict()
inputs["stream_slice"] = {cursor_field: start, cursor_field + "_end": end}
inputs["next_page_token"] = None
inputs["stream_state"] = None
expected_params = dict()
expected_params["api_token"] = "secret"
expected_params["timezone"] = timezone
expected_params["maximum_rows"] = 1_000_000
expected_params["from"] = start.to_datetime_string()
expected_params["to"] = end.to_datetime_string()
if date_only:
expected_params["from"] = start.to_date_string()
expected_params["to"] = end.to_date_string()
if additional_fields:
expected_params["additional_fields"] = (",").join(additional_fields)
if retargeting:
expected_params["reattr"] = retargeting
if currency:
expected_params["currency"] = currency
assert stream.request_params(**inputs) == expected_params
@pytest.mark.parametrize(
("current_stream_state", "latest_record", "expected_state"),
[
(dict(event_time="2021-09-09"), dict(event_time="2021-09-09"), dict(event_time="2021-09-09")),
({}, dict(event_time="2021-09-09"), dict(event_time="2021-09-09")),
({}, {}, {}),
],
)
def test_get_updated_state(patch_incremental_base_class, mocker, current_stream_state, latest_record, expected_state):
def __init__(self):
self.timezone = pendulum.timezone("UTC")
mocker.patch.object(IncrementalAppsflyerStream, "__init__", __init__)
mocker.patch.object(IncrementalAppsflyerStream, "cursor_field", "event_time")
stream = IncrementalAppsflyerStream()
inputs = {"current_stream_state": current_stream_state, "latest_record": latest_record}
assert stream.get_updated_state(**inputs) == expected_state
def test_get_updated_state_exists_current_stream_and_empty_latest_record(patch_incremental_base_class, mocker):
with raises(TypeError, match=r"Expected (.*) type '(.*)' but returned type '(.*)'."):
def __init__(self):
self.timezone = pendulum.timezone("UTC")
mocker.patch.object(IncrementalAppsflyerStream, "__init__", __init__)
mocker.patch.object(IncrementalAppsflyerStream, "cursor_field", "event_time")
stream = IncrementalAppsflyerStream()
inputs = {"current_stream_state": dict(event_time="2021-09-09"), "latest_record": {"event_time": None}}
stream.get_updated_state(**inputs)
def test_stream_slices(patch_incremental_base_class, mocker):
timezone = "UTC"
def __init__(self):
self.api_token = "secret"
self.timezone = pendulum.timezone("UTC")
self.start_date = pendulum.yesterday("UTC")
self.end_date = pendulum.today("UTC")
mocker.patch.object(IncrementalAppsflyerStream, "__init__", __init__)
mocker.patch.object(IncrementalAppsflyerStream, "cursor_field", "date")
stream = IncrementalAppsflyerStream()
inputs = {"sync_mode": SyncMode.incremental, "cursor_field": [], "stream_state": dict(date=pendulum.yesterday(timezone))}
expected_stream_slice = [{"date": pendulum.yesterday("UTC"), "date_end": pendulum.today("UTC")}]
assert stream.stream_slices(**inputs) == expected_stream_slice
def test_supports_incremental(patch_incremental_base_class, mocker):
mocker.patch.object(IncrementalAppsflyerStream, "__init__", lambda x: None)
mocker.patch.object(IncrementalAppsflyerStream, "cursor_field", "dummy_field")
stream = IncrementalAppsflyerStream()
assert stream.supports_incremental
def test_source_defined_cursor(patch_incremental_base_class, mocker):
mocker.patch.object(IncrementalAppsflyerStream, "__init__", lambda x: None)
stream = IncrementalAppsflyerStream()
assert stream.source_defined_cursor
def test_stream_checkpoint_interval(patch_incremental_base_class, mocker):
mocker.patch.object(IncrementalAppsflyerStream, "__init__", lambda x: None)
stream = IncrementalAppsflyerStream()
expected_checkpoint_interval = None
assert stream.state_checkpoint_interval == expected_checkpoint_interval