def setUp(self):
     super(IssueDetailsWorkflowTest, self).setUp()
     self.user = self.create_user("*****@*****.**")
     self.org = self.create_organization(owner=self.user,
                                         name="Rowdy Tiger")
     self.team = self.create_team(organization=self.org,
                                  name="Mariachi Band",
                                  members=[self.user])
     self.project = self.create_project(organization=self.org,
                                        teams=[self.team],
                                        name="Bengal")
     self.login_as(self.user)
     self.page = IssueDetailsPage(self.browser, self.client)
     self.dismiss_assistant()
예제 #2
0
 def setUp(self):
     super(IssueDetailsTest, self).setUp()
     patcher = patch("django.utils.timezone.now", return_value=now)
     patcher.start()
     self.addCleanup(patcher.stop)
     self.user = self.create_user("*****@*****.**")
     self.org = self.create_organization(owner=self.user,
                                         name="Rowdy Tiger")
     self.team = self.create_team(organization=self.org,
                                  name="Mariachi Band")
     self.project = self.create_project(organization=self.org,
                                        teams=[self.team],
                                        name="Bengal")
     self.login_as(self.user)
     self.page = IssueDetailsPage(self.browser, self.client)
예제 #3
0
 def setUp(self):
     super(IssueDetailsWorkflowTest, self).setUp()
     self.user = self.create_user('*****@*****.**')
     self.org = self.create_organization(
         owner=self.user, name='Rowdy Tiger')
     self.team = self.create_team(
         organization=self.org, name='Mariachi Band',
         members=[self.user])
     self.project = self.create_project(
         organization=self.org,
         teams=[self.team],
         name='Bengal',
     )
     self.login_as(self.user)
     self.page = IssueDetailsPage(self.browser, self.client)
예제 #4
0
class IssueTagValuesTest(AcceptanceTestCase, SnubaTestCase):
    def setUp(self):
        super().setUp()
        self.user = self.create_user("*****@*****.**")
        self.org = self.create_organization(owner=self.user,
                                            name="Rowdy Tiger")
        self.team = self.create_team(organization=self.org,
                                     name="Mariachi Band")
        self.project = self.create_project(organization=self.org,
                                           teams=[self.team],
                                           name="Bengal")
        self.login_as(self.user)
        self.page = IssueDetailsPage(self.browser, self.client)
        self.dismiss_assistant()

    def create_issue(self):
        event_data = load_data("javascript")
        event_data["timestamp"] = iso_format(before_now(minutes=1))
        event_data["tags"] = {"url": "http://example.org/path?key=value"}
        return self.store_event(data=event_data, project_id=self.project.id)

    def test_user_tag(self):
        event = self.create_issue()
        self.page.visit_tag_values(self.org.slug, event.group_id, "user")

        assert self.browser.find_element_by_partial_link_text(
            "*****@*****.**")
        self.browser.snapshot("issue details tag values - user")

    def test_url_tag(self):
        event = self.create_issue()
        self.page.visit_tag_values(self.org.slug, event.group_id, "url")

        assert self.browser.find_element_by_partial_link_text(
            "http://example.org")
        self.browser.snapshot("issue details tag values - url")
예제 #5
0
 def setUp(self):
     super(IssueDetailsWorkflowTest, self).setUp()
     self.user = self.create_user('*****@*****.**')
     self.org = self.create_organization(
         owner=self.user, name='Rowdy Tiger')
     self.team = self.create_team(
         organization=self.org, name='Mariachi Band',
         members=[self.user])
     self.project = self.create_project(
         organization=self.org,
         teams=[self.team],
         name='Bengal',
     )
     self.login_as(self.user)
     self.page = IssueDetailsPage(self.browser, self.client)
