Skip to content

Commit bc46ae9

Browse files
test(client): add tests to build transcript function (freeCodeCamp#63822)
1 parent 36be0f7 commit bc46ae9

4 files changed

Lines changed: 219 additions & 22 deletions

File tree

client/src/redux/prop-types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ export interface VideoLocaleIds {
7474
}
7575

7676
// English types for animations
77-
interface Dialogue {
77+
export interface Dialogue {
7878
text: string;
7979
align: 'left' | 'right' | 'center';
8080
}
@@ -85,7 +85,7 @@ export interface CharacterPosition {
8585
z?: number;
8686
}
8787

88-
interface SceneCommand {
88+
export interface SceneCommand {
8989
background?: string;
9090
character: string;
9191
position?: CharacterPosition;
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
import { describe, it, expect } from 'vitest';
2+
import { type SceneCommand } from '../../../../redux/prop-types';
3+
import { buildTranscript } from './scene-helpers';
4+
5+
describe('scene-helpers', () => {
6+
describe('buildTranscript', () => {
7+
it('should return empty string for empty commands array', () => {
8+
const commands: SceneCommand[] = [];
9+
const result = buildTranscript(commands);
10+
expect(result).toBe('');
11+
});
12+
13+
it('should build transcript from single command with dialogue', () => {
14+
const commands: SceneCommand[] = [
15+
{
16+
character: 'Naomi',
17+
startTime: 1,
18+
dialogue: {
19+
text: 'Hello world, I have 5 cats',
20+
align: 'left'
21+
}
22+
}
23+
];
24+
const result = buildTranscript(commands);
25+
expect(result).toBe(
26+
'\n<strong>Naomi</strong>: Hello world, I have 5 cats\n'
27+
);
28+
});
29+
30+
it('should build transcript from multiple commands with dialogue', () => {
31+
const commands: SceneCommand[] = [
32+
{
33+
character: 'Naomi',
34+
startTime: 1,
35+
dialogue: {
36+
text: 'Hello',
37+
align: 'left'
38+
}
39+
},
40+
{
41+
character: 'Quincy',
42+
startTime: 1,
43+
dialogue: {
44+
text: 'Hi there, I found 3 bugs',
45+
align: 'right'
46+
}
47+
},
48+
{
49+
character: 'Naomi',
50+
startTime: 2,
51+
dialogue: {
52+
text: 'How are you?',
53+
align: 'left'
54+
}
55+
}
56+
];
57+
const result = buildTranscript(commands);
58+
expect(result).toBe(
59+
'\n<strong>Naomi</strong>: Hello\n' +
60+
'\n<strong>Quincy</strong>: Hi there, I found 3 bugs\n' +
61+
'\n<strong>Naomi</strong>: How are you?\n'
62+
);
63+
});
64+
65+
it('should skip commands without dialogue', () => {
66+
const commands: SceneCommand[] = [
67+
{
68+
character: 'Naomi',
69+
startTime: 1,
70+
dialogue: {
71+
text: 'Hello',
72+
align: 'left'
73+
}
74+
},
75+
{
76+
character: 'Quincy',
77+
startTime: 1
78+
// No dialogue
79+
},
80+
{
81+
character: 'Naomi',
82+
startTime: 2,
83+
dialogue: {
84+
text: 'How are you?',
85+
align: 'left'
86+
}
87+
}
88+
];
89+
const result = buildTranscript(commands);
90+
expect(result).toBe(
91+
'\n<strong>Naomi</strong>: Hello\n' +
92+
'\n<strong>Naomi</strong>: How are you?\n'
93+
);
94+
});
95+
96+
it('should handle dialogue with special characters', () => {
97+
const commands: SceneCommand[] = [
98+
{
99+
character: 'Naomi',
100+
startTime: 1,
101+
dialogue: {
102+
text: 'He said "I love TypeScript!" & she replied, \'I prefer Ruby! #ruby #rubyonrails\'',
103+
align: 'left'
104+
}
105+
}
106+
];
107+
const result = buildTranscript(commands);
108+
expect(result).toBe(
109+
'\n<strong>Naomi</strong>: He said "I love TypeScript!" & she replied, \'I prefer Ruby! #ruby #rubyonrails\'\n'
110+
);
111+
});
112+
113+
it('should handle empty dialogue text', () => {
114+
const commands: SceneCommand[] = [
115+
{
116+
character: 'Naomi',
117+
startTime: 1,
118+
dialogue: {
119+
text: '',
120+
align: 'left'
121+
}
122+
}
123+
];
124+
const result = buildTranscript(commands);
125+
expect(result).toBe('\n<strong>Naomi</strong>: \n');
126+
});
127+
128+
it('should handle dialogue with newlines', () => {
129+
const commands: SceneCommand[] = [
130+
{
131+
character: 'Naomi',
132+
startTime: 1,
133+
dialogue: {
134+
text: 'Hello\nworld',
135+
align: 'left'
136+
}
137+
}
138+
];
139+
const result = buildTranscript(commands);
140+
expect(result).toBe('\n<strong>Naomi</strong>: Hello\nworld\n');
141+
});
142+
143+
it('should handle multiple consecutive commands from same character', () => {
144+
const commands: SceneCommand[] = [
145+
{
146+
character: 'Naomi',
147+
startTime: 1,
148+
dialogue: {
149+
text: 'First line',
150+
align: 'left'
151+
}
152+
},
153+
{
154+
character: 'Naomi',
155+
startTime: 1,
156+
dialogue: {
157+
text: 'Second line',
158+
align: 'left'
159+
}
160+
},
161+
{
162+
character: 'Naomi',
163+
startTime: 2,
164+
dialogue: {
165+
text: 'Third line',
166+
align: 'left'
167+
}
168+
}
169+
];
170+
const result = buildTranscript(commands);
171+
expect(result).toBe(
172+
'\n<strong>Naomi</strong>: First line\n' +
173+
'\n<strong>Naomi</strong>: Second line\n' +
174+
'\n<strong>Naomi</strong>: Third line\n'
175+
);
176+
});
177+
178+
it('should preserve HTML content', () => {
179+
const commands: SceneCommand[] = [
180+
{
181+
character: 'Naomi',
182+
startTime: 1,
183+
dialogue: {
184+
text: 'Use <div> and <span> tags',
185+
align: 'left'
186+
}
187+
}
188+
];
189+
const result = buildTranscript(commands);
190+
expect(result).toBe(
191+
'\n<strong>Naomi</strong>: Use <div> and <span> tags\n'
192+
);
193+
});
194+
});
195+
});
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { type SceneCommand } from '../../../../redux/prop-types';
2+
3+
export const buildTranscript = (commands: SceneCommand[]): string => {
4+
let transcriptText = '';
5+
commands.forEach(command => {
6+
if (command.character && command.dialogue && command.startTime) {
7+
transcriptText =
8+
transcriptText +
9+
'\n' +
10+
'<strong>' +
11+
command.character +
12+
'</strong>:' +
13+
' ' +
14+
command.dialogue.text +
15+
'\n';
16+
}
17+
});
18+
19+
return transcriptText;
20+
};

client/src/templates/Challenges/components/scene/scene.tsx

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import ChallengeTranscript from '../challenge-transcript';
1717
import { sounds, backgrounds, characterAssets } from './scene-assets';
1818
import Character from './character';
1919
import { SceneSubject } from './scene-subject';
20+
import { buildTranscript } from './scene-helpers';
2021

2122
import './scene.css';
2223

@@ -168,25 +169,6 @@ export function Scene({
168169
setSceneIsReady(true);
169170
};
170171

171-
const buildTranscript = () => {
172-
let transcriptText = '';
173-
commands.forEach(command => {
174-
if (command.character && command.dialogue && command.startTime) {
175-
transcriptText =
176-
transcriptText +
177-
'\n' +
178-
'<strong>' +
179-
command.character +
180-
'</strong>:' +
181-
' ' +
182-
command.dialogue.text +
183-
'\n';
184-
}
185-
});
186-
187-
return transcriptText;
188-
};
189-
190172
const handlePlay = useCallback(() => {
191173
const pausedAt = pausedAtRef.current;
192174
const updateCurrentTime = () => {
@@ -369,7 +351,7 @@ export function Scene({
369351
};
370352
}, []);
371353

372-
const transcriptText = buildTranscript();
354+
const transcriptText = buildTranscript(commands);
373355
return (
374356
<Col lg={10} lgOffset={1} md={10} mdOffset={1}>
375357
<div

0 commit comments

Comments
 (0)