Skip to content

chore: add 2025.05.0 and 2025.06.0 to integration test suite #418

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
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
2 changes: 2 additions & 0 deletions integration/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ PYTEST_ARGS ?= "-s"

# Versions
CONNECT_VERSIONS := \
2025.06.0 \
2025.05.0 \
2025.04.0 \
2025.03.0 \
2025.02.0 \
Expand Down
26 changes: 26 additions & 0 deletions integration/tests/posit/connect/fixtures.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from __future__ import annotations

import random
import string


def name() -> str:
"""Generate a unique name."""
return "".join(random.choices(string.ascii_letters, k=8))


def email() -> str:
"""Generate a unique email address."""
name = "".join(random.choices(string.ascii_lowercase, k=8))
return f"{name}@example.com"


def username() -> str:
"""Generate a unique username."""
return "".join(random.choices(string.ascii_letters, k=8))


def password() -> str:
"""Generate a secure password."""
characters = string.ascii_letters + string.digits + string.punctuation
return "".join(random.choices(characters, k=12)) # 12-character password
19 changes: 6 additions & 13 deletions integration/tests/posit/connect/oauth/test_associations.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from posit import connect

from .. import CONNECT_VERSION
from .. import CONNECT_VERSION, fixtures


@pytest.mark.skipif(
Expand All @@ -17,7 +17,7 @@ class TestAssociations:
def setup_class(cls):
cls.client = connect.Client()
cls.integration = cls.client.oauth.integrations.create(
name="example integration",
name=fixtures.name(),
description="integration description",
template="custom",
config={
Expand All @@ -32,7 +32,7 @@ def setup_class(cls):
)

cls.another_integration = cls.client.oauth.integrations.create(
name="another example integration",
name=fixtures.name(),
description="another integration description",
template="custom",
config={
Expand All @@ -48,26 +48,19 @@ def setup_class(cls):

# create content
# requires full bundle deployment to produce an interactive content type
cls.content = cls.client.content.create(name="example-flask-minimal")
cls.content = cls.client.content.create(name=fixtures.name())

# create bundle
path = Path("../../../../resources/connect/bundles/example-flask-minimal/bundle.tar.gz")
path = (Path(__file__).parent / path).resolve()
bundle = cls.content.bundles.create(str(path))

# deploy bundle
task = bundle.deploy()
task.wait_for()

cls.content.oauth.associations.update(cls.integration["guid"])

@classmethod
def teardown_class(cls):
cls.integration.delete()
cls.another_integration.delete()
assert len(cls.client.oauth.integrations.find()) == 0

cls.content.delete()
assert cls.client.content.count() == 0

def test_find_by_integration(self):
associations = self.integration.associations.find()
assert len(associations) == 1
Expand Down
26 changes: 10 additions & 16 deletions integration/tests/posit/connect/oauth/test_integrations.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from posit import connect

from .. import CONNECT_VERSION
from .. import CONNECT_VERSION, fixtures


@pytest.mark.skipif(
Expand All @@ -15,7 +15,7 @@ class TestIntegrations:
def setup_class(cls):
cls.client = connect.Client()
cls.integration = cls.client.oauth.integrations.create(
name="example integration",
name=fixtures.name(),
description="integration description",
template="custom",
config={
Expand All @@ -30,7 +30,7 @@ def setup_class(cls):
)

cls.another_integration = cls.client.oauth.integrations.create(
name="another example integration",
name=fixtures.name(),
description="another integration description",
template="custom",
config={
Expand All @@ -44,27 +44,21 @@ def setup_class(cls):
},
)

@classmethod
def teardown_class(cls):
cls.integration.delete()
cls.another_integration.delete()
assert len(cls.client.oauth.integrations.find()) == 0

def test_get(self):
result = self.client.oauth.integrations.get(self.integration["guid"])
assert result == self.integration

def test_find(self):
results = self.client.oauth.integrations.find()
assert len(results) == 2
assert results[0] == self.integration
assert results[1] == self.another_integration
assert len(results) >= 2
integration_guids = {integration["guid"] for integration in results}
assert self.integration["guid"] in integration_guids
assert self.another_integration["guid"] in integration_guids

def test_create_update_delete(self):
# create a new integration

integration = self.client.oauth.integrations.create(
name="new integration",
name=fixtures.name(),
description="new integration description",
template="custom",
config={
Expand All @@ -82,7 +76,7 @@ def test_create_update_delete(self):
assert created == integration

all_integrations = self.client.oauth.integrations.find()
assert len(all_integrations) == 3
assert len(all_integrations) >= 3

# update the new integration

Expand All @@ -94,4 +88,4 @@ def test_create_update_delete(self):

created.delete()
all_integrations_after_delete = self.client.oauth.integrations.find()
assert len(all_integrations_after_delete) == 2
assert len(all_integrations_after_delete) == len(all_integrations) - 1
4 changes: 0 additions & 4 deletions integration/tests/posit/connect/test_bundles.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,6 @@ def setup_class(cls):
)
cls.bundle_path = (Path(__file__).parent / bundle_path).resolve()

@classmethod
def teardown_class(cls):
cls.content.delete()

def test_create_bundle(self):
"""Test creating a bundle."""
bundle = self.content.bundles.create(str(self.bundle_path))
Expand Down
14 changes: 5 additions & 9 deletions integration/tests/posit/connect/test_content.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from posit import connect

from . import CONNECT_VERSION
from . import CONNECT_VERSION, fixtures


class TestContent:
Expand All @@ -14,13 +14,9 @@ def setup_class(cls):
cls.client = connect.Client()
cls.content = cls.client.content.create()

@classmethod
def teardown_class(cls):
cls.content.delete()
assert cls.client.content.count() == 0

def test_count(self):
assert self.client.content.count() == 1
# Assert that count works. We don't care what the count is.
assert self.client.content.count()

def test_get(self):
assert self.client.content.get(self.content["guid"]) == self.content
Expand Down Expand Up @@ -52,7 +48,7 @@ def test_content_item_owner_from_include(self):
)
def test_restart(self):
# create content
content = self.client.content.create(name="example-flask-minimal")
content = self.client.content.create(name=fixtures.name())
# create bundle
path = Path("../../../resources/connect/bundles/example-flask-minimal/bundle.tar.gz")
path = (Path(__file__).parent / path).resolve()
Expand All @@ -71,7 +67,7 @@ def test_restart(self):
)
def test_render(self):
# create content
content = self.client.content.create(name="example-quarto-minimal")
content = self.client.content.create(name=fixtures.name())
# create bundle
path = Path("../../../resources/connect/bundles/example-quarto-minimal/bundle.tar.gz")
path = (Path(__file__).parent / path).resolve()
Expand Down
47 changes: 20 additions & 27 deletions integration/tests/posit/connect/test_content_item_permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

from posit import connect

from .fixtures import email, name, password, username

if TYPE_CHECKING:
from posit.connect.content import ContentItem
from posit.connect.permissions import Permission
Expand All @@ -16,42 +18,33 @@ class TestContentPermissions:
@classmethod
def setup_class(cls):
cls.client = connect.Client()
cls.content = cls.client.content.create(name="example")
cls.content = cls.client.content.create(name=name())

cls.user_aron = cls.client.users.create(
username="permission_aron",
email="permission_aron@example.com",
password="permission_s3cur3p@ssword",
)
cls.user_bill = cls.client.users.create(
username="permission_bill",
email="permission_bill@example.com",
password="permission_s3cur3p@ssword",
cls.alice = cls.client.users.create(
username=name(),
email=email(),
password=password(),
)

cls.group_friends = cls.client.groups.create(name="Friends")

@classmethod
def teardown_class(cls):
cls.content.delete()
assert cls.client.content.count() == 0
cls.bob = cls.client.users.create(
username=username(),
email=email(),
password=password(),
)

cls.group_friends.delete()
assert cls.client.groups.count() == 0
cls.group = cls.client.groups.create(name=name())

def test_permissions_add_destroy(self):
assert self.client.groups.count() == 1
assert self.client.users.count() == 3
assert self.content.permissions.find() == []

# Add permissions
self.content.permissions.create(
principal_guid=self.user_aron["guid"],
principal_guid=self.alice["guid"],
principal_type="user",
role="viewer",
)
self.content.permissions.create(
principal_guid=self.group_friends["guid"],
principal_guid=self.group["guid"],
principal_type="group",
role="owner",
)
Expand All @@ -63,22 +56,22 @@ def assert_permissions_match_guids(permissions: list[Permission], objs_with_guid
# Prove they have been added
assert_permissions_match_guids(
self.content.permissions.find(),
[self.user_aron, self.group_friends],
[self.alice, self.group],
)

# Remove permissions (and from some that isn't an owner)
self.content.permissions.destroy(self.user_aron)
self.content.permissions.destroy(self.alice)
with pytest.raises(ValueError):
self.content.permissions.destroy(self.user_bill)
self.content.permissions.destroy(self.bob)

# Prove they have been removed
assert_permissions_match_guids(
self.content.permissions.find(),
[self.group_friends],
[self.group],
)

# Remove the last permission
self.content.permissions.destroy(self.group_friends)
self.content.permissions.destroy(self.group)

# Prove they have been removed
assert self.content.permissions.find() == []
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from posit.connect.content import ContentItem
from posit.connect.repository import ContentItemRepository

from . import CONNECT_VERSION
from . import CONNECT_VERSION, fixtures


class TestContentItemRepository:
Expand All @@ -14,12 +14,7 @@ class TestContentItemRepository:
@classmethod
def setup_class(cls):
cls.client = connect.Client()
cls.content = cls.client.content.create(name="example")

@classmethod
def teardown_class(cls):
cls.content.delete()
assert cls.client.content.count() == 0
cls.content = cls.client.content.create(name=fixtures.name())

@property
def repo_repository(self):
Expand Down
9 changes: 3 additions & 6 deletions integration/tests/posit/connect/test_env.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
from posit import connect

from . import fixtures


class TestEnvVars:
@classmethod
def setup_class(cls):
cls.client = connect.Client()
cls.content = cls.client.content.create(
name="Sample",
name=fixtures.name(),
description="Simple sample content for testing",
access_type="acl",
)

@classmethod
def teardown_class(cls):
cls.content.delete()
assert cls.client.content.count() == 0

def test_clear(self):
self.content.environment_variables.create("KEY", "value")
assert self.content.environment_variables.find() == ["KEY"]
Expand Down
5 changes: 0 additions & 5 deletions integration/tests/posit/connect/test_environments.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,6 @@ def setup_class(cls):
cluster_name="Kubernetes",
)

@classmethod
def teardown_class(cls):
cls.environment.destroy()
assert len(cls.client.environments) == 0

def test_find(self):
uid = self.environment["guid"]
environment = self.client.environments.find(uid)
Expand Down
Loading