예제 #6
0
class IssueDetailsTest(AcceptanceTestCase, SnubaTestCase):
    def setUp(self):
        super().setUp()
        patcher = patch("django.utils.timezone.now", return_value=now)
        patcher.start()
        self.addCleanup(patcher.stop)
        self.user = self.create_user("*****@*****.**")
        self.org = self.create_organization(owner=self.user,
                                            name="Rowdy Tiger")
        self.team = self.create_team(organization=self.org,
                                     name="Mariachi Band")
        self.project = self.create_project(organization=self.org,
                                           teams=[self.team],
                                           name="Bengal")
        self.login_as(self.user)
        self.page = IssueDetailsPage(self.browser, self.client)
        self.dismiss_assistant()

    def create_sample_event(self,
                            platform,
                            default=None,
                            sample_name=None,
                            time=None):
        event_data = load_data(platform,
                               default=default,
                               sample_name=sample_name)
        event_data["event_id"] = "d964fdbd649a4cf8bfc35d18082b6b0e"

        # Only set these properties if we were given a time.
        # event processing will mark old time values as processing errors.
        if time:
            event_data["received"] = time.isoformat()

        # We need a fallback datetime for the event
        if time is None:
            time = now - timedelta(days=2)
            time = time.replace(hour=0, minute=0, second=0, microsecond=0)

        event_data["timestamp"] = time.isoformat()
        event = self.store_event(data=event_data,
                                 project_id=self.project.id,
                                 assert_no_errors=False)
        event.group.update(first_seen=datetime(2015,
                                               8,
                                               13,
                                               3,
                                               8,
                                               25,
                                               tzinfo=timezone.utc),
                           last_seen=time)
        return event

    def test_python_event(self):
        self.create_sample_event(platform="python")
        self.create_sample_event(platform="python")
        event = self.create_sample_event(platform="python")
        self.page.visit_issue(self.org.slug, event.group.id)

        # Wait for tag bars to load
        self.browser.wait_until_test_id("loaded-device-name")
        self.browser.snapshot("issue details python")

    def test_python_rawbody_event(self):
        event = self.create_sample_event(platform="python-rawbody")
        self.page.visit_issue(self.org.slug, event.group.id)
        self.browser.move_to(
            '[data-test-id="rich-http-content-body-section-pre"]')
        self.browser.snapshot("issue details python raw body")

    def test_python_formdata_event(self):
        event = self.create_sample_event(platform="python-formdata")
        self.page.visit_issue(self.org.slug, event.group.id)
        self.browser.snapshot("issue details python formdata")

    def test_pii_tooltips(self):
        event = self.create_sample_event(platform="pii-tooltips")
        self.page.visit_issue(self.org.slug, event.group.id)
        self.browser.snapshot("issue details pii tooltips")

    def test_cocoa_event(self):
        event = self.create_sample_event(platform="cocoa")
        self.page.visit_issue(self.org.slug, event.group.id)
        self.browser.snapshot("issue details cocoa")

    def test_cocoa_event_frame_line_hover(self):
        event = self.create_sample_event(platform="cocoa")
        self.page.visit_issue(self.org.slug, event.group.id)
        self.browser.wait_until_not(".loading")
        self.browser.move_to(".traceback li:nth-child(2)")
        self.browser.snapshot("issue details cocoa frame line hover")

    def test_unity_event(self):
        event = self.create_sample_event(default="unity", platform="csharp")
        self.page.visit_issue(self.org.slug, event.group.id)
        self.browser.snapshot("issue details unity")

    def test_android_event(self):
        event = self.create_sample_event(platform="android")
        self.page.visit_issue(self.org.slug, event.group.id)
        self.browser.snapshot("issue details android")

    def test_android_ndk_event(self):
        event = self.create_sample_event(default="android-ndk",
                                         platform="android-ndk")
        self.page.visit_issue(self.org.slug, event.group.id)
        self.browser.snapshot("issue details android-ndk")

    def test_aspnetcore_event(self):
        event = self.create_sample_event(default="aspnetcore",
                                         platform="csharp")
        self.page.visit_issue(self.org.slug, event.group.id)
        self.browser.snapshot("issue details aspnetcore")

    def test_javascript_specific_event(self):
        event = self.create_sample_event(platform="javascript")
        self.page.visit_issue(self.org.slug, event.group.id)
        self.browser.snapshot("issue details javascript - event details")

        self.browser.click('[aria-label="curl"]')
        self.browser.snapshot(
            "issue details javascript - event details - curl command")

    def test_rust_event(self):
        # TODO: This should become its own "rust" platform type
        event = self.create_sample_event(platform="native", sample_name="Rust")
        self.page.visit_issue(self.org.slug, event.group.id)

        self.browser.snapshot("issue details rust")

    def test_cordova_event(self):
        event = self.create_sample_event(platform="cordova")
        self.page.visit_issue(self.org.slug, event.group.id)

        self.browser.snapshot("issue details cordova")

    def test_stripped_event(self):
        event = self.create_sample_event(platform="pii")
        self.page.visit_issue(self.org.slug, event.group.id)
        self.browser.snapshot("issue details pii stripped")

    def test_empty_exception(self):
        event = self.create_sample_event(platform="empty-exception")
        self.page.visit_issue(self.org.slug, event.group.id)
        self.browser.snapshot("issue details empty exception")

    def test_empty_stacktrace(self):
        event = self.create_sample_event(platform="empty-stacktrace")
        self.page.visit_issue(self.org.slug, event.group.id)
        self.browser.snapshot("issue details empty stacktrace")

    def test_invalid_interfaces(self):
        event = self.create_sample_event(platform="invalid-interfaces")
        self.page.visit_issue(self.org.slug, event.group.id)

        self.browser.click('[data-test-id="event-error-toggle"]')
        self.browser.wait_until_test_id("event-error-details")
        self.browser.snapshot("issue details invalid interfaces")

    def test_activity_page(self):
        event = self.create_sample_event(platform="python")
        self.page.visit_issue(self.org.slug, event.group.id)
        self.page.go_to_subtab("Activity")

        self.browser.wait_until_test_id("activity-item")
        self.browser.blur()
        self.browser.snapshot("issue activity python")

    def test_resolved(self):
        event = self.create_sample_event(platform="python")
        self.page.visit_issue(self.org.slug, event.group.id)
        self.page.resolve_issue()

        self.browser.snapshot("issue details resolved")

    def test_ignored(self):
        event = self.create_sample_event(platform="python")
        self.page.visit_issue(self.org.slug, event.group.id)
        self.page.ignore_issue()

        self.browser.snapshot("issue details ignored")

    def test_exception_and_no_threads_event(self):
        event = self.create_sample_event(platform="exceptions-and-no-threads")
        self.page.visit_issue(self.org.slug, event.group.id)
        self.browser.snapshot("issue details exceptions and no threads")

    def test_exception_with_stack_trace_and_crashed_thread_without_stack_trace_event(
            self):
        event = self.create_sample_event(
            platform=
            "exception-with-stack-trace-and-crashed-thread-without-stack-trace"
        )
        self.page.visit_issue(self.org.slug, event.group.id)
        self.browser.snapshot(
            "issue details exception with stack trace and crashed thread without stack trace"
        )

    def test_exception_without_stack_trace_and_crashed_thread_with_stack_trace_event(
            self):
        event = self.create_sample_event(
            platform=
            "exception-without-stack-trace-and-crashed-thread-with-stack-trace"
        )
        self.page.visit_issue(self.org.slug, event.group.id)
        self.browser.snapshot(
            "issue details exception without stack trace and crashed thread with stack trace"
        )

    def test_exception_with_stack_trace_and_crashed_thread_with_stack_trace_event(
            self):
        event = self.create_sample_event(
            platform=
            "exception-with-stack-trace-and-crashed-thread-with-stack-trace")
        self.page.visit_issue(self.org.slug, event.group.id)
        self.browser.snapshot(
            "issue details exception with stack trace and crashed thread with stack trace"
        )
