Skip to content

Commit 68a4e62

Browse files
authored
✨ Source Intercom: adding a mock server test (#54715)
1 parent dc28f8d commit 68a4e62

File tree

9 files changed

+433
-101
lines changed

9 files changed

+433
-101
lines changed

airbyte-ci/connectors/pipelines/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ If you are developing on pipelines, we recommend installing airbyte-ci with poet
8585
```bash
8686
cd airbyte-ci/connectors/pipelines/
8787
poetry install
88-
poetry shell
88+
poetry env activate
8989
cd ../../
9090
```
9191

airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/manifest_only_connectors.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ class ManifestOnlyConnectorUnitTests(PytestStep):
6464

6565
title = "Manifest-only unit tests"
6666
test_directory_name = "unit_tests"
67-
common_test_dependencies = ["pytest"]
67+
common_test_dependencies = ["pytest", "requests-mock"]
6868

6969
async def install_testing_environment(
7070
self,

airbyte-ci/connectors/pipelines/pipelines/airbyte_ci/connectors/test/steps/python_connectors.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ async def install_testing_environment(
168168
)
169169
if self.common_test_dependencies:
170170
container_with_test_deps = container_with_test_deps.with_user("root").with_exec(
171-
["pip", "install", f'{" ".join(self.common_test_dependencies)}']
171+
["pip", "install"] + self.common_test_dependencies
172172
)
173173

174174
container_with_test_deps = (

airbyte-integrations/connectors/source-intercom/metadata.yaml

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ data:
66
hosts:
77
- api.intercom.io
88
connectorBuildOptions:
9-
baseImage: docker.io/airbyte/source-declarative-manifest:6.33.6@sha256:81af934a2136edf0521a71697938cea20d1c6eb36c944566b9455bdd2a47d2bd
9+
baseImage: docker.io/airbyte/source-declarative-manifest:6.38.3@sha256:fcba02266f262aabc2f37e4f14574aa1c8c5cffd018504bab28803e405c93afe
1010
connectorSubtype: api
1111
connectorType: source
1212
definitionId: d8313939-3782-41b0-be29-b3ca20d8dd3a
@@ -43,6 +43,7 @@ data:
4343
- cdk:low-code
4444
- language:manifest-only
4545
connectorTestSuitesOptions:
46+
- suite: unitTests
4647
- suite: liveTests
4748
testConnections:
4849
- name: intercom_config_dev_null
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Copyright (c) 2024 Airbyte, Inc., all rights reserved.
2+
3+
from datetime import datetime
4+
from typing import Any, Mapping
5+
6+
7+
class ConfigBuilder:
8+
def __init__(self) -> None:
9+
self._config = {
10+
"access_token": "fake_access_token",
11+
"start_date": "2010-01-18T21:18:20Z",
12+
}
13+
14+
def start_date(self, start_date: datetime) -> "ConfigBuilder":
15+
self._config["start_date"] = start_date.strftime("%Y-%m-%dT%H:%M:%SZ")
16+
return self
17+
18+
def access_token(self, refresh_token: str) -> "ConfigBuilder":
19+
self._config["refresh_token"] = refresh_token
20+
return self
21+
22+
def build(self) -> Mapping[str, Any]:
23+
return self._config
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# Copyright (c) 2024 Airbyte, Inc., all rights reserved.
2+
3+
import sys
4+
from pathlib import Path
5+
from typing import Any, Dict, Optional
6+
from unittest import TestCase
7+
8+
from config_builder import ConfigBuilder
9+
10+
from airbyte_cdk import ConfiguredAirbyteCatalog, SyncMode, TState, YamlDeclarativeSource
11+
from airbyte_cdk.test.catalog_builder import CatalogBuilder
12+
from airbyte_cdk.test.entrypoint_wrapper import EntrypointOutput
13+
from airbyte_cdk.test.entrypoint_wrapper import read as entrypoint_read
14+
from airbyte_cdk.test.mock_http import HttpMocker, HttpRequest
15+
from airbyte_cdk.test.mock_http.response_builder import (
16+
FieldPath,
17+
HttpResponseBuilder,
18+
RecordBuilder,
19+
create_record_builder,
20+
create_response_builder,
21+
find_template,
22+
)
23+
from airbyte_cdk.test.state_builder import StateBuilder
24+
25+
26+
def _get_manifest_path() -> Path:
27+
source_declarative_manifest_path = Path("/airbyte/integration_code/source_declarative_manifest")
28+
if source_declarative_manifest_path.exists():
29+
return source_declarative_manifest_path
30+
return Path(__file__).parent.parent.parent
31+
32+
33+
_SOURCE_FOLDER_PATH = _get_manifest_path()
34+
_YAML_FILE_PATH = _SOURCE_FOLDER_PATH / "manifest.yaml"
35+
36+
sys.path.append(str(_SOURCE_FOLDER_PATH)) # to allow loading custom components
37+
38+
39+
def _catalog() -> ConfiguredAirbyteCatalog:
40+
return CatalogBuilder().with_stream("segments", SyncMode.full_refresh).build()
41+
42+
43+
def _source(catalog: ConfiguredAirbyteCatalog, config: Dict[str, Any], state: Optional[TState]) -> YamlDeclarativeSource:
44+
return YamlDeclarativeSource(path_to_yaml=str(_YAML_FILE_PATH), catalog=catalog, config=config, state=state)
45+
46+
47+
def _response_template() -> Dict[str, Any]:
48+
return find_template("segments", __file__)
49+
50+
51+
def _record() -> RecordBuilder:
52+
return create_record_builder(
53+
_response_template(), FieldPath("segments"), record_id_path=FieldPath("id"), record_cursor_path=FieldPath("updated_at")
54+
)
55+
56+
57+
def _response() -> HttpResponseBuilder:
58+
return create_response_builder(
59+
response_template=_response_template(),
60+
records_path=FieldPath("segments"),
61+
)
62+
63+
64+
def read(
65+
config_builder: Optional[ConfigBuilder] = None,
66+
state_builder: Optional[StateBuilder] = None,
67+
expecting_exception: bool = False,
68+
) -> EntrypointOutput:
69+
catalog = _catalog()
70+
config = config_builder.build() if config_builder else ConfigBuilder().build()
71+
state = state_builder.build() if state_builder else StateBuilder().build()
72+
return entrypoint_read(_source(catalog, config, state), config, catalog, state, expecting_exception)
73+
74+
75+
class SegmentsTest(TestCase):
76+
@HttpMocker()
77+
def test_when_read_then_extract_records(self, http_mocker: HttpMocker) -> None:
78+
http_mocker.get(
79+
HttpRequest("https://api.intercom.io/segments", query_params={"per_page": "150"}),
80+
_response().with_record(_record()).with_record(_record()).build(),
81+
)
82+
output = read(ConfigBuilder(), StateBuilder())
83+
assert len(output.records) == 2

0 commit comments

Comments
 (0)