import React from 'react'; import { Factory } from 'rosie'; import { initializeTestStore, loadUnit, messageEvent, render, screen, waitFor, } from '../../../setupTest'; import Unit from './Unit'; describe('Unit', () => { let mockData; const courseMetadata = Factory.build( 'courseMetadata', { content_type_gating_enabled: true }, ); const unitBlocks = [Factory.build( 'block', { type: 'problem' }, { courseId: courseMetadata.id }, ), Factory.build( 'block', { type: 'vertical', graded: true, bookmarked: true }, { courseId: courseMetadata.id }, )]; const [unit, gradedUnit] = unitBlocks; beforeAll(async () => { await initializeTestStore({ courseMetadata, unitBlocks }); mockData = { id: unit.id, courseId: courseMetadata.id, format: 'Homework', }; }); it('renders correctly', () => { render(); expect(screen.getByText('Loading learning sequence...')).toBeInTheDocument(); const renderedUnit = screen.getByTitle(unit.display_name); expect(renderedUnit).toHaveAttribute('height', String(0)); expect(renderedUnit).toHaveAttribute( 'src', `http://localhost:18000/xblock/${mockData.id}?show_title=0&show_bookmark_button=0&view=student_view&format=${mockData.format}`, ); }); it('renders proper message for gated content', () => { render(); expect(screen.getByText('Loading learning sequence...')).toBeInTheDocument(); expect(screen.getByText('Loading locked content messaging...')).toBeInTheDocument(); }); it('handles receiving MessageEvent', async () => { render(); loadUnit(); // Loading message is gone now. await waitFor(() => expect(screen.queryByText('Loading learning sequence...')).not.toBeInTheDocument()); // Iframe's height is set via message. expect(screen.getByTitle(unit.display_name)).toHaveAttribute('height', String(messageEvent.payload.height)); }); it('calls onLoaded after receiving MessageEvent', async () => { const onLoaded = jest.fn(); render(); loadUnit(); await waitFor(() => expect(onLoaded).toHaveBeenCalledTimes(1)); }); it('resizes iframe on second MessageEvent, does not call onLoaded again', async () => { const onLoaded = jest.fn(); // Clone message and set different height. const testMessageWithOtherHeight = { ...messageEvent, payload: { height: 200 } }; render(); loadUnit(); await waitFor(() => expect(screen.getByTitle(unit.display_name)).toHaveAttribute('height', String(messageEvent.payload.height))); window.postMessage(testMessageWithOtherHeight, '*'); await waitFor(() => expect(screen.getByTitle(unit.display_name)).toHaveAttribute('height', String(testMessageWithOtherHeight.payload.height))); expect(onLoaded).toHaveBeenCalledTimes(1); }); it('ignores MessageEvent with unhandled type', async () => { // Clone message and set different type. const testMessageWithUnhandledType = { ...messageEvent, type: 'wrong type' }; render(); window.postMessage(testMessageWithUnhandledType, '*'); // HACK: We don't have a function we could reliably await here, so this test relies on the timeout of `waitFor`. await expect(waitFor( () => expect(screen.getByTitle(unit.display_name)).toHaveAttribute('height', String(testMessageWithUnhandledType.payload.height)), { timeout: 100 }, )).rejects.toThrowError(/Expected the element to have attribute/); }); });