예제 #7
0
class IssueDetailsWorkflowTest(AcceptanceTestCase, SnubaTestCase):
    def setUp(self):
        super(IssueDetailsWorkflowTest, self).setUp()
        self.user = self.create_user("*****@*****.**")
        self.org = self.create_organization(owner=self.user,
                                            name="Rowdy Tiger")
        self.team = self.create_team(organization=self.org,
                                     name="Mariachi Band",
                                     members=[self.user])
        self.project = self.create_project(organization=self.org,
                                           teams=[self.team],
                                           name="Bengal")
        self.login_as(self.user)
        self.page = IssueDetailsPage(self.browser, self.client)
        self.dismiss_assistant()

    def create_sample_event(self, platform, default=None, sample_name=None):
        event_data = load_data(platform,
                               default=default,
                               sample_name=sample_name)
        event_data["event_id"] = "d964fdbd649a4cf8bfc35d18082b6b0e"
        event = self.store_event(data=event_data,
                                 project_id=self.project.id,
                                 assert_no_errors=False)
        event.group.update(
            first_seen=datetime(2015, 8, 13, 3, 8, 25, tzinfo=timezone.utc),
            last_seen=datetime(2016, 1, 13, 3, 8, 25, tzinfo=timezone.utc),
        )
        return event

    def test_resolve_basic(self):
        event = self.create_sample_event(platform="python")
        self.page.visit_issue(self.org.slug, event.group.id)
        self.page.resolve_issue()

        res = self.page.api_issue_get(event.group.id)
        assert res.status_code == 200, res
        assert res.data["status"] == "resolved"

    def test_ignore_basic(self):
        event = self.create_sample_event(platform="python")
        self.page.visit_issue(self.org.slug, event.group.id)
        self.page.ignore_issue()

        res = self.page.api_issue_get(event.group.id)
        assert res.status_code == 200, res
        assert res.data["status"] == "ignored"

    def test_bookmark(self):
        event = self.create_sample_event(platform="python")
        self.page.visit_issue(self.org.slug, event.group.id)
        self.page.bookmark_issue()

        res = self.page.api_issue_get(event.group.id)
        assert res.status_code == 200, res
        assert res.data["isBookmarked"]

    def test_assign_issue(self):
        event = self.create_sample_event(platform="python")
        self.page.visit_issue(self.org.slug, event.group.id)
        self.page.assign_to(self.user.email)

        res = self.page.api_issue_get(event.group.id)
        assert res.status_code == 200, res
        assert res.data["assignedTo"]

    def test_create_comment(self):
        event = self.create_sample_event(platform="python")
        self.page.visit_issue(self.org.slug, event.group.id)
        self.page.go_to_subtab("Activity")

        form = self.page.find_comment_form()
        form.find_element_by_tag_name("textarea").send_keys("this looks bad")
        form.submit()

        assert self.page.has_comment("this looks bad")
