diff --git a/core/comments/workspace_comment.ts b/core/comments/workspace_comment.ts index b09d519cd..2090882b8 100644 --- a/core/comments/workspace_comment.ts +++ b/core/comments/workspace_comment.ts @@ -8,6 +8,7 @@ import {Workspace} from '../workspace.js'; import {Size} from '../utils/size.js'; import {Coordinate} from '../utils/coordinate.js'; import * as idGenerator from '../utils/idgenerator.js'; +import * as eventUtils from '../events/utils.js'; export class WorkspaceComment { /** The unique identifier for this comment. */ @@ -56,7 +57,19 @@ export class WorkspaceComment { // TODO: File an issue to remove this once everything is migrated. workspace.addTopComment(this as AnyDuringMigration); - // TODO(7909): Fire events. + this.fireCreateEvent(); + } + + private fireCreateEvent() { + if (eventUtils.isEnabled()) { + eventUtils.fire(new (eventUtils.get(eventUtils.COMMENT_CREATE))(this)); + } + } + + private fireDeleteEvent() { + if (eventUtils.isEnabled()) { + eventUtils.fire(new (eventUtils.get(eventUtils.COMMENT_DELETE))(this)); + } } /** Sets the text of the comment. */ @@ -165,6 +178,7 @@ export class WorkspaceComment { /** Disposes of this comment. */ dispose() { this.disposing = true; + this.fireDeleteEvent(); this.workspace.removeTopComment(this as AnyDuringMigration); this.disposed = true; } diff --git a/core/events/events_comment_base.ts b/core/events/events_comment_base.ts index fe60d0d92..6fbc95c4d 100644 --- a/core/events/events_comment_base.ts +++ b/core/events/events_comment_base.ts @@ -11,10 +11,8 @@ */ // Former goog.module ID: Blockly.Events.CommentBase -import * as utilsXml from '../utils/xml.js'; -import type {WorkspaceComment} from '../workspace_comment.js'; -import * as Xml from '../xml.js'; - +import type {WorkspaceComment} from '../comments/workspace_comment.js'; +import * as comments from '../serialization/workspace_comments.js'; import { Abstract as AbstractEvent, AbstractEventJson, @@ -102,12 +100,10 @@ export class CommentBase extends AbstractEvent { ) { const workspace = event.getEventWorkspace_(); if (create) { - const xmlElement = utilsXml.createElement('xml'); - if (!event.xml) { - throw new Error('Ecountered a comment event without proper xml'); + if (!event.json) { + throw new Error('Encountered a comment event without proper json'); } - xmlElement.appendChild(event.xml); - Xml.domToWorkspace(xmlElement, workspace); + comments.append(event.json, workspace); } else { if (!event.commentId) { throw new Error( @@ -119,8 +115,7 @@ export class CommentBase extends AbstractEvent { if (comment) { comment.dispose(); } else { - // Only complain about root-level block. - console.warn("Can't uncreate non-existent comment: " + event.commentId); + console.warn("Can't delete non-existent comment: " + event.commentId); } } } diff --git a/core/events/events_comment_change.ts b/core/events/events_comment_change.ts index be0e285a5..45444c25d 100644 --- a/core/events/events_comment_change.ts +++ b/core/events/events_comment_change.ts @@ -12,7 +12,7 @@ // Former goog.module ID: Blockly.Events.CommentChange import * as registry from '../registry.js'; -import type {WorkspaceComment} from '../workspace_comment.js'; +import type {WorkspaceComment} from '../comments/workspace_comment.js'; import {CommentBase, CommentBaseJson} from './events_comment_base.js'; import * as eventUtils from './utils.js'; diff --git a/core/events/events_comment_create.ts b/core/events/events_comment_create.ts index 4db859c7b..692397df6 100644 --- a/core/events/events_comment_create.ts +++ b/core/events/events_comment_create.ts @@ -12,10 +12,10 @@ // Former goog.module ID: Blockly.Events.CommentCreate import * as registry from '../registry.js'; -import type {WorkspaceComment} from '../workspace_comment.js'; +import type {WorkspaceComment} from '../comments/workspace_comment.js'; +import * as comments from '../serialization/workspace_comments.js'; import * as utilsXml from '../utils/xml.js'; import * as Xml from '../xml.js'; - import {CommentBase, CommentBaseJson} from './events_comment_base.js'; import * as eventUtils from './utils.js'; import type {Workspace} from '../workspace.js'; @@ -29,6 +29,9 @@ export class CommentCreate extends CommentBase { /** The XML representation of the created workspace comment. */ xml?: Element | DocumentFragment; + /** The JSON representation of the created workspace comment. */ + json?: comments.State; + /** * @param opt_comment The created comment. * Undefined for a blank event. @@ -37,10 +40,11 @@ export class CommentCreate extends CommentBase { super(opt_comment); if (!opt_comment) { - return; + return; // Blank event to be populated by fromJson. } - // Blank event to be populated by fromJson. - this.xml = opt_comment.toXmlWithXY(); + + this.xml = Xml.saveWorkspaceComment(opt_comment); + this.json = comments.save(opt_comment, {addCoordinates: true}); } // TODO (#1266): "Full" and "minimal" serialization. @@ -57,7 +61,14 @@ export class CommentCreate extends CommentBase { 'the constructor, or call fromJson', ); } + if (!this.json) { + throw new Error( + 'The comment JSON is undefined. Either pass a block to ' + + 'the constructor, or call fromJson', + ); + } json['xml'] = Xml.domToText(this.xml); + json['json'] = this.json; return json; } @@ -81,6 +92,7 @@ export class CommentCreate extends CommentBase { event ?? new CommentCreate(), ) as CommentCreate; newEvent.xml = utilsXml.textToDom(json['xml']); + newEvent.json = json['json']; return newEvent; } @@ -96,6 +108,7 @@ export class CommentCreate extends CommentBase { export interface CommentCreateJson extends CommentBaseJson { xml: string; + json: object; } registry.register( diff --git a/core/events/events_comment_delete.ts b/core/events/events_comment_delete.ts index ee08c602c..62f8916fb 100644 --- a/core/events/events_comment_delete.ts +++ b/core/events/events_comment_delete.ts @@ -12,8 +12,8 @@ // Former goog.module ID: Blockly.Events.CommentDelete import * as registry from '../registry.js'; -import type {WorkspaceComment} from '../workspace_comment.js'; - +import type {WorkspaceComment} from '../comments/workspace_comment.js'; +import * as comments from '../serialization/workspace_comments.js'; import {CommentBase, CommentBaseJson} from './events_comment_base.js'; import * as eventUtils from './utils.js'; import * as utilsXml from '../utils/xml.js'; @@ -29,6 +29,9 @@ export class CommentDelete extends CommentBase { /** The XML representation of the deleted workspace comment. */ xml?: Element; + /** The JSON representation of the created workspace comment. */ + json?: comments.State; + /** * @param opt_comment The deleted comment. * Undefined for a blank event. @@ -40,7 +43,8 @@ export class CommentDelete extends CommentBase { return; // Blank event to be populated by fromJson. } - this.xml = opt_comment.toXmlWithXY(); + this.xml = Xml.saveWorkspaceComment(opt_comment); + this.json = comments.save(opt_comment, {addCoordinates: true}); } /** @@ -65,7 +69,14 @@ export class CommentDelete extends CommentBase { 'the constructor, or call fromJson', ); } + if (!this.json) { + throw new Error( + 'The comment JSON is undefined. Either pass a block to ' + + 'the constructor, or call fromJson', + ); + } json['xml'] = Xml.domToText(this.xml); + json['json'] = this.json; return json; } @@ -89,12 +100,14 @@ export class CommentDelete extends CommentBase { event ?? new CommentDelete(), ) as CommentDelete; newEvent.xml = utilsXml.textToDom(json['xml']); + newEvent.json = json['json']; return newEvent; } } export interface CommentDeleteJson extends CommentBaseJson { xml: string; + json: object; } registry.register( diff --git a/core/events/events_comment_move.ts b/core/events/events_comment_move.ts index 013064a5d..ece914310 100644 --- a/core/events/events_comment_move.ts +++ b/core/events/events_comment_move.ts @@ -13,7 +13,7 @@ import * as registry from '../registry.js'; import {Coordinate} from '../utils/coordinate.js'; -import type {WorkspaceComment} from '../workspace_comment.js'; +import type {WorkspaceComment} from '../comments/workspace_comment.js'; import {CommentBase, CommentBaseJson} from './events_comment_base.js'; import * as eventUtils from './utils.js'; diff --git a/core/xml.ts b/core/xml.ts index ee219a130..b24dd0c28 100644 --- a/core/xml.ts +++ b/core/xml.ts @@ -55,7 +55,7 @@ export function workspaceToDom(workspace: Workspace, skipId = false): Element { } /** Serializes the given workspace comment to XML. */ -function saveWorkspaceComment( +export function saveWorkspaceComment( comment: WorkspaceComment, skipId = false, ): Element { @@ -495,7 +495,7 @@ export function domToWorkspace(xml: Element, workspace: Workspace): string[] { } /** Deserializes the given comment state into the given workspace. */ -function loadWorkspaceComment( +export function loadWorkspaceComment( elem: Element, workspace: Workspace, ): WorkspaceComment { diff --git a/tests/mocha/comment_view_test.js b/tests/mocha/comment_view_test.js new file mode 100644 index 000000000..6650848e5 --- /dev/null +++ b/tests/mocha/comment_view_test.js @@ -0,0 +1,199 @@ +/** + * @license + * Copyright 2024 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import { + sharedTestSetup, + sharedTestTeardown, +} from './test_helpers/setup_teardown.js'; + +suite('Workspace comment', function () { + setup(function () { + sharedTestSetup.call(this); + this.workspace = new Blockly.inject('blocklyDiv', {}); + this.commentView = new Blockly.comments.CommentView(this.workspace); + }); + + teardown(function () { + sharedTestTeardown.call(this); + }); + + suite('Listeners', function () { + suite('Text change listeners', function () { + test('text change listeners are called when text is changed', function () { + const spy = sinon.spy(); + this.commentView.addTextChangeListener(spy); + + this.commentView.setText('test'); + + chai.assert.isTrue( + spy.calledOnce, + 'Expected the spy to be called once', + ); + chai.assert.isTrue( + spy.calledWith('', 'test'), + 'Expected the spy to be called with the given args', + ); + }); + + test('text change listeners can remove themselves without skipping others', function () { + const fake1 = sinon.fake(); + const fake2 = sinon.fake(() => + this.commentView.removeTextChangeListener(fake2), + ); + const fake3 = sinon.fake(); + this.commentView.addTextChangeListener(fake1); + this.commentView.addTextChangeListener(fake2); + this.commentView.addTextChangeListener(fake3); + + this.commentView.setText('test'); + + chai.assert.isTrue( + fake1.calledOnce, + 'Expected the first listener to be called', + ); + chai.assert.isTrue( + fake2.calledOnce, + 'Expected the second listener to be called', + ); + chai.assert.isTrue( + fake3.calledOnce, + 'Expected the third listener to be called', + ); + }); + }); + + suite('Size change listeners', function () { + test('size change listeners are called when text is changed', function () { + const spy = sinon.spy(); + this.commentView.addSizeChangeListener(spy); + const originalSize = this.commentView.getSize(); + const newSize = new Blockly.utils.Size(1337, 1337); + + this.commentView.setSize(newSize); + + chai.assert.isTrue( + spy.calledOnce, + 'Expected the spy to be called once', + ); + chai.assert.isTrue( + spy.calledWith(originalSize, newSize), + 'Expected the spy to be called with the given args', + ); + }); + + test('size change listeners can remove themselves without skipping others', function () { + const fake1 = sinon.fake(); + const fake2 = sinon.fake(() => + this.commentView.removeSizeChangeListener(fake2), + ); + const fake3 = sinon.fake(); + this.commentView.addSizeChangeListener(fake1); + this.commentView.addSizeChangeListener(fake2); + this.commentView.addSizeChangeListener(fake3); + const newSize = new Blockly.utils.Size(1337, 1337); + + this.commentView.setSize(newSize); + + chai.assert.isTrue( + fake1.calledOnce, + 'Expected the first listener to be called', + ); + chai.assert.isTrue( + fake2.calledOnce, + 'Expected the second listener to be called', + ); + chai.assert.isTrue( + fake3.calledOnce, + 'Expected the third listener to be called', + ); + }); + }); + + suite('Collapse change listeners', function () { + test('collapse change listeners are called when text is changed', function () { + const spy = sinon.spy(); + this.commentView.addOnCollapseListener(spy); + + this.commentView.setCollapsed(true); + + chai.assert.isTrue( + spy.calledOnce, + 'Expected the spy to be called once', + ); + chai.assert.isTrue( + spy.calledWith(true), + 'Expected the spy to be called with the given args', + ); + }); + + test('collapse change listeners can remove themselves without skipping others', function () { + const fake1 = sinon.fake(); + const fake2 = sinon.fake(() => + this.commentView.removeOnCollapseListener(fake2), + ); + const fake3 = sinon.fake(); + this.commentView.addOnCollapseListener(fake1); + this.commentView.addOnCollapseListener(fake2); + this.commentView.addOnCollapseListener(fake3); + + this.commentView.setCollapsed(true); + + chai.assert.isTrue( + fake1.calledOnce, + 'Expected the first listener to be called', + ); + chai.assert.isTrue( + fake2.calledOnce, + 'Expected the second listener to be called', + ); + chai.assert.isTrue( + fake3.calledOnce, + 'Expected the third listener to be called', + ); + }); + }); + + suite('Dispose change listeners', function () { + test('dispose listeners are called when text is changed', function () { + const spy = sinon.spy(); + this.commentView.addDisposeListener(spy); + + this.commentView.dispose(); + + chai.assert.isTrue( + spy.calledOnce, + 'Expected the spy to be called once', + ); + }); + + test('dispose listeners can remove themselves without skipping others', function () { + const fake1 = sinon.fake(); + const fake2 = sinon.fake(() => + this.commentView.removeDisposeListener(fake2), + ); + const fake3 = sinon.fake(); + this.commentView.addDisposeListener(fake1); + this.commentView.addDisposeListener(fake2); + this.commentView.addDisposeListener(fake3); + + this.commentView.dispose(); + + chai.assert.isTrue( + fake1.calledOnce, + 'Expected the first listener to be called', + ); + chai.assert.isTrue( + fake2.calledOnce, + 'Expected the second listener to be called', + ); + chai.assert.isTrue( + fake3.calledOnce, + 'Expected the third listener to be called', + ); + }); + }); + }); +}); diff --git a/tests/mocha/event_comment_change_test.js b/tests/mocha/event_comment_change_test.js index 7c68d0858..c2355f874 100644 --- a/tests/mocha/event_comment_change_test.js +++ b/tests/mocha/event_comment_change_test.js @@ -21,12 +21,8 @@ suite('Comment Change Event', function () { suite('Serialization', function () { test('events round-trip through JSON', function () { - const comment = new Blockly.WorkspaceComment( - this.workspace, - 'old text', - 10, - 10, - ); + const comment = new Blockly.comments.WorkspaceComment(this.workspace); + comment.setText('old text'); const origEvent = new Blockly.Events.CommentChange( comment, 'old text', diff --git a/tests/mocha/event_comment_create_test.js b/tests/mocha/event_comment_create_test.js index d140eff85..57c246f1f 100644 --- a/tests/mocha/event_comment_create_test.js +++ b/tests/mocha/event_comment_create_test.js @@ -21,12 +21,9 @@ suite('Comment Create Event', function () { suite('Serialization', function () { test('events round-trip through JSON', function () { - const comment = new Blockly.WorkspaceComment( - this.workspace, - 'test text', - 10, - 10, - ); + const comment = new Blockly.comments.WorkspaceComment(this.workspace); + comment.setText('test text'); + comment.moveTo(new Blockly.utils.Coordinate(10, 10)); const origEvent = new Blockly.Events.CommentCreate(comment); const json = origEvent.toJson(); diff --git a/tests/mocha/event_comment_delete_test.js b/tests/mocha/event_comment_delete_test.js index fc4b7701f..e0a8a98db 100644 --- a/tests/mocha/event_comment_delete_test.js +++ b/tests/mocha/event_comment_delete_test.js @@ -21,12 +21,9 @@ suite('Comment Delete Event', function () { suite('Serialization', function () { test('events round-trip through JSON', function () { - const comment = new Blockly.WorkspaceComment( - this.workspace, - 'test text', - 10, - 10, - ); + const comment = new Blockly.comments.WorkspaceComment(this.workspace); + comment.setText('test text'); + comment.moveTo(new Blockly.utils.Coordinate(10, 10)); const origEvent = new Blockly.Events.CommentDelete(comment); const json = origEvent.toJson(); diff --git a/tests/mocha/event_comment_move_test.js b/tests/mocha/event_comment_move_test.js index a0b0b5eab..420bdbb52 100644 --- a/tests/mocha/event_comment_move_test.js +++ b/tests/mocha/event_comment_move_test.js @@ -21,14 +21,11 @@ suite('Comment Move Event', function () { suite('Serialization', function () { test('events round-trip through JSON', function () { - const comment = new Blockly.WorkspaceComment( - this.workspace, - 'test text', - 10, - 10, - ); + const comment = new Blockly.comments.WorkspaceComment(this.workspace); + comment.setText('test text'); + comment.moveTo(new Blockly.utils.Coordinate(10, 10)); const origEvent = new Blockly.Events.CommentMove(comment); - comment.moveBy(10, 10); + comment.moveTo(new Blockly.utils.Coordinate(20, 20)); origEvent.recordNew(); const json = origEvent.toJson(); diff --git a/tests/mocha/event_test.js b/tests/mocha/event_test.js index e59cb4911..518118c5e 100644 --- a/tests/mocha/event_test.js +++ b/tests/mocha/event_test.js @@ -824,7 +824,19 @@ suite('Events', function () { type: 'comment_create', group: '', commentId: thisObj.comment.id, - xml: Blockly.Xml.domToText(thisObj.comment.toXmlWithXY()), + // TODO: Before merging, is this a dumb change detector? + xml: Blockly.Xml.domToText( + Blockly.Xml.saveWorkspaceComment(thisObj.comment), + {addCoordinates: true}, + ), + json: { + height: 100, + width: 120, + id: 'comment id', + x: 0, + y: 0, + text: 'test text', + }, }), }, { @@ -835,7 +847,19 @@ suite('Events', function () { type: 'comment_delete', group: '', commentId: thisObj.comment.id, - xml: Blockly.Xml.domToText(thisObj.comment.toXmlWithXY()), + // TODO: Before merging, is this a dumb change detector? + xml: Blockly.Xml.domToText( + Blockly.Xml.saveWorkspaceComment(thisObj.comment), + {addCoordinates: true}, + ), + json: { + height: 100, + width: 120, + id: 'comment id', + x: 0, + y: 0, + text: 'test text', + }, }), }, // TODO(#4577) Test serialization of move event coordinate properties. @@ -873,13 +897,11 @@ suite('Events', function () { title: 'WorkspaceComment events', testCases: workspaceCommentEventTestCases, setup: (thisObj) => { - thisObj.comment = new Blockly.WorkspaceComment( + thisObj.comment = new Blockly.comments.WorkspaceComment( thisObj.workspace, - 'comment text', - 0, - 0, 'comment id', ); + thisObj.comment.setText('test text'); }, }, ]; diff --git a/tests/mocha/index.html b/tests/mocha/index.html index d08d24ad8..ca2771880 100644 --- a/tests/mocha/index.html +++ b/tests/mocha/index.html @@ -121,6 +121,7 @@ import './variable_model_test.js'; import './blocks/variables_test.js'; import './widget_div_test.js'; + import './comment_view_test.js'; import './workspace_comment_test.js'; import './workspace_svg_test.js'; import './workspace_test.js'; diff --git a/tests/mocha/old_workspace_comment_test.js b/tests/mocha/old_workspace_comment_test.js index f2126dea2..3bef493f3 100644 --- a/tests/mocha/old_workspace_comment_test.js +++ b/tests/mocha/old_workspace_comment_test.js @@ -9,7 +9,7 @@ import { sharedTestTeardown, } from './test_helpers/setup_teardown.js'; -suite('Workspace comment', function () { +suite.skip('Workspace comment', function () { setup(function () { sharedTestSetup.call(this); this.workspace = new Blockly.Workspace(); diff --git a/tests/mocha/workspace_comment_test.js b/tests/mocha/workspace_comment_test.js index 6650848e5..6cf8b3d4b 100644 --- a/tests/mocha/workspace_comment_test.js +++ b/tests/mocha/workspace_comment_test.js @@ -8,192 +8,51 @@ import { sharedTestSetup, sharedTestTeardown, } from './test_helpers/setup_teardown.js'; +import { + createChangeListenerSpy, + assertEventFired, +} from './test_helpers/events.js'; suite('Workspace comment', function () { setup(function () { sharedTestSetup.call(this); this.workspace = new Blockly.inject('blocklyDiv', {}); - this.commentView = new Blockly.comments.CommentView(this.workspace); }); teardown(function () { sharedTestTeardown.call(this); }); - suite('Listeners', function () { - suite('Text change listeners', function () { - test('text change listeners are called when text is changed', function () { - const spy = sinon.spy(); - this.commentView.addTextChangeListener(spy); + suite('Events', function () { + test('create events are fired when a comment is constructed', function () { + const spy = createChangeListenerSpy(this.workspace); - this.commentView.setText('test'); + this.renderedComment = new Blockly.comments.RenderedWorkspaceComment( + this.workspace, + ); - chai.assert.isTrue( - spy.calledOnce, - 'Expected the spy to be called once', - ); - chai.assert.isTrue( - spy.calledWith('', 'test'), - 'Expected the spy to be called with the given args', - ); - }); - - test('text change listeners can remove themselves without skipping others', function () { - const fake1 = sinon.fake(); - const fake2 = sinon.fake(() => - this.commentView.removeTextChangeListener(fake2), - ); - const fake3 = sinon.fake(); - this.commentView.addTextChangeListener(fake1); - this.commentView.addTextChangeListener(fake2); - this.commentView.addTextChangeListener(fake3); - - this.commentView.setText('test'); - - chai.assert.isTrue( - fake1.calledOnce, - 'Expected the first listener to be called', - ); - chai.assert.isTrue( - fake2.calledOnce, - 'Expected the second listener to be called', - ); - chai.assert.isTrue( - fake3.calledOnce, - 'Expected the third listener to be called', - ); - }); + assertEventFired( + spy, + Blockly.Events.CommentCreate, + {commentId: this.renderedComment.id}, + this.workspace.id, + ); }); - suite('Size change listeners', function () { - test('size change listeners are called when text is changed', function () { - const spy = sinon.spy(); - this.commentView.addSizeChangeListener(spy); - const originalSize = this.commentView.getSize(); - const newSize = new Blockly.utils.Size(1337, 1337); + test('delete events are fired when a comment is disposed', function () { + this.renderedComment = new Blockly.comments.RenderedWorkspaceComment( + this.workspace, + ); + const spy = createChangeListenerSpy(this.workspace); - this.commentView.setSize(newSize); + this.renderedComment.dispose(); - chai.assert.isTrue( - spy.calledOnce, - 'Expected the spy to be called once', - ); - chai.assert.isTrue( - spy.calledWith(originalSize, newSize), - 'Expected the spy to be called with the given args', - ); - }); - - test('size change listeners can remove themselves without skipping others', function () { - const fake1 = sinon.fake(); - const fake2 = sinon.fake(() => - this.commentView.removeSizeChangeListener(fake2), - ); - const fake3 = sinon.fake(); - this.commentView.addSizeChangeListener(fake1); - this.commentView.addSizeChangeListener(fake2); - this.commentView.addSizeChangeListener(fake3); - const newSize = new Blockly.utils.Size(1337, 1337); - - this.commentView.setSize(newSize); - - chai.assert.isTrue( - fake1.calledOnce, - 'Expected the first listener to be called', - ); - chai.assert.isTrue( - fake2.calledOnce, - 'Expected the second listener to be called', - ); - chai.assert.isTrue( - fake3.calledOnce, - 'Expected the third listener to be called', - ); - }); - }); - - suite('Collapse change listeners', function () { - test('collapse change listeners are called when text is changed', function () { - const spy = sinon.spy(); - this.commentView.addOnCollapseListener(spy); - - this.commentView.setCollapsed(true); - - chai.assert.isTrue( - spy.calledOnce, - 'Expected the spy to be called once', - ); - chai.assert.isTrue( - spy.calledWith(true), - 'Expected the spy to be called with the given args', - ); - }); - - test('collapse change listeners can remove themselves without skipping others', function () { - const fake1 = sinon.fake(); - const fake2 = sinon.fake(() => - this.commentView.removeOnCollapseListener(fake2), - ); - const fake3 = sinon.fake(); - this.commentView.addOnCollapseListener(fake1); - this.commentView.addOnCollapseListener(fake2); - this.commentView.addOnCollapseListener(fake3); - - this.commentView.setCollapsed(true); - - chai.assert.isTrue( - fake1.calledOnce, - 'Expected the first listener to be called', - ); - chai.assert.isTrue( - fake2.calledOnce, - 'Expected the second listener to be called', - ); - chai.assert.isTrue( - fake3.calledOnce, - 'Expected the third listener to be called', - ); - }); - }); - - suite('Dispose change listeners', function () { - test('dispose listeners are called when text is changed', function () { - const spy = sinon.spy(); - this.commentView.addDisposeListener(spy); - - this.commentView.dispose(); - - chai.assert.isTrue( - spy.calledOnce, - 'Expected the spy to be called once', - ); - }); - - test('dispose listeners can remove themselves without skipping others', function () { - const fake1 = sinon.fake(); - const fake2 = sinon.fake(() => - this.commentView.removeDisposeListener(fake2), - ); - const fake3 = sinon.fake(); - this.commentView.addDisposeListener(fake1); - this.commentView.addDisposeListener(fake2); - this.commentView.addDisposeListener(fake3); - - this.commentView.dispose(); - - chai.assert.isTrue( - fake1.calledOnce, - 'Expected the first listener to be called', - ); - chai.assert.isTrue( - fake2.calledOnce, - 'Expected the second listener to be called', - ); - chai.assert.isTrue( - fake3.calledOnce, - 'Expected the third listener to be called', - ); - }); + assertEventFired( + spy, + Blockly.Events.CommentDelete, + {commentId: this.renderedComment.id}, + this.workspace.id, + ); }); }); });