123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- import {ProjectFixture} from 'sentry-fixture/project';
- import {render, screen, userEvent, within} from 'sentry-test/reactTestingLibrary';
- import {ViewHierarchy} from '.';
- // Mocks for useVirtualizedTree hook
- class ResizeObserver {
- observe() {}
- unobserve() {}
- disconnect() {}
- }
- window.ResizeObserver = ResizeObserver;
- window.Element.prototype.scrollTo = jest.fn();
- window.Element.prototype.scrollIntoView = jest.fn();
- const DEFAULT_VALUES = {alpha: 1, height: 1, width: 1, x: 1, y: 1, visible: true};
- const DEFAULT_MOCK_DATA = {
- rendering_system: 'test-rendering-system',
- windows: [
- {
- ...DEFAULT_VALUES,
- type: 'Container',
- identifier: 'test_identifier',
- x: 200,
- children: [
- {
- ...DEFAULT_VALUES,
- type: 'Nested Container',
- x: 10,
- y: 10,
- width: 3,
- height: 4,
- identifier: 'nested',
- children: [
- {
- ...DEFAULT_VALUES,
- type: 'Text',
- children: [],
- },
- ],
- },
- ],
- },
- ],
- };
- describe('View Hierarchy', function () {
- let MOCK_DATA;
- let project;
- beforeEach(() => {
- MOCK_DATA = DEFAULT_MOCK_DATA;
- project = ProjectFixture();
- });
- it('can continue make selections for inspecting data', async function () {
- render(<ViewHierarchy viewHierarchy={MOCK_DATA} project={project} />);
- // 1 for the tree node, 1 for the details panel header
- expect(screen.getAllByText('Container - test_identifier')).toHaveLength(2);
- await userEvent.click(screen.getByText('Nested Container - nested'));
- // 1 for the tree node, 1 for the details panel header
- expect(screen.getAllByText('Nested Container - nested')).toHaveLength(2);
- // Only visible in the tree node
- expect(screen.getByText('Container - test_identifier')).toBeInTheDocument();
- await userEvent.click(screen.getByText('Text'));
- // 1 for the tree node, 1 for the details panel header, 1 for the details value
- expect(screen.getAllByText('Text')).toHaveLength(3);
- // Only visible in the tree node
- expect(screen.getByText('Nested Container - nested')).toBeInTheDocument();
- });
- it('can expand and collapse by clicking the icon', async function () {
- render(<ViewHierarchy viewHierarchy={MOCK_DATA} project={project} />);
- expect(screen.queryByText('Text')).toBeInTheDocument();
- await userEvent.click(
- within(screen.getByLabelText('Nested Container - nested')).getByRole('button', {
- name: 'Collapse',
- })
- );
- expect(screen.queryByText('Text')).not.toBeInTheDocument();
- await userEvent.click(screen.getByRole('button', {name: 'Expand'}));
- expect(screen.queryByText('Text')).toBeInTheDocument();
- });
- it('can navigate with keyboard shortcuts after a selection', async function () {
- render(<ViewHierarchy viewHierarchy={MOCK_DATA} project={project} />);
- await userEvent.click(screen.getAllByText('Container - test_identifier')[0]);
- await userEvent.keyboard('{ArrowDown}');
- // 1 for the tree node, 1 for the details panel header
- expect(screen.getAllByText('Nested Container - nested')).toHaveLength(2);
- });
- it('can expand/collapse with the keyboard', async function () {
- render(<ViewHierarchy viewHierarchy={MOCK_DATA} project={project} />);
- await userEvent.click(screen.getAllByText('Nested Container - nested')[0]);
- await userEvent.keyboard('{Enter}');
- expect(screen.queryByText('Text')).not.toBeInTheDocument();
- await userEvent.keyboard('{Enter}');
- expect(screen.getByText('Text')).toBeInTheDocument();
- });
- it('can render multiple windows together', function () {
- MOCK_DATA.windows = [
- ...MOCK_DATA.windows,
- {
- ...DEFAULT_VALUES,
- type: 'Second Window',
- children: [
- {
- ...DEFAULT_VALUES,
- type: 'Second Window Child',
- children: [],
- },
- ],
- },
- ];
- render(<ViewHierarchy viewHierarchy={MOCK_DATA} project={project} />);
- expect(screen.getByText('Second Window')).toBeInTheDocument();
- expect(screen.getByText('Second Window Child')).toBeInTheDocument();
- });
- it('does not render the wireframe for the Unity platform', function () {
- const mockUnityProject = ProjectFixture({platform: 'unity'});
- render(<ViewHierarchy viewHierarchy={MOCK_DATA} project={mockUnityProject} />);
- expect(screen.queryByTestId('view-hierarchy-wireframe')).not.toBeInTheDocument();
- });
- it('draws the selected node when a tree selection is made', async function () {
- render(<ViewHierarchy viewHierarchy={MOCK_DATA} project={project} />);
- const canvas = screen.getByTestId(
- 'view-hierarchy-wireframe-overlay'
- ) as HTMLCanvasElement;
- const context = canvas.getContext('2d');
- if (!context) {
- throw new Error('Canvas context is not defined');
- }
- expect(context.fillRect).not.toHaveBeenCalledWith(210, 11, 3, 4);
- await userEvent.click(screen.getByText('Nested Container - nested'));
- // This is the nested container, the x, y positions are shifted by the parent
- expect(context.fillRect).toHaveBeenCalledWith(210, 11, 3, 4);
- });
- it('does not render a wireframe selection initially', function () {
- render(<ViewHierarchy viewHierarchy={MOCK_DATA} project={project} />);
- const canvas = screen.getByTestId(
- 'view-hierarchy-wireframe-overlay'
- ) as HTMLCanvasElement;
- const context = canvas.getContext('2d');
- if (!context) {
- throw new Error('Canvas context is not defined');
- }
- // The overlay should not have rendered anything before any interactions
- expect(context.fillRect).not.toHaveBeenCalled();
- });
- it('renders an empty state if there is no data in windows to visualize', function () {
- render(
- <ViewHierarchy
- viewHierarchy={{rendering_system: 'This can be anything', windows: []}}
- project={project}
- />
- );
- expect(
- screen.getByText('There is no view hierarchy data to visualize')
- ).toBeInTheDocument();
- });
- it('renders with depth markers', function () {
- render(<ViewHierarchy viewHierarchy={MOCK_DATA} project={project} />);
- });
- it('renders an icon with a tooltip for the rendering system', async function () {
- MOCK_DATA.rendering_system = 'flutter';
- render(<ViewHierarchy viewHierarchy={MOCK_DATA} project={project} />);
- await userEvent.hover(screen.getByTestId('rendering-system-icon'));
- expect(await screen.findByText('Rendering System: flutter')).toBeInTheDocument();
- });
- });
|