Skip to content

Commit 71b8967

Browse files
committed
test: expand RhythmBlocks test suite coverage (#5607)
1 parent a439d40 commit 71b8967

File tree

1 file changed

+134
-0
lines changed

1 file changed

+134
-0
lines changed

js/blocks/__tests__/RhythmBlocks.test.js

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,4 +450,138 @@ describe("RhythmBlocks", () => {
450450
expect(block.hidden).toBe(true);
451451
});
452452
});
453+
454+
describe("Edge Cases and Additional Coverage", () => {
455+
test("MyNoteValueBlock handles undefined connections gracefully", () => {
456+
activity.blocks.blockList[1] = { connections: undefined };
457+
global.Singer.RhythmActions.getNoteValue.mockReturnValue(0);
458+
459+
const block = getBlock("mynotevalue");
460+
const result = block.arg(logo, 0, 1);
461+
462+
expect(result).toBe(0);
463+
});
464+
465+
test("SkipNotesBlock handles zero skip value", () => {
466+
turtle.singer.skipFactor = 0;
467+
const block = getBlock("skipnotes");
468+
block.flow([0, true], logo, 0, 10);
469+
470+
expect(turtle.singer.skipFactor).toBe(0);
471+
});
472+
473+
test("SkipNotesBlock handles negative skip value", () => {
474+
turtle.singer.skipFactor = 0;
475+
const block = getBlock("skipnotes");
476+
block.flow([-5, true], logo, 0, 10);
477+
478+
expect(turtle.singer.skipFactor).toBe(-5);
479+
});
480+
481+
test("MultiplyBeatFactorBlock handles fractional factor", () => {
482+
const block = getBlock("multiplybeatfactor");
483+
block.flow([0.5, true], logo, 0, 10);
484+
485+
expect(global.Singer.RhythmActions.multiplyNoteValue).toHaveBeenCalledWith(0.5, 0, 10);
486+
});
487+
488+
test("RhythmicDotBlock handles single dot", () => {
489+
const block = getBlock("rhythmicdot");
490+
block.flow([true], logo, 0, 10);
491+
492+
expect(global.Singer.RhythmActions.doRhythmicDot).toHaveBeenCalledWith(1, 0, 10);
493+
});
494+
495+
test("RhythmicDot2Block handles multiple dots", () => {
496+
const block = getBlock("rhythmicdot2");
497+
block.flow([3, true], logo, 0, 10);
498+
499+
expect(global.Singer.RhythmActions.doRhythmicDot).toHaveBeenCalledWith(3, 0, 10);
500+
});
501+
502+
test("NewNoteBlock registers correctly", () => {
503+
const block = getBlock("newnote");
504+
expect(block).toBeDefined();
505+
expect(block.formDefn.args).toBe(2);
506+
});
507+
508+
test("NoteBlock macros are defined", () => {
509+
const noteBlocks = ["note1", "note2", "note3", "note4", "note5", "note6", "note7", "note8"];
510+
noteBlocks.forEach(blockName => {
511+
const block = getBlock(blockName);
512+
expect(block).toBeDefined();
513+
expect(block.macro).toBeDefined();
514+
});
515+
});
516+
517+
test("OctaveSpaceBlock is defined", () => {
518+
const block = getBlock("octavespace");
519+
expect(block).toBeDefined();
520+
});
521+
522+
test("DefineFrequencyBlock is defined", () => {
523+
const block = getBlock("definefrequency");
524+
expect(block).toBeDefined();
525+
});
526+
527+
test("All rhythm blocks have proper palette assignment", () => {
528+
const rhythmBlockNames = [
529+
"mynotevalue", "skipfactor", "osctime", "swing", "newswing",
530+
"newswing2", "skipnotes", "multiplybeatfactor", "tie",
531+
"rhythmicdot", "rhythmicdot2", "rest2", "note", "newnote"
532+
];
533+
534+
rhythmBlockNames.forEach(blockName => {
535+
const block = activity.registeredBlocks[blockName];
536+
if (block) {
537+
expect(block.palette).toBe("rhythm");
538+
}
539+
});
540+
});
541+
542+
test("Flow blocks return correct tuple format", () => {
543+
const flowBlocks = ["swing", "newswing2", "skipnotes", "multiplybeatfactor", "tie"];
544+
545+
flowBlocks.forEach(blockName => {
546+
const block = getBlock(blockName);
547+
if (block && block.flow) {
548+
const result = block.flow([1, true], logo, 0, 10);
549+
if (result) {
550+
expect(Array.isArray(result)).toBe(true);
551+
expect(result.length).toBe(2);
552+
}
553+
}
554+
});
555+
});
556+
});
557+
558+
describe("Error Handling", () => {
559+
test("handles logo with missing statusFields", () => {
560+
logo.inStatusMatrix = true;
561+
logo.statusFields = undefined;
562+
activity.blocks.blockList[1] = { connections: [2] };
563+
activity.blocks.blockList[2] = { name: "print" };
564+
565+
const block = getBlock("mynotevalue");
566+
expect(() => block.arg(logo, 0, 1)).not.toThrow();
567+
});
568+
569+
test("handles turtle with missing singer object", () => {
570+
activity.turtles.ithTurtle = jest.fn(() => ({}));
571+
activity.blocks.blockList[1] = { connections: [0] };
572+
573+
const block = getBlock("skipfactor");
574+
expect(() => block.arg(logo, 0, 1)).not.toThrow();
575+
});
576+
577+
test("handles null blockList entries", () => {
578+
activity.blocks.blockList = { 0: null, 1: null };
579+
global.Singer.RhythmActions.getNoteValue.mockReturnValue(0);
580+
581+
const block = getBlock("mynotevalue");
582+
const result = block.arg(logo, 0, 1);
583+
584+
expect(result).toBe(0);
585+
});
586+
});
453587
});

0 commit comments

Comments
 (0)