예제 #8
0
class OrganizationGlobalHeaderTest(AcceptanceTestCase, SnubaTestCase):
    def setUp(self):
        super().setUp()
        self.user = self.create_user("*****@*****.**")
        self.org = self.create_organization(owner=self.user,
                                            name="Rowdy Tiger")
        self.team = self.create_team(organization=self.org,
                                     name="Mariachi Band",
                                     members=[self.user])

        self.project_1 = self.create_project(organization=self.org,
                                             teams=[self.team],
                                             name="Bengal")
        self.project_2 = self.create_project(organization=self.org,
                                             teams=[self.team],
                                             name="Sumatra")
        self.project_3 = self.create_project(organization=self.org,
                                             teams=[self.team],
                                             name="Siberian")

        self.create_environment(name="development", project=self.project_1)
        self.create_environment(name="production", project=self.project_1)
        self.create_environment(name="visible",
                                project=self.project_1,
                                is_hidden=False)
        self.create_environment(name="not visible",
                                project=self.project_1,
                                is_hidden=True)
        self.create_environment(name="dev", project=self.project_2)
        self.create_environment(name="prod", project=self.project_2)

        self.login_as(self.user)
        self.issues_list = IssueListPage(self.browser, self.client)
        self.issue_details = IssueDetailsPage(self.browser, self.client)

    def create_issues(self):
        self.issue_1 = self.store_event(
            data={
                "event_id": "a" * 32,
                "message": "oh no",
                "timestamp": iso_format(event_time),
                "fingerprint": ["group-1"],
            },
            project_id=self.project_1.id,
        )
        self.issue_2 = self.store_event(
            data={
                "event_id": "b" * 32,
                "message": "oh snap",
                "timestamp": iso_format(event_time),
                "fingerprint": ["group-2"],
                "environment": "prod",
            },
            project_id=self.project_2.id,
        )

    def test_global_selection_header_dropdown(self):
        self.dismiss_assistant()
        self.project.update(first_event=timezone.now())
        self.issues_list.visit_issue_list(
            self.org.slug,
            query="?query=assigned%3Ame&project=" + str(self.project_1.id))
        self.browser.wait_until_test_id("awaiting-events")

        self.browser.click('[data-test-id="global-header-project-selector"]')
        self.browser.snapshot("globalSelectionHeader - project selector")

        self.browser.click(
            '[data-test-id="global-header-environment-selector"]')
        self.browser.snapshot("globalSelectionHeader - environment selector")

        self.browser.click('[data-test-id="global-header-timerange-selector"]')
        self.browser.snapshot("globalSelectionHeader - timerange selector")

    @pytest.mark.skip(reason="Has been flaky lately.")
    def test_global_selection_header_loads_with_correct_project(self):
        """
        Global Selection Header should:
        1) load project from URL if it exists
        2) enforce a single project if loading issues list with no project in URL
           a) last selected project via local storage if it exists
           b) otherwise need to just select first project
        """
        self.create_issues()
        # No project id in URL, selects first project
        self.issues_list.visit_issue_list(self.org.slug)
        assert f"project={self.project_1.id}" in self.browser.current_url
        assert self.issues_list.global_selection.get_selected_project_slug(
        ) == self.project_1.slug

        # Uses project id in URL
        self.issues_list.visit_issue_list(
            self.org.slug, query=f"?project={self.project_2.id}")
        assert f"project={self.project_2.id}" in self.browser.current_url
        assert self.issues_list.global_selection.get_selected_project_slug(
        ) == self.project_2.slug

        # reloads page with no project id in URL, selects first project
        self.issues_list.visit_issue_list(self.org.slug)
        assert f"project={self.project_1.id}" in self.browser.current_url
        assert self.issues_list.global_selection.get_selected_project_slug(
        ) == self.project_1.slug

        # can select a different project
        self.issues_list.global_selection.select_project_by_slug(
            self.project_3.slug)
        self.issues_list.wait_until_loaded()
        assert f"project={self.project_3.id}" in self.browser.current_url
        assert self.issues_list.global_selection.get_selected_project_slug(
        ) == self.project_3.slug

        # reloading page with no project id in URL after previously
        # selecting an explicit project should load previously selected project
        # from local storage
        # TODO check environment as well
        self.issues_list.visit_issue_list(self.org.slug)
        self.issues_list.wait_until_loaded()
        assert f"project={self.project_3.id}" in self.browser.current_url

    def test_global_selection_header_navigates_with_browser_back_button(self):
        """
        Global Selection Header should:
        1) load project from URL if it exists
        2) enforce a single project if loading issues list with no project in URL
           a) last selected project via local storage if it exists
           b) otherwise need to just select first project
        """
        self.create_issues()
        # Issues list with project 1 selected
        self.issues_list.visit_issue_list(self.org.slug,
                                          query="?project=" +
                                          str(self.project_1.id))
        self.issues_list.visit_issue_list(self.org.slug)
        assert self.issues_list.global_selection.get_selected_project_slug(
        ) == self.project_1.slug

        # selects a different project
        self.issues_list.global_selection.select_project_by_slug(
            self.project_3.slug)
        self.issues_list.wait_until_loaded()
        assert f"project={self.project_3.id}" in self.browser.current_url
        assert self.issues_list.global_selection.get_selected_project_slug(
        ) == self.project_3.slug

        # simulate pressing the browser back button
        self.browser.back()
        self.issues_list.wait_until_loaded()
        assert f"project={self.project_1.id}" in self.browser.current_url
        assert self.issues_list.global_selection.get_selected_project_slug(
        ) == self.project_1.slug

    def test_global_selection_header_updates_environment_with_browser_navigation_buttons(
            self):
        """
        Global Selection Header should:
        1) load project from URL if it exists
        2) clear the current environment if the user clicks clear
        3) reload the environment from URL if it exists on browser navigation
        """
        with self.feature("organizations:global-views"):
            self.create_issues()
            """
            set up workflow:
            1) environment=All environments
            2) environment=prod
            3) environment=All environments
            """
            self.issues_list.visit_issue_list(self.org.slug)
            self.issues_list.wait_until_loaded()
            assert "environment=" not in self.browser.current_url
            assert (self.issue_details.global_selection.
                    get_selected_environment() == "All Environments")

            self.browser.click(
                '[data-test-id="global-header-environment-selector"]')
            self.browser.click('[data-test-id="environment-prod"]')
            self.issues_list.wait_until_loaded()
            assert "environment=prod" in self.browser.current_url
            assert self.issue_details.global_selection.get_selected_environment(
            ) == "prod"

            self.browser.click(
                '[data-test-id="global-header-environment-selector"] > svg')
            self.issues_list.wait_until_loaded()
            assert "environment=" not in self.browser.current_url
            assert (self.issue_details.global_selection.
                    get_selected_environment() == "All Environments")
            """
            navigate back through history to the beginning
            1) environment=All Environments -> environment=prod
            2) environment=prod -> environment=All Environments
            """
            self.browser.back()
            self.issues_list.wait_until_loaded()
            assert "environment=prod" in self.browser.current_url
            assert self.issue_details.global_selection.get_selected_environment(
            ) == "prod"

            self.browser.back()
            self.issues_list.wait_until_loaded()
            assert "environment=" not in self.browser.current_url
            assert (self.issue_details.global_selection.
                    get_selected_environment() == "All Environments")
            """
            navigate forward through history to the end
            1) environment=All Environments -> environment=prod
            2) environment=prod -> environment=All Environments
            """
            self.browser.forward()
            self.issues_list.wait_until_loaded()
            assert "environment=prod" in self.browser.current_url
            assert self.issue_details.global_selection.get_selected_environment(
            ) == "prod"

            self.browser.forward()
            self.issues_list.wait_until_loaded()
            assert "environment=" not in self.browser.current_url
            assert (self.issue_details.global_selection.
                    get_selected_environment() == "All Environments")

    def test_global_selection_header_loads_with_correct_project_with_multi_project(
            self):
        """
        Global Selection Header should:
        1) load project from URL if it exists
        2) load last selected projects via local storage if it exists
        3) otherwise can search within "my projects"
        """
        with self.feature("organizations:global-views"):
            self.create_issues()
            # No project id in URL, is "my projects"
            self.issues_list.visit_issue_list(self.org.slug)
            assert "project=" not in self.browser.current_url
            assert self.issues_list.global_selection.get_selected_project_slug(
            ) == "My Projects"
            assert self.browser.get_local_storage_item(
                f"global-selection:{self.org.slug}") is None

            # Uses project id in URL
            self.issues_list.visit_issue_list(
                self.org.slug, query=f"?project={self.project_2.id}")
            assert f"project={self.project_2.id}" in self.browser.current_url
            assert (self.issues_list.global_selection.
                    get_selected_project_slug() == self.project_2.slug)

            # should not be in local storage
            assert self.browser.get_local_storage_item(
                f"global-selection:{self.org.slug}") is None

            # reloads page with no project id in URL, remains "My Projects" because
            # there has been no explicit project selection via UI
            self.issues_list.visit_issue_list(self.org.slug)
            assert "project=" not in self.browser.current_url
            assert self.issues_list.global_selection.get_selected_project_slug(
            ) == "My Projects"

            # can select a different project
            self.issues_list.global_selection.select_project_by_slug(
                self.project_3.slug)
            self.issues_list.wait_until_loaded()
            assert f"project={self.project_3.id}" in self.browser.current_url
            assert (self.issues_list.global_selection.
                    get_selected_project_slug() == self.project_3.slug)

            self.issues_list.global_selection.select_date("Last 24 hours")
            self.issues_list.wait_until_loaded()
            assert "statsPeriod=24h" in self.browser.current_url
            # This doesn't work because we treat as dynamic data in CI
            # assert self.issues_list.global_selection.get_selected_date() == "Last 24 hours"

            # reloading page with no project id in URL after previously
            # selecting an explicit project should load previously selected project
            # from local storage
            self.issues_list.visit_issue_list(self.org.slug)
            self.issues_list.wait_until_loaded()
            # TODO check environment as well
            assert f"project={self.project_3.id}" in self.browser.current_url
            assert (self.issues_list.global_selection.
                    get_selected_project_slug() == self.project_3.slug)

    @patch("django.utils.timezone.now")
    def test_issues_list_to_details_and_back_with_all_projects(self, mock_now):
        """
        If user has access to the `global-views` feature, which allows selecting multiple projects,
        they should be able to visit issues list with no project in URL and list issues
        for all projects they are members of.

        They should also be able to open an issue and then navigate back to still see
        "My Projects" in issues list.
        """
        with self.feature("organizations:global-views"):
            mock_now.return_value = datetime.utcnow().replace(tzinfo=pytz.utc)
            self.create_issues()
            self.issues_list.visit_issue_list(self.org.slug)
            self.issues_list.wait_for_issue()

            assert "project=" not in self.browser.current_url
            assert self.issues_list.global_selection.get_selected_project_slug(
            ) == "My Projects"

            # select the issue
            self.issues_list.navigate_to_issue(1)

            # going back to issues list should not have the issue's project id in url
            self.issues_list.issue_details.go_back_to_issues()
            self.issues_list.wait_for_issue()

            # project id should remain *NOT* in URL
            assert "project=" not in self.browser.current_url
            assert self.issues_list.global_selection.get_selected_project_slug(
            ) == "My Projects"

            # can select a different project
            self.issues_list.global_selection.select_project_by_slug(
                self.project_3.slug)
            self.issues_list.wait_until_loaded()
            assert f"project={self.project_3.id}" in self.browser.current_url
            assert (self.issues_list.global_selection.
                    get_selected_project_slug() == self.project_3.slug)

    @patch("django.utils.timezone.now")
    def test_issues_list_to_details_and_back_with_initial_project(
            self, mock_now):
        """
        If user has a project defined in URL, if they visit an issue and then
        return back to issues list, that project id should still exist in URL
        """
        mock_now.return_value = datetime.utcnow().replace(tzinfo=pytz.utc)
        self.create_issues()
        self.issues_list.visit_issue_list(
            self.org.slug, query=f"?project={self.project_2.id}")
        self.issues_list.wait_for_issue()

        assert f"project={self.project_2.id}" in self.browser.current_url
        assert self.issues_list.global_selection.get_selected_project_slug(
        ) == self.project_2.slug

        # select the issue
        self.issues_list.navigate_to_issue(1)

        # project id should remain in URL
        assert f"project={self.project_2.id}" in self.browser.current_url

        # going back to issues list should keep project in URL
        self.issues_list.issue_details.go_back_to_issues()
        self.issues_list.wait_for_issue()

        # project id should remain in URL
        assert f"project={self.project_2.id}" in self.browser.current_url

        # can select a different project
        self.issues_list.global_selection.select_project_by_slug(
            self.project_3.slug)
        self.issues_list.wait_until_loaded()
        assert f"project={self.project_3.id}" in self.browser.current_url
        assert self.issues_list.global_selection.get_selected_project_slug(
        ) == self.project_3.slug

    @patch("django.utils.timezone.now")
    def test_issue_details_to_stream_with_initial_env_no_project(
            self, mock_now):
        """
        Visiting issue details directly with no project but with an environment defined in URL.
        When navigating back to issues stream, should keep environment and project in context.
        """

        mock_now.return_value = datetime.utcnow().replace(tzinfo=pytz.utc)
        self.create_issues()
        self.issue_details.visit_issue_in_environment(self.org.slug,
                                                      self.issue_2.group.id,
                                                      "prod")

        # Make sure issue's project is in URL and in header
        assert f"project={self.project_2.id}" in self.browser.current_url
        assert self.issues_list.global_selection.get_selected_project_slug(
        ) == self.project_2.slug

        # environment should be in URL and header
        assert "environment=prod" in self.browser.current_url
        assert self.issue_details.global_selection.get_selected_environment(
        ) == "prod"

        # going back to issues list should keep project and environment in URL
        self.issue_details.go_back_to_issues()
        self.issues_list.wait_for_issue()

        # project id should remain in URL
        assert f"project={self.project_2.id}" in self.browser.current_url
        assert "environment=prod" in self.browser.current_url
        assert self.issues_list.global_selection.get_selected_project_slug(
        ) == self.project_2.slug
        assert self.issue_details.global_selection.get_selected_environment(
        ) == "prod"

    @patch("django.utils.timezone.now")
    def test_issue_details_to_stream_with_initial_env_no_project_with_multi_project_feature(
            self, mock_now):
        """
        Visiting issue details directly with no project but with an environment defined in URL.
        When navigating back to issues stream, should keep environment and project in context.
        """

        with self.feature("organizations:global-views"):
            mock_now.return_value = datetime.utcnow().replace(tzinfo=pytz.utc)
            self.create_issues()
            self.issue_details.visit_issue_in_environment(
                self.org.slug, self.issue_2.group.id, "prod")

            # Make sure issue's project is in URL and in header
            assert f"project={self.project_2.id}" in self.browser.current_url
            assert (self.issues_list.global_selection.
                    get_selected_project_slug() == self.project_2.slug)

            # environment should be in URL and header
            assert "environment=prod" in self.browser.current_url
            assert self.issue_details.global_selection.get_selected_environment(
            ) == "prod"

            # can change environment so that when you navigate back to issues stream,
            # it keeps environment as selected

            # going back to issues list should keep project and environment in URL
            self.issue_details.go_back_to_issues()
            self.issues_list.wait_for_issue()

            # project id should remain in URL
            assert f"project={self.project_2.id}" in self.browser.current_url
            assert "environment=prod" in self.browser.current_url
            assert (self.issues_list.global_selection.
                    get_selected_project_slug() == self.project_2.slug)
            assert self.issue_details.global_selection.get_selected_environment(
            ) == "prod"
