From 2c2f4329e040f8f8f05e6e047510cbfebefc37db Mon Sep 17 00:00:00 2001 From: Jesse Charlie Naser Date: Mon, 15 Apr 2024 21:53:33 -0400 Subject: [PATCH] Fix tests --- tests/constructor.test.js | 113 +++++++++++++------------------- tests/openModal.test.js | 72 ++++++++++---------- tests/transformVideoUrl.test.js | 32 +++------ 3 files changed, 91 insertions(+), 126 deletions(-) diff --git a/tests/constructor.test.js b/tests/constructor.test.js index 4b295050..7d3cf9f2 100644 --- a/tests/constructor.test.js +++ b/tests/constructor.test.js @@ -1,85 +1,60 @@ const VideoModal = require('../scripts/videopage'); -global.fetch = jest.fn(() => Promise.resolve({ - ok: true, - json: () => Promise.resolve({ liked: true, likes: 10 }) -})); +// Mocking the necessary DOM structure and behavior +document.body.innerHTML = ` + + + +
+ + +
+`; + +// Mocking global fetch +global.fetch = jest.fn(); describe('VideoModal', () => { + let videoModal; beforeEach(() => { - // Reset all mocks between tests - fetch.mockClear(); - document.getElementById.mockClear(); - document.getElementsByClassName.mockClear(); - document.querySelectorAll.mockClear(); - - // Set up mocks for document methods used in VideoModal - document.getElementById = jest.fn().mockImplementation(id => { - if (id === 'modal') return { style: { display: 'none' } }; - if (id === 'videoFrame') return { src: '' }; - return null; + // Reset fetch mock before each test + fetch.mockReset(); + + // Setup fetch mock response + fetch.mockResolvedValue({ + ok: true, + json: () => Promise.resolve({ + liked: true, + likes: 10 + }) }); - document.getElementsByClassName = jest.fn().mockReturnValue([{ - addEventListener: jest.fn() - }]); - - document.querySelectorAll = jest.fn().mockReturnValue([...new Array(5)].map(() => ({ - getAttribute: jest.fn().mockReturnValue('123'), - addEventListener: jest.fn(), - querySelector: jest.fn().mockReturnValue({ - textContent: '', - classList: { - toggle: jest.fn() - }, - innerHTML: '' - }) - }))); + // Initialize VideoModal instance + videoModal = new VideoModal('modal', 'videoFrame', 'close', '.video-card'); }); - it('initializes and binds UI elements correctly', () => { - const videoModal = new VideoModal('modal', 'videoFrame', 'close', '.video-card'); - - // Check proper instantiation and method calls - expect(document.getElementById).toHaveBeenCalledWith('modal'); - expect(document.getElementById).toHaveBeenCalledWith('videoFrame'); - expect(document.getElementsByClassName).toHaveBeenCalledWith('close'); - expect(document.querySelectorAll).toHaveBeenCalledWith('.video-card'); - - // Assert that properties are set up correctly - expect(videoModal.modal).toBeDefined(); - expect(videoModal.videoFrame).toBeDefined(); - expect(videoModal.closeButton).toBeDefined(); - expect(videoModal.videoCards.length).toBe(5); + it('initializes class properties correctly', () => { + expect(videoModal.modal).toEqual(document.getElementById('modal')); + expect(videoModal.videoFrame).toEqual(document.getElementById('videoFrame')); + expect(videoModal.closeButton).toEqual(document.getElementsByClassName('close')[0]); + expect(videoModal.videoCards.length).toBe(1); + expect(videoModal.videoCards[0]).toEqual(document.querySelector('.video-card')); }); - it('updates like states correctly when initializing', async () => { - const videoModal = new VideoModal('modal', 'videoFrame', 'close', '.video-card'); - - // The updateAllLikeStates method should be called during initialization - await videoModal.init(); - - // Since there are 5 cards, ensure fetch was called 5 times - expect(fetch).toHaveBeenCalledTimes(5); - expect(fetch.mock.calls[0][0]).toBe('/api/likes?videoId=123'); - - const card = document.querySelectorAll().mock.results[0].value[0]; - expect(card.querySelector.mock.calls.length).toBe(2); // Called twice per card: once for button, once for count - expect(card.querySelector().classList.toggle).toHaveBeenCalledWith('liked', true); - expect(card.querySelector().textContent).toBe('10 Likes'); - }); + it('calls fetch and updates like state for video cards', async () => { + // Trigger the update method which calls fetch + await videoModal.updateAllLikeStates(); - it('handles modal opening and closing correctly', () => { - const videoModal = new VideoModal('modal', 'videoFrame', 'close', '.video-card'); - videoModal.openModal('https://youtube.com/watch?v=dQw4w9WgXcQ'); + // Check if fetch was called correctly + expect(fetch).toHaveBeenCalledTimes(1); + expect(fetch).toHaveBeenCalledWith('/api/likes?videoId=123'); - // Verify that the modal display style changes to block - expect(videoModal.modal.style.display).toBe('block'); - expect(videoModal.videoFrame.src).toContain('https://youtube.com/embed/dQw4w9WgXcQ?autoplay=1&rel=0'); + // Check changes to DOM (like count and button text) + const likesCountElement = videoModal.videoCards[0].querySelector('.like-count'); + const likeButton = videoModal.videoCards[0].querySelector('.like-btn'); - // Simulate closing the modal - videoModal.closeModal(); - expect(videoModal.modal.style.display).toBe('none'); - expect(videoModal.videoFrame.src).toBe(''); + expect(likesCountElement.textContent).toBe('10 Likes'); + expect(likeButton.classList.contains('liked')).toBe(true); + expect(likeButton.innerHTML).toContain('Liked'); }); }); \ No newline at end of file diff --git a/tests/openModal.test.js b/tests/openModal.test.js index f8a34d84..d579817f 100644 --- a/tests/openModal.test.js +++ b/tests/openModal.test.js @@ -1,47 +1,53 @@ const VideoModal = require('../scripts/videopage'); -// Mock fetch -global.fetch = jest.fn(() => - Promise.resolve({ - ok: true, - json: () => Promise.resolve({ likes: 10, liked: true }) - }) -); +// Setting up a full mock for fetch within Jest +beforeAll(() => { + global.fetch = jest.fn(); +}); -describe('VideoModal', () => { - let mockModal, mockVideoFrame, mockCards; +afterAll(() => { + global.fetch.mockRestore(); +}); +describe('VideoModal - openModal', () => { + let mockModal, mockVideoFrame; + beforeEach(() => { - fetch.mockClear(); + // Clear mocks before each test + fetch.mockClear().mockResolvedValue({ + ok: true, + json: () => Promise.resolve({ likes: 10, liked: true }) + }); + // Mock modal and videoFrame elements mockModal = { style: { display: 'none' } }; mockVideoFrame = { src: '' }; - mockCards = [{ - getAttribute: jest.fn().mockReturnValue('123'), - querySelector: jest.fn().mockReturnValue({ - textContent: '', - classList: { - toggle: jest.fn() - }, - innerHTML: '' - }) - }]; - - document.getElementById = jest.fn((id) => ({ - 'modal': mockModal, - 'videoFrame': mockVideoFrame - })[id]); - - document.getElementsByClassName = jest.fn().mockReturnValue([{ onclick: null }]); - document.querySelectorAll = jest.fn().mockReturnValue(mockCards); + + // Using jest.spyOn to mock document API calls + jest.spyOn(document, 'getElementById').mockImplementation((id) => { + if (id === 'modal') return mockModal; + if (id === 'videoFrame') return mockVideoFrame; + return null; + }); + + // Mocking classes and query selectors + jest.spyOn(document, 'getElementsByClassName').mockReturnValue([{ onclick: jest.fn() }]); + jest.spyOn(document, 'querySelectorAll').mockReturnValue([{ + addEventListener: jest.fn(), + getAttribute: jest.fn().mockReturnValue('https://www.youtube.com/watch?v=dQw4w9WgXcQ') + }]); + }); + + afterEach(() => { + jest.restoreAllMocks(); }); - it('updates all like states when initialized', async () => { + it('sets videoFrame src and displays modal', () => { const videoModal = new VideoModal('modal', 'videoFrame', 'close', '.video-card'); - await videoModal.updateAllLikeStates(); + const testUrl = 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'; + videoModal.openModal(testUrl); - expect(fetch).toHaveBeenCalledTimes(mockCards.length); - expect(mockCards[0].querySelector).toHaveBeenCalledWith('.like-btn'); - expect(mockCards[0].querySelector).toHaveBeenCalledWith('.like-count'); + expect(mockVideoFrame.src).toContain('https://www.youtube.com/embed/dQw4w9WgXcQ?autoplay=1&rel=0'); + expect(mockModal.style.display).toBe('block'); }); }); \ No newline at end of file diff --git a/tests/transformVideoUrl.test.js b/tests/transformVideoUrl.test.js index 67a47528..1847d9d9 100644 --- a/tests/transformVideoUrl.test.js +++ b/tests/transformVideoUrl.test.js @@ -1,40 +1,24 @@ const VideoModal = require('../scripts/videopage'); -global.fetch = jest.fn(() => - Promise.resolve({ - ok: true, - json: () => Promise.resolve({ likes: 10, liked: true }) - }) -); +// Mock fetch globally +global.fetch = jest.fn(); describe('VideoModal - transformVideoUrl', () => { beforeEach(() => { - // Clear all mocks before each test + // Clear all mocks before each test to ensure clean slate jest.clearAllMocks(); + + // Mock required DOM elements + document.getElementById = jest.fn(() => document.createElement('div')); + document.getElementsByClassName = jest.fn(() => [document.createElement('button')]); + document.querySelectorAll = jest.fn(() => [document.createElement('div')]); }); it('transforms YouTube watch URL to embed URL correctly', () => { - // Mocking the necessary DOM elements - document.getElementById = jest.fn(id => { - if (id === 'dummyModalId') return document.createElement('div'); - if (id === 'dummyVideoFrameId') return document.createElement('iframe'); - return null; - }); - document.getElementsByClassName = jest.fn((className) => { - if (className === 'dummyCloseButtonClass') return [document.createElement('button')]; - return []; - }); - document.querySelectorAll = jest.fn((selector) => { - if (selector === 'dummyVideoCardClass') return [document.createElement('div')]; - return []; - }); - const videoModal = new VideoModal('dummyModalId', 'dummyVideoFrameId', 'dummyCloseButtonClass', 'dummyVideoCardClass'); const inputUrl = 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'; const expectedUrl = 'https://www.youtube.com/embed/dQw4w9WgXcQ'; expect(videoModal.transformVideoUrl(inputUrl)).toBe(expectedUrl); - - expect(fetch).not.toHaveBeenCalled(); }); }); \ No newline at end of file