AsyncIcon.integration.test.tsx 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing,
  13. * software distributed under the License is distributed on an
  14. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15. * KIND, either express or implied. See the License for the
  16. * specific language governing permissions and limitations
  17. * under the License.
  18. */
  19. import '@testing-library/jest-dom';
  20. import { render, fireEvent } from '@testing-library/react';
  21. import { SupersetTheme, ThemeProvider } from '@superset-ui/core';
  22. // CRITICAL: Don't import from the mocked path - import directly to avoid global mocks
  23. import AsyncIcon from '../../../src/components/Icons/AsyncIcon';
  24. // Mock only the SVG import to prevent dynamic import issues
  25. jest.mock(
  26. '!!@svgr/webpack!../../../src/assets/images/icons/slack.svg',
  27. () => {
  28. const MockSlackSVG = (props: any) => (
  29. <svg {...props} viewBox="0 0 24 24" data-testid="slack-svg">
  30. <path d="M5.042 15.165a2.528 2.528 0 0 1-2.52 2.523A2.528 2.528 0 0 1 0 15.165a2.527 2.527 0 0 1 2.522-2.52h2.52v2.52z" />
  31. </svg>
  32. );
  33. return { default: MockSlackSVG };
  34. },
  35. { virtual: true },
  36. );
  37. // Basic theme for testing
  38. const mockTheme: SupersetTheme = {
  39. fontSize: 16,
  40. sizeUnit: 4,
  41. } as SupersetTheme;
  42. describe('AsyncIcon Integration Tests (Real Component)', () => {
  43. it('should have data-test and aria-label attributes with real component', () => {
  44. const { container } = render(
  45. <ThemeProvider theme={mockTheme}>
  46. <AsyncIcon customIcons fileName="slack" iconSize="l" />
  47. </ThemeProvider>,
  48. );
  49. // Don't wait for SVG since it's mocked - just check the span wrapper
  50. const spanElement = container.querySelector('span');
  51. // Test the ACTUAL component behavior (not the mock)
  52. expect(spanElement).toHaveAttribute('aria-label', 'slack');
  53. expect(spanElement).toHaveAttribute('role', 'img');
  54. expect(spanElement).toHaveAttribute('data-test', 'slack');
  55. });
  56. it('should always have aria-label and data-test for testing', () => {
  57. const { container } = render(
  58. <ThemeProvider theme={mockTheme}>
  59. <AsyncIcon customIcons fileName="slack" iconSize="l" />
  60. </ThemeProvider>,
  61. );
  62. const spanElement = container.querySelector('span');
  63. // The critical requirement: we MUST have these attributes for accessibility and testing
  64. expect(spanElement).toHaveAttribute('aria-label');
  65. expect(spanElement).toHaveAttribute('data-test');
  66. // The values should be consistent
  67. const ariaLabel = spanElement?.getAttribute('aria-label');
  68. const dataTest = spanElement?.getAttribute('data-test');
  69. expect(ariaLabel).toBe('slack');
  70. expect(dataTest).toBe('slack');
  71. });
  72. it('should set role to button when onClick is provided in real component', () => {
  73. const onClick = jest.fn();
  74. const { container } = render(
  75. <ThemeProvider theme={mockTheme}>
  76. <AsyncIcon
  77. customIcons
  78. fileName="slack"
  79. iconSize="l"
  80. onClick={onClick}
  81. />
  82. </ThemeProvider>,
  83. );
  84. const spanElement = container.querySelector('span');
  85. expect(spanElement).toHaveAttribute('role', 'button');
  86. expect(spanElement).toHaveAttribute('aria-label', 'slack');
  87. expect(spanElement).toHaveAttribute('data-test', 'slack');
  88. // Verify onClick handler actually works
  89. fireEvent.click(spanElement!);
  90. expect(onClick).toHaveBeenCalledTimes(1);
  91. });
  92. it('should handle complex fileName patterns like BaseIcon', () => {
  93. const { container } = render(
  94. <ThemeProvider theme={mockTheme}>
  95. <AsyncIcon customIcons fileName="slack_notification" iconSize="l" />
  96. </ThemeProvider>,
  97. );
  98. const spanElement = container.querySelector('span');
  99. // Should follow BaseIcon's genAriaLabel logic:
  100. // fileName="slack_notification" -> name="slack-notification" -> "slack-notification" (not just "slack")
  101. expect(spanElement).toHaveAttribute('aria-label', 'slack-notification');
  102. expect(spanElement).toHaveAttribute('data-test', 'slack-notification');
  103. });
  104. });