예제 #9
0
class IssueDetailsWorkflowTest(AcceptanceTestCase, SnubaTestCase):
    def setUp(self):
        super(IssueDetailsWorkflowTest, self).setUp()
        self.user = self.create_user('*****@*****.**')
        self.org = self.create_organization(
            owner=self.user, name='Rowdy Tiger')
        self.team = self.create_team(
            organization=self.org, name='Mariachi Band',
            members=[self.user])
        self.project = self.create_project(
            organization=self.org,
            teams=[self.team],
            name='Bengal',
        )
        self.login_as(self.user)
        self.page = IssueDetailsPage(self.browser, self.client)

    def create_sample_event(self, platform, default=None, sample_name=None):
        event_data = load_data(platform, default=default,
                               sample_name=sample_name)
        event_data['event_id'] = 'd964fdbd649a4cf8bfc35d18082b6b0e'
        event = self.store_event(
            data=event_data,
            project_id=self.project.id,
            assert_no_errors=False,
        )
        event.datetime = datetime(2017, 9, 6, 0, 0)
        event.save()
        event.group.update(
            first_seen=datetime(2015, 8, 13, 3, 8, 25, tzinfo=timezone.utc),
            last_seen=datetime(2016, 1, 13, 3, 8, 25, tzinfo=timezone.utc),
        )
        return event

    def test_resolve_basic(self):
        event = self.create_sample_event(
            platform='python',
        )
        self.page.visit_issue(self.org.slug, event.group.id)
        self.page.resolve_issue()

        res = self.page.api_issue_get(event.group.id)
        assert res.status_code == 200, res
        assert res.data['status'] == 'resolved'

    def test_ignore_basic(self):
        event = self.create_sample_event(
            platform='python',
        )
        self.page.visit_issue(self.org.slug, event.group.id)
        self.page.ignore_issue()

        res = self.page.api_issue_get(event.group.id)
        assert res.status_code == 200, res
        assert res.data['status'] == 'ignored'

    def test_bookmark(self):
        event = self.create_sample_event(
            platform='python',
        )
        self.page.visit_issue(self.org.slug, event.group.id)
        self.page.bookmark_issue()

        res = self.page.api_issue_get(event.group.id)
        assert res.status_code == 200, res
        assert res.data['isBookmarked']

    def test_assign_issue(self):
        event = self.create_sample_event(
            platform='python',
        )
        self.page.visit_issue(self.org.slug, event.group.id)
        self.page.assign_to(self.user.email)

        res = self.page.api_issue_get(event.group.id)
        assert res.status_code == 200, res
        assert res.data['assignedTo']

    def test_create_comment(self):
        event = self.create_sample_event(
            platform='python',
        )
        self.page.visit_issue(self.org.slug, event.group.id)
        self.page.go_to_subtab('Comments')

        form = self.page.find_comment_form()
        form.find_element_by_tag_name('textarea').send_keys('this looks bad')
        form.submit()

        assert self.page.has_comment('this looks bad')
