import { render, screen } from '@testing-library/react'; import { renderHook } from '@testing-library/react-hooks'; import { Theme, createTheme } from '@aws-amplify/ui'; import * as React from 'react'; import { ThemeProvider } from '../index'; import { Heading } from '../../../primitives'; import { useTheme } from '../../../hooks'; const App = () => { return Howdy; }; describe('ThemeProvider', () => { it('does not require props', async () => { render( ); const heading = await screen.getByText('Howdy'); expect(heading.nodeName).toBe('H6'); }); it('should accept the output of createTheme to allow for extending themes', async () => { const studioTheme = createTheme(); const extendedTheme = createTheme( { name: 'extended-theme', tokens: { colors: { font: { primary: { value: 'hotpink' }, }, }, }, }, studioTheme ); const { result } = renderHook(() => useTheme(), { wrapper: ({ children }) => ( {children} ), }); expect(result.current.tokens.colors.font.primary.value).toBe('hotpink'); }); it('wraps the App in [data-amplify-theme="default-theme"]', () => { const { container } = render( ); expect(container.querySelector(`[data-amplify-theme]`)).toHaveAttribute( 'data-amplify-theme', 'default-theme' ); }); it('takes direction prop and sets dir', () => { const { container } = render( ); expect(container.querySelector(`[data-amplify-theme]`)).toHaveAttribute( 'dir', 'rtl' ); }); it('takes the colorMode prop and sets [data-amplify-color-mode]', () => { const { container } = render( ); expect(container.querySelector(`[data-amplify-theme]`)).toHaveAttribute( 'data-amplify-color-mode', 'light' ); }); it('filters out XSS attacks which attempt to escape the CSS context', async () => { const name = 'maliciousTheme'; const xss = ``; const maliciousTheme: Theme = { name, tokens: { colors: { font: { primary: { value: 'pink' }, secondary: { value: xss } }, }, }, }; const { container } = render( ); const styleTag = container.querySelector(`#amplify-theme-${name}`); expect(styleTag).toBe(null); }); it('filters out XSS attacks which attempt to escape the CSS context using whitespace characters', async () => { const name = 'maliciousTheme'; const xss = ``; const maliciousTheme: Theme = { name, tokens: { colors: { font: { primary: { value: 'pink' }, secondary: { value: xss } }, }, }, }; const { container } = render( ); const styleTag = container.querySelector(`#amplify-theme-${name}`); expect(styleTag).toBe(null); }); });