|
@@ -1,132 +1,92 @@
|
|
|
-import {render, screen} from 'sentry-test/reactTestingLibrary';
|
|
|
+import {browserHistory} from 'react-router';
|
|
|
|
|
|
-import {PageFilters} from 'sentry/types';
|
|
|
+import {render, screen, userEvent} from 'sentry-test/reactTestingLibrary';
|
|
|
+
|
|
|
+import useDismissAlert from 'sentry/utils/useDismissAlert';
|
|
|
import {useLocation} from 'sentry/utils/useLocation';
|
|
|
-import usePageFilters from 'sentry/utils/usePageFilters';
|
|
|
-import useProjects from 'sentry/utils/useProjects';
|
|
|
-import {useProjectSdkUpdates} from 'sentry/utils/useProjectSdkUpdates';
|
|
|
import {ReplaySearchAlert} from 'sentry/views/replays/list/replaySearchAlert';
|
|
|
|
|
|
-jest.mock('sentry/utils/useProjects');
|
|
|
jest.mock('sentry/utils/useLocation');
|
|
|
-jest.mock('sentry/utils/usePageFilters');
|
|
|
-jest.mock('sentry/utils/useProjectSdkUpdates');
|
|
|
+jest.mock('sentry/utils/useDismissAlert');
|
|
|
+jest.mock('react-router');
|
|
|
|
|
|
-const mockUseProjects = useProjects as jest.MockedFunction<typeof useProjects>;
|
|
|
-const mockUsePageFilters = usePageFilters as jest.MockedFunction<typeof usePageFilters>;
|
|
|
-const mockUseLocation = useLocation as jest.MockedFunction<typeof useLocation>;
|
|
|
-const mockUseProjectSdkUpdates = useProjectSdkUpdates as jest.MockedFunction<
|
|
|
- typeof useProjectSdkUpdates
|
|
|
+const mockBrowserHistoryPush = browserHistory.push as jest.MockedFunction<
|
|
|
+ typeof browserHistory.push
|
|
|
+>;
|
|
|
+const mockUseDismissAlert = useDismissAlert as jest.MockedFunction<
|
|
|
+ typeof useDismissAlert
|
|
|
>;
|
|
|
|
|
|
-const project = TestStubs.Project();
|
|
|
+const mockUseLocation = useLocation as jest.MockedFunction<typeof useLocation>;
|
|
|
|
|
|
function getMockContext() {
|
|
|
return TestStubs.routerContext([{}]);
|
|
|
}
|
|
|
|
|
|
-function mockLocationReturn(query: string = ''): ReturnType<typeof useLocation> {
|
|
|
- return {
|
|
|
- query: {
|
|
|
- query,
|
|
|
- },
|
|
|
- pathname: '',
|
|
|
- search: '',
|
|
|
- hash: '',
|
|
|
- state: {},
|
|
|
- action: 'PUSH',
|
|
|
- key: '',
|
|
|
- };
|
|
|
-}
|
|
|
-
|
|
|
describe('ReplaySearchAlert', () => {
|
|
|
beforeEach(() => {
|
|
|
- mockUseProjects.mockReturnValue({
|
|
|
- projects: [project],
|
|
|
- fetching: false,
|
|
|
- hasMore: false,
|
|
|
- onSearch: () => Promise.resolve(),
|
|
|
- fetchError: null,
|
|
|
- initiallyLoaded: false,
|
|
|
- placeholders: [],
|
|
|
+ mockUseDismissAlert.mockReturnValue({
|
|
|
+ dismiss: () => {},
|
|
|
+ isDismissed: false,
|
|
|
});
|
|
|
-
|
|
|
- mockUsePageFilters.mockReturnValue({
|
|
|
- selection: {
|
|
|
- // for some reason project.id selections are numbers, but elsewhere project.id is string
|
|
|
- projects: [Number(project.id)],
|
|
|
- datetime: {} as PageFilters['datetime'],
|
|
|
- environments: [],
|
|
|
- },
|
|
|
- isReady: true,
|
|
|
- shouldPersist: true,
|
|
|
- desyncedFilters: new Set(),
|
|
|
- pinnedFilters: new Set(),
|
|
|
+ mockUseLocation.mockReturnValue({
|
|
|
+ pathname: '',
|
|
|
+ query: {},
|
|
|
+ search: '',
|
|
|
+ key: '',
|
|
|
+ state: {},
|
|
|
+ action: 'PUSH',
|
|
|
+ hash: '',
|
|
|
});
|
|
|
+ });
|
|
|
|
|
|
- mockUseLocation.mockReturnValue(mockLocationReturn());
|
|
|
-
|
|
|
- mockUseProjectSdkUpdates.mockReturnValue({
|
|
|
- type: 'initial',
|
|
|
+ it('should render search alert by w/ Try Now CTA by default', () => {
|
|
|
+ const {container} = render(<ReplaySearchAlert needSdkUpdates={false} />, {
|
|
|
+ context: getMockContext(),
|
|
|
});
|
|
|
+ expect(container).not.toBeEmptyDOMElement();
|
|
|
+ expect(container).toHaveTextContent('Try Now');
|
|
|
});
|
|
|
|
|
|
- it('should not render search alert by default', () => {
|
|
|
- const {container} = render(<ReplaySearchAlert />, {
|
|
|
+ it('should render Learn More CTA if SDK requires update', () => {
|
|
|
+ const {container} = render(<ReplaySearchAlert needSdkUpdates />, {
|
|
|
context: getMockContext(),
|
|
|
});
|
|
|
- expect(container).toBeEmptyDOMElement();
|
|
|
+
|
|
|
+ expect(container).toHaveTextContent('Learn More');
|
|
|
});
|
|
|
|
|
|
- it('should render dismissible alert if minSdk <= 7.44.0', () => {
|
|
|
- mockUseProjectSdkUpdates.mockReturnValue({
|
|
|
- type: 'resolved',
|
|
|
- // @ts-expect-error - ts doesn't play nice with overloaded returns
|
|
|
- data: [
|
|
|
- {
|
|
|
- projectId: project.id,
|
|
|
- sdkName: 'javascript',
|
|
|
- sdkVersion: '7.0.0',
|
|
|
- suggestions: [],
|
|
|
- },
|
|
|
- ],
|
|
|
+ it('should push location.query and dismiss when clicking Try Now CTA', async () => {
|
|
|
+ const dismiss = jest.fn();
|
|
|
+ mockUseDismissAlert.mockReturnValue({
|
|
|
+ dismiss,
|
|
|
+ isDismissed: false,
|
|
|
});
|
|
|
-
|
|
|
- const {container} = render(<ReplaySearchAlert />, {
|
|
|
+ const {container} = render(<ReplaySearchAlert needSdkUpdates={false} />, {
|
|
|
context: getMockContext(),
|
|
|
});
|
|
|
-
|
|
|
- expect(container).not.toBeEmptyDOMElement();
|
|
|
- expect(screen.queryByTestId('min-sdk-alert')).toBeInTheDocument();
|
|
|
- expect(container).toHaveTextContent(
|
|
|
- "Search for dom elements clicked during a replay by using our new search key 'click'. Sadly, it requires an SDK version >= 7.44.0"
|
|
|
+ expect(container).toHaveTextContent('Try Now');
|
|
|
+ const tryNowButton = await screen.findByText('Try Now');
|
|
|
+ await userEvent.click(tryNowButton);
|
|
|
+ expect(dismiss).toHaveBeenCalled();
|
|
|
+ expect(mockBrowserHistoryPush).toHaveBeenCalledWith(
|
|
|
+ expect.objectContaining({
|
|
|
+ query: {
|
|
|
+ query: 'click.tag:button',
|
|
|
+ },
|
|
|
+ })
|
|
|
);
|
|
|
});
|
|
|
|
|
|
- it('should render update alert if minSdk <= 7.44.0 and search contains "click" key', () => {
|
|
|
- mockUseLocation.mockReturnValue(mockLocationReturn('click.alt:foo'));
|
|
|
-
|
|
|
- mockUseProjectSdkUpdates.mockReturnValue({
|
|
|
- type: 'resolved',
|
|
|
- // @ts-expect-error - ts doesn't play nice with overloaded returns
|
|
|
- data: [
|
|
|
- {
|
|
|
- projectId: project.id,
|
|
|
- sdkName: 'javascript',
|
|
|
- sdkVersion: '7.0.0',
|
|
|
- suggestions: [],
|
|
|
- },
|
|
|
- ],
|
|
|
+ it('should render nothing if dismissed', () => {
|
|
|
+ mockUseDismissAlert.mockReturnValue({
|
|
|
+ dismiss: () => {},
|
|
|
+ isDismissed: true,
|
|
|
});
|
|
|
|
|
|
- const {container} = render(<ReplaySearchAlert />, {
|
|
|
+ const {container} = render(<ReplaySearchAlert needSdkUpdates={false} />, {
|
|
|
context: getMockContext(),
|
|
|
});
|
|
|
-
|
|
|
- expect(container).not.toBeEmptyDOMElement();
|
|
|
- expect(screen.queryByTestId('min-sdk-alert')).toBeInTheDocument();
|
|
|
- expect(container).toHaveTextContent(
|
|
|
- "Search field 'click' requires a minimum SDK version of >= 7.44.0."
|
|
|
- );
|
|
|
+ expect(container).toBeEmptyDOMElement();
|
|
|
});
|
|
|
});
|