예제 #10
0
class IssueDetailsWorkflowTest(AcceptanceTestCase, SnubaTestCase):
    def setUp(self):
        super(IssueDetailsWorkflowTest, self).setUp()
        self.user = self.create_user('*****@*****.**')
        self.org = self.create_organization(
            owner=self.user, name='Rowdy Tiger')
        self.team = self.create_team(
            organization=self.org, name='Mariachi Band',
            members=[self.user])
        self.project = self.create_project(
            organization=self.org,
            teams=[self.team],
            name='Bengal',
        )
        self.login_as(self.user)
        self.page = IssueDetailsPage(self.browser, self.client)

    def create_sample_event(self, platform, default=None, sample_name=None):
        event_data = load_data(platform, default=default,
                               sample_name=sample_name)
        event_data['event_id'] = 'd964fdbd649a4cf8bfc35d18082b6b0e'
        event = self.store_event(
            data=event_data,
            project_id=self.project.id,
            assert_no_errors=False,
        )
        event.datetime = datetime(2017, 9, 6, 0, 0)
        event.save()
        event.group.update(
            first_seen=datetime(2015, 8, 13, 3, 8, 25, tzinfo=timezone.utc),
            last_seen=datetime(2016, 1, 13, 3, 8, 25, tzinfo=timezone.utc),
        )
        return event

    def test_resolve_basic(self):
        event = self.create_sample_event(
            platform='python',
        )
        with self.feature('organizations:sentry10'):
            self.page.visit_issue(self.org.slug, event.group.id)
            self.page.resolve_issue()

            res = self.page.api_issue_get(event.group.id)
            assert res.status_code == 200, res
            assert res.data['status'] == 'resolved'

    def test_ignore_basic(self):
        event = self.create_sample_event(
            platform='python',
        )
        self.page.visit_issue(self.org.slug, event.group.id)
        self.page.ignore_issue()

        res = self.page.api_issue_get(event.group.id)
        assert res.status_code == 200, res
        assert res.data['status'] == 'ignored'

    def test_bookmark(self):
        event = self.create_sample_event(
            platform='python',
        )
        self.page.visit_issue(self.org.slug, event.group.id)
        self.page.bookmark_issue()

        res = self.page.api_issue_get(event.group.id)
        assert res.status_code == 200, res
        assert res.data['isBookmarked']

    def test_assign_issue(self):
        event = self.create_sample_event(
            platform='python',
        )
        self.page.visit_issue(self.org.slug, event.group.id)
        self.page.assign_to(self.user.email)

        res = self.page.api_issue_get(event.group.id)
        assert res.status_code == 200, res
        assert res.data['assignedTo']

    def test_create_comment(self):
        event = self.create_sample_event(
            platform='python',
        )
        self.page.visit_issue(self.org.slug, event.group.id)
        self.page.go_to_subtab('Comments')

        form = self.page.find_comment_form()
        form.find_element_by_tag_name('textarea').send_keys('this looks bad')
        form.submit()

        assert self.page.has_comment('this looks bad')