diff --git a/src/sentry/testutils/asserts.py b/src/sentry/testutils/asserts.py index d48cd8f0b5be33..5ea303596247b0 100644 --- a/src/sentry/testutils/asserts.py +++ b/src/sentry/testutils/asserts.py @@ -2,9 +2,12 @@ from django.http import StreamingHttpResponse +from sentry.constants import ObjectStatus from sentry.integrations.types import EventLifecycleOutcome from sentry.models.auditlogentry import AuditLogEntry from sentry.models.commitfilechange import CommitFileChange +from sentry.models.organization import Organization +from sentry.models.project import Project from sentry.silo.base import SiloMode from sentry.testutils.silo import assume_test_silo_mode @@ -45,6 +48,23 @@ def assert_status_code(response, minimum: int, maximum: int | None = None): ) +def assert_existing_projects_status( + org: Organization, active_project_ids: list[int], deleted_project_ids: list[int] +): + all_projects = Project.objects.filter(organization=org).values_list("id", "status") + active_ids = [] + deleted_or_to_be_deleted_ids = [] + + for project_id, status in all_projects: + if status == ObjectStatus.ACTIVE: + active_ids.append(project_id) + else: + deleted_or_to_be_deleted_ids.append(project_id) + + assert active_ids == active_project_ids + assert deleted_or_to_be_deleted_ids == deleted_project_ids + + @assume_test_silo_mode(SiloMode.CONTROL) def org_audit_log_exists(**kwargs): assert kwargs diff --git a/tests/acceptance/test_create_project.py b/tests/acceptance/test_create_project.py index 08f97ed00c28d6..0251ec3d304981 100644 --- a/tests/acceptance/test_create_project.py +++ b/tests/acceptance/test_create_project.py @@ -1,5 +1,5 @@ -from selenium.webdriver.common.by import By - +from sentry.models.project import Project +from sentry.testutils.asserts import assert_existing_projects_status from sentry.testutils.cases import AcceptanceTestCase from sentry.testutils.silo import no_silo_test @@ -11,37 +11,42 @@ def setUp(self): self.user = self.create_user("foo@example.com") self.org = self.create_organization(name="Rowdy Tiger", owner=self.user) self.login_as(self.user) - self.path = f"/organizations/{self.org.slug}/projects/new/" - def test_no_teams(self): + def load_project_creation_page(self): self.browser.get(self.path) - self.browser.wait_until_not(".loading") + self.browser.wait_until('[aria-label="Create Project"]') + def test_no_teams(self): + self.load_project_creation_page() self.browser.click(None, "//*[text()='Select a Team']") self.browser.click('[data-test-id="create-team-option"]') self.browser.wait_until("[role='dialog']") input = self.browser.element('input[name="slug"]') input.send_keys("new-team") - self.browser.element("[role='dialog'] form").submit() - - # After creating team, should end up in onboarding screen self.browser.wait_until(xpath='//div[text()="#new-team"]') def test_select_correct_platform(self): self.create_team(organization=self.org, name="team three") - - self.browser.get(self.path) - self.browser.wait_until_not(".loading") - - self.browser.click('[data-test-id="platform-javascript-react"]') - self.browser.wait_until_not(".loading") + self.load_project_creation_page() + self.browser.click("[data-test-id='platform-javascript-react']") self.browser.click('[data-test-id="create-project"]') + self.browser.wait_until(xpath="//h2[text()='Configure React SDK']") - self.browser.wait_until_not(".loading") - self.browser.wait_until("h2") - - title = self.browser.find_element(by=By.CSS_SELECTOR, value="h2") - - assert "React" in title.text + def test_project_deletion_on_going_back(self): + self.create_team(organization=self.org, name="team three") + self.load_project_creation_page() + self.browser.click("[data-test-id='platform-php-laravel']") + self.browser.click('[data-test-id="create-project"]') + self.browser.wait_until(xpath="//h2[text()='Configure Laravel SDK']") + project1 = Project.objects.get(organization=self.org, slug="php-laravel") + self.browser.click('[aria-label="Back to Platform Selection"]') + self.browser.click("[data-test-id='platform-javascript-nextjs']") + self.browser.click('[data-test-id="create-project"]') + self.browser.wait_until(xpath="//h2[text()='Configure Next.js SDK']") + project2 = Project.objects.get(organization=self.org, slug="javascript-nextjs") + self.browser.back() + self.browser.get("/organizations/%s/projects/" % self.org.slug) + self.browser.wait_until(xpath='//h1[text()="Remain Calm"]') + assert_existing_projects_status(self.org, [], [project1.id, project2.id]) diff --git a/tests/acceptance/test_onboarding.py b/tests/acceptance/test_onboarding.py index 71d835f93c13d5..6f001a7b58e5b4 100644 --- a/tests/acceptance/test_onboarding.py +++ b/tests/acceptance/test_onboarding.py @@ -1,9 +1,11 @@ -from selenium.common.exceptions import TimeoutException +import pytest from sentry.models.project import Project +from sentry.testutils.asserts import assert_existing_projects_status from sentry.testutils.cases import AcceptanceTestCase from sentry.testutils.silo import no_silo_test -from sentry.utils.retries import TimedRetryPolicy + +pytestmark = pytest.mark.sentry_metrics @no_silo_test @@ -18,55 +20,69 @@ def setUp(self): ) self.login_as(self.user) - def test_onboarding(self): + def start_onboarding(self): self.browser.get("/onboarding/%s/" % self.org.slug) - - # Welcome step self.browser.wait_until('[data-test-id="onboarding-step-welcome"]') self.browser.click('[aria-label="Start"]') - - # Platform selection step self.browser.wait_until('[data-test-id="onboarding-step-select-platform"]') - @TimedRetryPolicy.wrap(timeout=5, exceptions=((TimeoutException,))) - def click_platform_select_name(browser): - # Select and create React project - browser.click('[data-test-id="platform-javascript-react"]') - - # Project getting started loads - browser.wait_until(xpath='//h2[text()="Configure React SDK"]') - - click_platform_select_name(self.browser) - - # Verify project was created for org - project = Project.objects.get(organization=self.org) + def test_onboarding_happy_path(self): + self.start_onboarding() + self.browser.click('[data-test-id="platform-javascript-react"]') + self.browser.wait_until(xpath='//h2[text()="Configure React SDK"]') + project = Project.objects.get(organization=self.org, slug="javascript-react") assert project.name == "javascript-react" assert project.platform == "javascript-react" - - # Click on back button + assert_existing_projects_status(self.org, [project.id], []) + + def test_project_deletion_on_going_back(self): + self.start_onboarding() + self.browser.click('[data-test-id="platform-javascript-nextjs"]') + self.browser.wait_until(xpath='//h2[text()="Configure Next.js SDK"]') + project1 = Project.objects.get(organization=self.org, slug="javascript-nextjs") + assert project1.name == "javascript-nextjs" + assert project1.platform == "javascript-nextjs" self.browser.click('[aria-label="Back"]') - - # Assert no deletion confirm dialog is shown - assert not self.browser.element_exists("[role='dialog']") - - # Platform selection step - self.browser.wait_until('[data-test-id="onboarding-step-select-platform"]') - - # Select generic platform + self.browser.click('[data-test-id="platform-javascript-react"]') + self.browser.wait_until(xpath='//h2[text()="Configure React SDK"]') + project2 = Project.objects.get(organization=self.org, slug="javascript-react") + assert project2.name == "javascript-react" + assert project2.platform == "javascript-react" + self.browser.back() + self.browser.click(xpath='//a[text()="Skip Onboarding"]') + self.browser.get("/organizations/%s/projects/" % self.org.slug) + self.browser.wait_until(xpath='//h1[text()="Remain Calm"]') + assert_existing_projects_status(self.org, [], [project1.id, project2.id]) + + def test_framework_modal_open_by_selecting_vanilla_platform(self): + self.start_onboarding() self.browser.click('[data-test-id="platform-javascript"]') - - # Modal is shown prompting to select a framework self.browser.wait_until(xpath='//h6[text()="Do you use a framework?"]') - - # Close modal self.browser.click('[aria-label="Close Modal"]') - - # Platform is not selected assert not self.browser.element_exists('[aria-label="Clear"]') - - # Click again on the modal and continue with the vanilla project self.browser.click('[data-test-id="platform-javascript"]') self.browser.click('[aria-label="Configure SDK"]') - - # Project getting started loads self.browser.wait_until(xpath='//h2[text()="Configure Browser JavaScript SDK"]') + project = Project.objects.get(organization=self.org, slug="javascript") + assert project.name == "javascript" + assert project.platform == "javascript" + assert_existing_projects_status(self.org, [project.id], []) + + def test_create_delete_create_same_platform(self): + "This test ensures that the regression fixed in PR https://github.com/getsentry/sentry/pull/87869 no longer occurs." + self.start_onboarding() + self.browser.click('[data-test-id="platform-javascript-nextjs"]') + self.browser.wait_until(xpath='//h2[text()="Configure Next.js SDK"]') + project1 = Project.objects.get(organization=self.org, slug="javascript-nextjs") + assert project1.name == "javascript-nextjs" + assert project1.platform == "javascript-nextjs" + self.browser.click('[aria-label="Back"]') + self.browser.click('[data-test-id="platform-javascript-nextjs"]') + self.browser.wait_until(xpath='//h2[text()="Configure Next.js SDK"]') + project2 = Project.objects.get(organization=self.org, slug="javascript-nextjs") + assert project2.name == "javascript-nextjs" + assert project2.platform == "javascript-nextjs" + self.browser.click(xpath='//a[text()="Skip Onboarding"]') + self.browser.get("/organizations/%s/projects/" % self.org.slug) + self.browser.wait_until("[data-test-id='javascript-nextjs']") + assert_existing_projects_status(self.org, [project2.id], [project1.id])