Skip to content

Commit

Permalink
Add Unit Tests for Modal Component and NFT Submission Flow (#269)
Browse files Browse the repository at this point in the history
* Testing the creation of lesson submission files

* Verifying the call to the NFT mint function through the modal

* Creating test for the modal

* refactor: modularize setup and simplify submission creation test

- Move test data initialization to  to reduce redundancy.
- Extract submission document creation to .
- Simplify main test body to focus on core assertions.

* Improving the code to make it easier to understand

* Removing mintNFT where it wasn't making much sense in testing

* Delete tests/submissionLesson.test.js

This test is not testing anything in the end, it is only creating a doc at firebase and checking if it was created.

---------

Co-authored-by: Yan Luiz <[email protected]>
  • Loading branch information
viniblack and nomadbitcoin authored Nov 13, 2024
1 parent 32f5e98 commit 3737775
Show file tree
Hide file tree
Showing 3 changed files with 198 additions and 2 deletions.
92 changes: 92 additions & 0 deletions components/Modal/index.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/**
* @jest-environment jsdom
*/
import { render, screen, fireEvent, waitFor } from '@testing-library/react'
import Modal from './index'
import '@testing-library/jest-dom'
import { serverTimestamp } from 'firebase/firestore'
import { getUserFromFirestore } from '../../lib/user'
import { getAllCohorts, getCurrentCohort } from '../../lib/cohorts'

jest.mock('uuidv4', () => ({ uuid: jest.fn() }))
jest.mock('react-i18next', () => ({
useTranslation: () => ({ t: (key) => key, i18n: { resolvedLanguage: 'en' } }),
}))
jest.mock('../../lib/user')
jest.mock('../../lib/cohorts')

describe('Check if submit link is calling mintNFT function', () => {
const mockOnClose = jest.fn()

const mockSubmission = {
course: { id: 'Rust_State_Machine' },
title: 'Upload Assignment',
text: 'Submit your assignment',
type: 'text',
}

const lessonSubmission = {
cohort_id: 'RU5mLpQrZZWlmftNSB2w',
content: { type: 'text', value: 'Conteúdo aleatório para teste' },
createdAt: serverTimestamp(),
lesson: 'Lesson_2_Add_State.md',
section: 'Section_1',
}
const mockUser = {
uid: '27mBUecPdbEjIDdFfzYPQiQ9Uyqr',
cohorts: [{ cohort_id: 'RU5mLpQrZZWlmftNSB2w', course_id: 'Rust_State_Machine' }],
}
const mockCohort = {
id: 'RU5mLpQrZZWlmftNSB2w',
startDate: Date.now() + 86400000 * 7,
endDate: Date.now() + 86400000 * 7 + 3600000,
kickoffStartTime: Date.now() + 86400000 * 7,
kickoffEndTime: Date.now() + 86400000 * 7 + 3600000,
}

beforeAll(() => {
global.fetch = jest.fn(() =>
Promise.resolve({ json: () => Promise.resolve({ data: 'fake data' }) })
)
global.IntersectionObserver = class {
observe() {}
unobserve() {}
disconnect() {}
}
})

beforeEach(() => {
jest.clearAllMocks()
getAllCohorts.mockResolvedValue([mockCohort])
getCurrentCohort.mockReturnValue(mockCohort)
getUserFromFirestore.mockResolvedValue(mockUser)
})

const setupModal = () => {
render(
<Modal
openExternal
onClose={mockOnClose}
course={mockSubmission.course}
lesson={lessonSubmission.lesson}
section={lessonSubmission.section}
submissionType={mockSubmission.type}
submissionTitle={mockSubmission.title}
submissionText={mockSubmission.text}
/>
)
}

it('should display modal content correctly', () => {
setupModal()
expect(screen.getByText(mockSubmission.title)).toBeInTheDocument()
expect(screen.getByText(mockSubmission.text)).toBeInTheDocument()

const textarea = screen.getByRole('textbox')
fireEvent.change(textarea, { target: { value: lessonSubmission.content.value } })
expect(textarea.value).toBe(lessonSubmission.content.value)

expect(screen.getByText('send')).toBeInTheDocument()
expect(screen.getByText('cancel')).toBeInTheDocument()
})
})
5 changes: 3 additions & 2 deletions seed-data.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"discord_channel": "rust-state-machine-explorers",
"course_id": "Rust_State_Machine",
"endDate": {
"_seconds": 1729724400,
"_seconds": 1732743757,
"_nanoseconds": 0
},
"nft_title": "Rust State Machine",
Expand Down Expand Up @@ -62,6 +62,7 @@
"tags": ["rust", "blockchain", "polkadot", "substrate"],
"resized_img_url": "https://firebasestorage.googleapis.com/v0/b/web3dev-development.appspot.com/o/courses_cover%2FRust_State_Machine_Resized.png?alt=media&token=73d4418c-8a0a-4115-9997-512341a0ed82",
"nft_title": "Rust State Machine NFT",
"lastLesson": "Lesson_4_Use_the_Runtime_Macro.md",
"metadata": {
"pt-BR": {
"difficulty": "Intermediário",
Expand Down Expand Up @@ -5150,7 +5151,7 @@
"url": null
}
],
"wallet": null,
"wallet": "0xf3B669953879Bf8148D21104f4395C235AB93109",
"name": null,
"bio": "",
"cohorts": [],
Expand Down
103 changes: 103 additions & 0 deletions tests/modalSubmissionLesson.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/**
* @jest-environment jsdom
*/

import { render, screen, fireEvent, waitFor } from '@testing-library/react'
import Modal from '../components/Modal/index'
import '@testing-library/jest-dom'
import { serverTimestamp } from 'firebase/firestore'
import { getUserFromFirestore, submitLessonInFirestore } from '../lib/user'
import { auth } from '../firebase/initFirebase'
import { getAllCohorts, getCurrentCohort } from '../lib/cohorts'

jest.mock('uuidv4', () => ({ uuid: jest.fn() }))
jest.mock('react-i18next', () => ({
useTranslation: () => ({ t: (key) => key, i18n: { resolvedLanguage: 'en' } }),
}))
jest.mock('../lib/user')
jest.mock('../lib/cohorts')

describe('Modal - NFT Submission', () => {
const mockOnClose = jest.fn()
const mockCourse = { id: 'Rust_State_Machine' }
const lessonSubmission = {
cohort_id: 'RU5mLpQrZZWlmftNSB2w',
content: { type: 'text', value: 'Conteúdo aleatório para teste' },
createdAt: serverTimestamp(),
lesson: 'Lesson_2_Add_State.md',
section: 'Section_1',
}
const mockUser = {
uid: '27mBUecPdbEjIDdFfzYPQiQ9Uyqr',
cohorts: [{ cohort_id: 'RU5mLpQrZZWlmftNSB2w', course_id: 'Rust_State_Machine' }],
}
const mockCohort = {
id: 'RU5mLpQrZZWlmftNSB2w',
startDate: Date.now() + 86400000 * 7,
endDate: Date.now() + 86400000 * 7 + 3600000,
kickoffStartTime: Date.now() + 86400000 * 7,
kickoffEndTime: Date.now() + 86400000 * 7 + 3600000,
}

const setupMocks = () => {
jest.clearAllMocks()
getAllCohorts.mockResolvedValue([mockCohort])
getCurrentCohort.mockReturnValue(mockCohort)
getUserFromFirestore.mockResolvedValue(mockUser)
}

const renderModal = () => {
render(
<Modal
openExternal
onClose={mockOnClose}
course={mockCourse}
lesson={lessonSubmission.lesson}
section={lessonSubmission.section}
submissionType="text"
submissionTitle="Upload Assignment"
submissionText="Submit your assignment"
/>
)
}

beforeAll(() => {
global.fetch = jest.fn(() =>
Promise.resolve({ json: () => Promise.resolve({ data: 'fake data' }) })
)
global.IntersectionObserver = class {
observe() {}
unobserve() {}
disconnect() {}
}
})

beforeEach(() => {
setupMocks()
auth.currentUser = { uid: mockUser.uid }
})

it('should submit lesson correctly and call mintNFT function', async () => {
const submitLessonSpy = jest.spyOn(require('../lib/user'), 'submitLessonInFirestore')

renderModal()
await waitFor(async () => {
const textarea = screen.getByRole('textbox')
fireEvent.change(textarea, { target: { value: lessonSubmission.content.value } })
expect(textarea.value).toBe(lessonSubmission.content.value)

const submitButton = screen.getByText('send')
fireEvent.click(submitButton)

const lessonId = undefined // undefined because these lessons are being created and not updated
expect(submitLessonSpy).toHaveBeenCalledWith(
lessonSubmission.cohort_id,
mockUser,
lessonSubmission.lesson,
lessonSubmission.section,
lessonSubmission.content,
lessonId
)
})
})
})

0 comments on commit 3737775

Please sign in to comment.