mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-05-28 18:26:54 +00:00
feat(client): Added tests for per-module progress in client (#64226)
Co-authored-by: Almee Christian <almee@Almees-MacBook-Pro.local>
This commit is contained in:
@@ -3,6 +3,10 @@ import { render, screen, within } from '@testing-library/react';
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { SuperBlocks } from '../../../../../shared-dist/config/curriculum';
|
||||
import { SuperBlockAccordion } from './super-block-accordion';
|
||||
import {
|
||||
BlockLabel,
|
||||
BlockLayouts
|
||||
} from '../../../../../shared-dist/config/blocks';
|
||||
|
||||
const mockStructure = {
|
||||
superBlock: SuperBlocks.RespWebDesign,
|
||||
@@ -19,6 +23,19 @@ const mockStructure = {
|
||||
]
|
||||
};
|
||||
|
||||
// Representative challenge used to populate module content.
|
||||
const mockChallenge = {
|
||||
id: 'test-challenge-id',
|
||||
block: 'test-block',
|
||||
blockLabel: BlockLabel.lecture,
|
||||
title: 'Test Challenge',
|
||||
fields: { slug: '/test-slug' },
|
||||
dashedName: 'test-challenge',
|
||||
challengeType: 0,
|
||||
blockLayout: BlockLayouts.ChallengeList,
|
||||
superBlock: SuperBlocks.RespWebDesign
|
||||
};
|
||||
|
||||
describe('SuperBlockAccordion', () => {
|
||||
it('does not show completed checkmark when there are zero challenges in a chapter', () => {
|
||||
render(
|
||||
@@ -40,4 +57,125 @@ describe('SuperBlockAccordion', () => {
|
||||
const checkmark = within(chapterButton).getByTestId('green-not-completed');
|
||||
expect(checkmark).toBeInTheDocument();
|
||||
});
|
||||
|
||||
// With progress data present, the module button should render the steps label.
|
||||
it('shows module progress when totalSteps > 0 and not comingSoon', () => {
|
||||
const structureWithProgress = {
|
||||
superBlock: SuperBlocks.RespWebDesign,
|
||||
chapters: [
|
||||
{
|
||||
dashedName: 'test-chapter',
|
||||
modules: [
|
||||
{
|
||||
dashedName: 'test-module',
|
||||
blocks: ['test-block'],
|
||||
comingSoon: false,
|
||||
totalSteps: 10,
|
||||
completedSteps: 5
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
render(
|
||||
<SuperBlockAccordion
|
||||
challenges={[mockChallenge]}
|
||||
superBlock={SuperBlocks.RespWebDesign}
|
||||
structure={structureWithProgress}
|
||||
chosenBlock={''}
|
||||
completedChallengeIds={[]}
|
||||
/>
|
||||
);
|
||||
|
||||
const moduleButtons = screen.getAllByRole('button', {
|
||||
name: /test-module/i
|
||||
});
|
||||
const moduleButton = moduleButtons[0];
|
||||
|
||||
const moduleRight = within(moduleButton).getByTestId('module-button-right');
|
||||
const moduleSteps = within(moduleRight).getByText(
|
||||
/learn\.steps-completed/i
|
||||
);
|
||||
expect(moduleSteps).toBeInTheDocument();
|
||||
expect(moduleSteps).toHaveClass('module-steps');
|
||||
});
|
||||
|
||||
// A coming-soon module should hide the steps summary even if progress exists.
|
||||
it('does not show module progress when comingSoon is true', () => {
|
||||
const structureComingSoon = {
|
||||
superBlock: SuperBlocks.RespWebDesign,
|
||||
chapters: [
|
||||
{
|
||||
dashedName: 'test-chapter',
|
||||
modules: [
|
||||
{
|
||||
dashedName: 'test-module',
|
||||
blocks: ['test-block'],
|
||||
comingSoon: true,
|
||||
totalSteps: 10,
|
||||
completedSteps: 5
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
render(
|
||||
<SuperBlockAccordion
|
||||
challenges={[mockChallenge]}
|
||||
superBlock={SuperBlocks.RespWebDesign}
|
||||
structure={structureComingSoon}
|
||||
chosenBlock={''}
|
||||
completedChallengeIds={[]}
|
||||
/>
|
||||
);
|
||||
|
||||
const moduleButtons = screen.getAllByRole('button', {
|
||||
name: /test-module/i
|
||||
});
|
||||
const moduleButton = moduleButtons[0];
|
||||
|
||||
const moduleRight = within(moduleButton).getByTestId('module-button-right');
|
||||
expect(within(moduleRight).queryByText(/steps/i)).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
// Modules with zero total steps should not display any progress text.
|
||||
it('does not show module progress when totalSteps is zero', () => {
|
||||
const structureZeroSteps = {
|
||||
superBlock: SuperBlocks.RespWebDesign,
|
||||
chapters: [
|
||||
{
|
||||
dashedName: 'test-chapter',
|
||||
modules: [
|
||||
{
|
||||
dashedName: 'test-module',
|
||||
blocks: ['test-block'],
|
||||
comingSoon: false,
|
||||
totalSteps: 0,
|
||||
completedSteps: 0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
render(
|
||||
<SuperBlockAccordion
|
||||
challenges={[]}
|
||||
superBlock={SuperBlocks.RespWebDesign}
|
||||
structure={structureZeroSteps}
|
||||
chosenBlock={''}
|
||||
completedChallengeIds={[]}
|
||||
/>
|
||||
);
|
||||
|
||||
const moduleButtons = screen.getAllByRole('button', {
|
||||
name: /test-module/i
|
||||
});
|
||||
const moduleButton = moduleButtons[0];
|
||||
|
||||
const moduleRight = within(moduleButton).getByTestId('module-button-right');
|
||||
expect(within(moduleRight).queryByText(/steps/i)).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -189,7 +189,7 @@ const Module = ({
|
||||
</span>
|
||||
{t(`intro:${superBlock}.modules.${dashedName}`)}
|
||||
</div>
|
||||
<div className='module-button-right'>
|
||||
<div className='module-button-right' data-testid='module-button-right'>
|
||||
{!comingSoon && !!totalSteps && (
|
||||
<span className='module-steps'>
|
||||
{t('learn.steps-completed', {
|
||||
|
||||
Reference in New Issue
Block a user