mirror of
https://github.com/google/blockly.git
synced 2026-01-10 02:17:09 +01:00
Merge pull request #5237 from rachel-fenichel/clipboard
Move clipboard functions to a separate namespace
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
goog.provide('Blockly');
|
||||
|
||||
goog.require('Blockly.browserEvents');
|
||||
goog.require('Blockly.clipboard');
|
||||
goog.require('Blockly.ComponentManager');
|
||||
goog.require('Blockly.connectionTypes');
|
||||
goog.require('Blockly.constants');
|
||||
@@ -91,27 +92,6 @@ Blockly.selected = null;
|
||||
*/
|
||||
Blockly.draggingConnections = [];
|
||||
|
||||
/**
|
||||
* Contents of the local clipboard.
|
||||
* @type {Element}
|
||||
* @private
|
||||
*/
|
||||
Blockly.clipboardXml_ = null;
|
||||
|
||||
/**
|
||||
* Source of the local clipboard.
|
||||
* @type {Blockly.WorkspaceSvg}
|
||||
* @private
|
||||
*/
|
||||
Blockly.clipboardSource_ = null;
|
||||
|
||||
/**
|
||||
* Map of types to type counts for the clipboard object and descendants.
|
||||
* @type {Object}
|
||||
* @private
|
||||
*/
|
||||
Blockly.clipboardTypeCounts_ = null;
|
||||
|
||||
/**
|
||||
* Cached value for whether 3D is supported.
|
||||
* @type {?boolean}
|
||||
@@ -136,9 +116,7 @@ Blockly.svgSize = function(svg) {
|
||||
// When removing this function, remove svg.cachedWidth_ and svg.cachedHeight_
|
||||
// from setCachedParentSvgSize.
|
||||
Blockly.utils.deprecation.warn(
|
||||
'Blockly.svgSize',
|
||||
'March 2021',
|
||||
'March 2022',
|
||||
'Blockly.svgSize', 'March 2021', 'March 2022',
|
||||
'workspace.getCachedParentSvgSize');
|
||||
svg = /** @type {?} */ (svg);
|
||||
return new Blockly.utils.Size(svg.cachedWidth_, svg.cachedHeight_);
|
||||
@@ -220,7 +198,8 @@ Blockly.deleteBlock = function(selected) {
|
||||
Blockly.Events.setGroup(true);
|
||||
Blockly.hideChaff();
|
||||
if (selected.outputConnection) {
|
||||
// Do not attempt to heal rows (https://github.com/google/blockly/issues/4832)
|
||||
// Do not attempt to heal rows
|
||||
// (https://github.com/google/blockly/issues/4832)
|
||||
selected.dispose(false, true);
|
||||
} else {
|
||||
selected.dispose(/* heal */ true, true);
|
||||
@@ -234,39 +213,14 @@ Blockly.deleteBlock = function(selected) {
|
||||
* @param {!Blockly.ICopyable} toCopy Block or Workspace Comment to be copied.
|
||||
* @package
|
||||
*/
|
||||
Blockly.copy = function(toCopy) {
|
||||
var data = toCopy.toCopyData();
|
||||
if (data) {
|
||||
Blockly.clipboardXml_ = data.xml;
|
||||
Blockly.clipboardSource_ = data.source;
|
||||
Blockly.clipboardTypeCounts_ = data.typeCounts;
|
||||
}
|
||||
};
|
||||
Blockly.copy = Blockly.clipboard.copy;
|
||||
|
||||
/**
|
||||
* Paste a block or workspace comment on to the main workspace.
|
||||
* @return {boolean} True if the paste was successful, false otherwise.
|
||||
* @package
|
||||
*/
|
||||
Blockly.paste = function() {
|
||||
if (!Blockly.clipboardXml_) {
|
||||
return false;
|
||||
}
|
||||
// Pasting always pastes to the main workspace, even if the copy
|
||||
// started in a flyout workspace.
|
||||
var workspace = Blockly.clipboardSource_;
|
||||
if (workspace.isFlyout) {
|
||||
workspace = workspace.targetWorkspace;
|
||||
}
|
||||
if (Blockly.clipboardTypeCounts_ &&
|
||||
workspace.isCapacityAvailable(Blockly.clipboardTypeCounts_)) {
|
||||
Blockly.Events.setGroup(true);
|
||||
workspace.paste(Blockly.clipboardXml_);
|
||||
Blockly.Events.setGroup(false);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
Blockly.paste = Blockly.clipboard.paste;
|
||||
|
||||
/**
|
||||
* Duplicate this block and its children, or a workspace comment.
|
||||
@@ -274,19 +228,7 @@ Blockly.paste = function() {
|
||||
* copied.
|
||||
* @package
|
||||
*/
|
||||
Blockly.duplicate = function(toDuplicate) {
|
||||
// Save the clipboard.
|
||||
var clipboardXml = Blockly.clipboardXml_;
|
||||
var clipboardSource = Blockly.clipboardSource_;
|
||||
|
||||
// Create a duplicate via a copy/paste operation.
|
||||
Blockly.copy(toDuplicate);
|
||||
toDuplicate.workspace.paste(Blockly.clipboardXml_);
|
||||
|
||||
// Restore the clipboard.
|
||||
Blockly.clipboardXml_ = clipboardXml;
|
||||
Blockly.clipboardSource_ = clipboardSource;
|
||||
};
|
||||
Blockly.duplicate = Blockly.clipboard.duplicate;
|
||||
|
||||
/**
|
||||
* Cancel the native context menu, unless the focus is on an HTML input widget.
|
||||
@@ -402,9 +344,7 @@ Blockly.defineBlocksWithJsonArray = function(jsonArray) {
|
||||
'Block definition #' + i + ' in JSON array' +
|
||||
' overwrites prior definition of "' + typename + '".');
|
||||
}
|
||||
Blockly.Blocks[typename] = {
|
||||
init: Blockly.jsonInitFactory_(elem)
|
||||
};
|
||||
Blockly.Blocks[typename] = {init: Blockly.jsonInitFactory_(elem)};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
80
core/clipboard.js
Normal file
80
core/clipboard.js
Normal file
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2021 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Blockly's internal clipboard for managing copy-paste.
|
||||
* @author fenichel@google.com (Rachel Fenichel)
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.module('Blockly.clipboard');
|
||||
goog.module.declareLegacyNamespace();
|
||||
|
||||
const Events = goog.require('Blockly.Events');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const ICopyable = goog.requireType('Blockly.ICopyable');
|
||||
|
||||
/**
|
||||
* Metadata about the object that is currently on the clipboard.
|
||||
* @type {?ICopyable.CopyData}
|
||||
*/
|
||||
let copyData = null;
|
||||
|
||||
/**
|
||||
* Copy a block or workspace comment onto the local clipboard.
|
||||
* @param {!ICopyable} toCopy Block or Workspace Comment to be copied.
|
||||
*/
|
||||
const copy = function(toCopy) {
|
||||
copyData = toCopy.toCopyData();
|
||||
};
|
||||
/** @package */
|
||||
exports.copy = copy;
|
||||
|
||||
/**
|
||||
* Paste a block or workspace comment on to the main workspace.
|
||||
* @return {boolean} True if the paste was successful, false otherwise.
|
||||
*/
|
||||
const paste = function() {
|
||||
if (!copyData.xml) {
|
||||
return false;
|
||||
}
|
||||
// Pasting always pastes to the main workspace, even if the copy
|
||||
// started in a flyout workspace.
|
||||
var workspace = copyData.source;
|
||||
if (workspace.isFlyout) {
|
||||
workspace = workspace.targetWorkspace;
|
||||
}
|
||||
if (copyData.typeCounts &&
|
||||
workspace.isCapacityAvailable(copyData.typeCounts)) {
|
||||
Events.setGroup(true);
|
||||
workspace.paste(copyData.xml);
|
||||
Events.setGroup(false);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
/** @package */
|
||||
exports.paste = paste;
|
||||
|
||||
/**
|
||||
* Duplicate this block and its children, or a workspace comment.
|
||||
* @param {!ICopyable} toDuplicate Block or Workspace Comment to be
|
||||
* duplicated.
|
||||
*/
|
||||
const duplicate = function(toDuplicate) {
|
||||
// Save the clipboard.
|
||||
const oldCopyData = copyData;
|
||||
|
||||
// Create a duplicate via a copy/paste operation.
|
||||
copy(toDuplicate);
|
||||
// copy() replaced the value of copyData.
|
||||
toDuplicate.workspace.paste(copyData.xml);
|
||||
|
||||
// Restore the clipboard.
|
||||
copyData = oldCopyData;
|
||||
};
|
||||
/** @package */
|
||||
exports.duplicate = duplicate;
|
||||
@@ -15,7 +15,7 @@
|
||||
* @namespace
|
||||
*/
|
||||
goog.provide('Blockly.ContextMenuItems');
|
||||
|
||||
goog.require('Blockly.clipboard');
|
||||
/** @suppress {extraRequire} */
|
||||
goog.require('Blockly.constants');
|
||||
goog.require('Blockly.ContextMenuRegistry');
|
||||
@@ -316,7 +316,7 @@ Blockly.ContextMenuItems.registerDuplicate = function() {
|
||||
},
|
||||
callback: function(/** @type {!Blockly.ContextMenuRegistry.Scope} */ scope) {
|
||||
if (scope.block) {
|
||||
Blockly.duplicate(scope.block);
|
||||
Blockly.clipboard.duplicate(scope.block);
|
||||
}
|
||||
},
|
||||
scopeType: Blockly.ContextMenuRegistry.ScopeType.BLOCK,
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
goog.provide('Blockly.ShortcutItems');
|
||||
|
||||
goog.require('Blockly.clipboard');
|
||||
goog.require('Blockly.Gesture');
|
||||
goog.require('Blockly.ShortcutRegistry');
|
||||
goog.require('Blockly.utils.KeyCodes');
|
||||
@@ -104,7 +105,7 @@ Blockly.ShortcutItems.registerCopy = function() {
|
||||
// an error due to the lack of a selection.
|
||||
e.preventDefault();
|
||||
Blockly.hideChaff();
|
||||
Blockly.copy(/** @type {!Blockly.ICopyable} */ (Blockly.selected));
|
||||
Blockly.clipboard.copy(/** @type {!Blockly.ICopyable} */ (Blockly.selected));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -137,7 +138,7 @@ Blockly.ShortcutItems.registerCut = function() {
|
||||
!Blockly.selected.workspace.isFlyout;
|
||||
},
|
||||
callback: function() {
|
||||
Blockly.copy(/** @type {!Blockly.ICopyable} */ (Blockly.selected));
|
||||
Blockly.clipboard.copy(/** @type {!Blockly.ICopyable} */ (Blockly.selected));
|
||||
Blockly.deleteBlock(/** @type {!Blockly.BlockSvg} */ (Blockly.selected));
|
||||
return true;
|
||||
}
|
||||
@@ -167,7 +168,7 @@ Blockly.ShortcutItems.registerPaste = function() {
|
||||
return !workspace.options.readOnly && !Blockly.Gesture.inProgress();
|
||||
},
|
||||
callback: function() {
|
||||
return Blockly.paste();
|
||||
return Blockly.clipboard.paste();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -12,11 +12,12 @@ goog.addDependency('../../core/block_animations.js', ['Blockly.blockAnimations']
|
||||
goog.addDependency('../../core/block_drag_surface.js', ['Blockly.BlockDragSurfaceSvg'], ['Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/block_dragger.js', ['Blockly.BlockDragger'], ['Blockly.Events', 'Blockly.Events.BlockDrag', 'Blockly.Events.BlockMove', 'Blockly.IBlockDragger', 'Blockly.InsertionMarkerManager', 'Blockly.blockAnimations', 'Blockly.registry', 'Blockly.utils.Coordinate', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/block_svg.js', ['Blockly.BlockSvg'], ['Blockly.ASTNode', 'Blockly.Block', 'Blockly.ContextMenu', 'Blockly.ContextMenuRegistry', 'Blockly.Events', 'Blockly.Events.BlockMove', 'Blockly.Events.Selected', 'Blockly.IASTNodeLocationSvg', 'Blockly.IBoundedElement', 'Blockly.ICopyable', 'Blockly.IDraggable', 'Blockly.Msg', 'Blockly.RenderedConnection', 'Blockly.TabNavigateCursor', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.Xml', 'Blockly.blockAnimations', 'Blockly.blockRendering.IPathObject', 'Blockly.browserEvents', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.internalConstants', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.Svg', 'Blockly.utils.deprecation', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent']);
|
||||
goog.addDependency('../../core/blockly.js', ['Blockly'], ['Blockly.ComponentManager', 'Blockly.DropDownDiv', 'Blockly.Events', 'Blockly.Events.BlockCreate', 'Blockly.Events.FinishedLoading', 'Blockly.Events.Ui', 'Blockly.Events.UiBase', 'Blockly.Events.VarCreate', 'Blockly.Procedures', 'Blockly.ShortcutRegistry', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.Variables', 'Blockly.WidgetDiv', 'Blockly.WorkspaceSvg', 'Blockly.Xml', 'Blockly.browserEvents', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.inject', 'Blockly.inputTypes', 'Blockly.internalConstants', 'Blockly.utils', 'Blockly.utils.Size', 'Blockly.utils.colour', 'Blockly.utils.deprecation', 'Blockly.utils.toolbox']);
|
||||
goog.addDependency('../../core/blockly.js', ['Blockly'], ['Blockly.ComponentManager', 'Blockly.DropDownDiv', 'Blockly.Events', 'Blockly.Events.BlockCreate', 'Blockly.Events.FinishedLoading', 'Blockly.Events.Ui', 'Blockly.Events.UiBase', 'Blockly.Events.VarCreate', 'Blockly.Procedures', 'Blockly.ShortcutRegistry', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.Variables', 'Blockly.WidgetDiv', 'Blockly.WorkspaceSvg', 'Blockly.Xml', 'Blockly.browserEvents', 'Blockly.clipboard', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.inject', 'Blockly.inputTypes', 'Blockly.internalConstants', 'Blockly.utils', 'Blockly.utils.Size', 'Blockly.utils.colour', 'Blockly.utils.deprecation', 'Blockly.utils.toolbox']);
|
||||
goog.addDependency('../../core/blocks.js', ['Blockly.Blocks'], [], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/browser_events.js', ['Blockly.browserEvents'], ['Blockly.Touch', 'Blockly.utils.global']);
|
||||
goog.addDependency('../../core/bubble.js', ['Blockly.Bubble'], ['Blockly.IBubble', 'Blockly.Scrollbar', 'Blockly.Touch', 'Blockly.Workspace', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.math', 'Blockly.utils.userAgent']);
|
||||
goog.addDependency('../../core/bubble_dragger.js', ['Blockly.BubbleDragger'], ['Blockly.Bubble', 'Blockly.ComponentManager', 'Blockly.Events', 'Blockly.Events.CommentMove', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.Coordinate'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/clipboard.js', ['Blockly.clipboard'], ['Blockly.Events'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/comment.js', ['Blockly.Comment'], ['Blockly.Bubble', 'Blockly.Css', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Events.BubbleOpen', 'Blockly.Icon', 'Blockly.Warning', 'Blockly.browserEvents', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/component_manager.js', ['Blockly.ComponentManager'], [], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/connection.js', ['Blockly.Connection'], ['Blockly.Events', 'Blockly.Events.BlockMove', 'Blockly.IASTNodeLocationWithBlock', 'Blockly.Xml', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.utils.deprecation'], {'lang': 'es6', 'module': 'goog'});
|
||||
@@ -25,7 +26,7 @@ goog.addDependency('../../core/connection_db.js', ['Blockly.ConnectionDB'], ['Bl
|
||||
goog.addDependency('../../core/connection_types.js', ['Blockly.connectionTypes'], [], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/constants.js', ['Blockly.constants'], [], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/contextmenu.js', ['Blockly.ContextMenu'], ['Blockly.Events', 'Blockly.Events.BlockCreate', 'Blockly.Menu', 'Blockly.MenuItem', 'Blockly.Msg', 'Blockly.WidgetDiv', 'Blockly.Xml', 'Blockly.browserEvents', 'Blockly.internalConstants', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.userAgent']);
|
||||
goog.addDependency('../../core/contextmenu_items.js', ['Blockly.ContextMenuItems'], ['Blockly.ContextMenuRegistry', 'Blockly.Events', 'Blockly.constants', 'Blockly.inputTypes'], {'lang': 'es5'});
|
||||
goog.addDependency('../../core/contextmenu_items.js', ['Blockly.ContextMenuItems'], ['Blockly.ContextMenuRegistry', 'Blockly.Events', 'Blockly.clipboard', 'Blockly.constants', 'Blockly.inputTypes'], {'lang': 'es5'});
|
||||
goog.addDependency('../../core/contextmenu_registry.js', ['Blockly.ContextMenuRegistry'], [], {'lang': 'es5'});
|
||||
goog.addDependency('../../core/css.js', ['Blockly.Css'], [], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/delete_area.js', ['Blockly.DeleteArea'], ['Blockly.BlockSvg', 'Blockly.DragTarget', 'Blockly.IDeleteArea', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'});
|
||||
@@ -159,7 +160,7 @@ goog.addDependency('../../core/renderers/zelos/path_object.js', ['Blockly.zelos.
|
||||
goog.addDependency('../../core/renderers/zelos/renderer.js', ['Blockly.zelos.Renderer'], ['Blockly.InsertionMarkerManager', 'Blockly.blockRendering', 'Blockly.blockRendering.Renderer', 'Blockly.connectionTypes', 'Blockly.utils.object', 'Blockly.zelos.ConstantProvider', 'Blockly.zelos.Drawer', 'Blockly.zelos.MarkerSvg', 'Blockly.zelos.PathObject', 'Blockly.zelos.RenderInfo']);
|
||||
goog.addDependency('../../core/requires.js', ['Blockly.requires'], ['Blockly', 'Blockly.Comment', 'Blockly.ContextMenuItems', 'Blockly.FieldAngle', 'Blockly.FieldCheckbox', 'Blockly.FieldColour', 'Blockly.FieldDropdown', 'Blockly.FieldImage', 'Blockly.FieldLabelSerializable', 'Blockly.FieldMultilineInput', 'Blockly.FieldNumber', 'Blockly.FieldTextInput', 'Blockly.FieldVariable', 'Blockly.FlyoutButton', 'Blockly.Generator', 'Blockly.HorizontalFlyout', 'Blockly.Mutator', 'Blockly.ShortcutItems', 'Blockly.Themes.Classic', 'Blockly.Toolbox', 'Blockly.Trashcan', 'Blockly.VariablesDynamic', 'Blockly.VerticalFlyout', 'Blockly.Warning', 'Blockly.ZoomControls', 'Blockly.geras.Renderer', 'Blockly.thrasos.Renderer', 'Blockly.zelos.Renderer']);
|
||||
goog.addDependency('../../core/scrollbar.js', ['Blockly.Scrollbar', 'Blockly.ScrollbarPair'], ['Blockly.Events', 'Blockly.Touch', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Metrics', 'Blockly.utils.Svg', 'Blockly.utils.dom']);
|
||||
goog.addDependency('../../core/shortcut_items.js', ['Blockly.ShortcutItems'], ['Blockly.Gesture', 'Blockly.ShortcutRegistry', 'Blockly.utils.KeyCodes']);
|
||||
goog.addDependency('../../core/shortcut_items.js', ['Blockly.ShortcutItems'], ['Blockly.Gesture', 'Blockly.ShortcutRegistry', 'Blockly.clipboard', 'Blockly.utils.KeyCodes']);
|
||||
goog.addDependency('../../core/shortcut_registry.js', ['Blockly.ShortcutRegistry'], ['Blockly.utils.KeyCodes', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/theme.js', ['Blockly.Theme'], ['Blockly.registry', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'});
|
||||
goog.addDependency('../../core/theme/classic.js', ['Blockly.Themes.Classic'], ['Blockly.Theme']);
|
||||
|
||||
@@ -17,11 +17,11 @@ suite('Context Menu Items', function() {
|
||||
Blockly.ContextMenuItems.registerDefaultOptions();
|
||||
this.registry = Blockly.ContextMenuRegistry.registry;
|
||||
});
|
||||
|
||||
|
||||
teardown(function() {
|
||||
sharedTestTeardown.call(this);
|
||||
});
|
||||
|
||||
|
||||
suite('Workspace Items', function() {
|
||||
setup(function() {
|
||||
this.scope = {workspace: this.workspace};
|
||||
@@ -328,12 +328,12 @@ suite('Context Menu Items', function() {
|
||||
});
|
||||
|
||||
test('Calls duplicate', function() {
|
||||
var stub = sinon.stub(Blockly, 'duplicate');
|
||||
var spy = sinon.spy(Blockly.clipboard, 'duplicate');
|
||||
|
||||
this.duplicateOption.callback(this.scope);
|
||||
|
||||
sinon.assert.calledOnce(stub);
|
||||
sinon.assert.calledWith(stub, this.block);
|
||||
sinon.assert.calledOnce(spy);
|
||||
sinon.assert.calledWith(spy, this.block);
|
||||
});
|
||||
|
||||
test('Has correct label', function() {
|
||||
|
||||
@@ -93,7 +93,7 @@ suite('Key Down', function() {
|
||||
suite('Copy', function() {
|
||||
setup(function() {
|
||||
setSelectedBlock(this.workspace);
|
||||
this.copySpy = sinon.spy(Blockly, 'copy');
|
||||
this.copySpy = sinon.spy(Blockly.clipboard, 'copy');
|
||||
this.hideChaffSpy = sinon.spy(Blockly, 'hideChaff');
|
||||
});
|
||||
var testCases = [
|
||||
|
||||
Reference in New Issue
Block a user