Skip to content

Commit ee2ef2f

Browse files
authored
Merge pull request #223 from /issues/221
Issues/221
2 parents f450774 + 45b96ee commit ee2ef2f

File tree

17 files changed

+217
-283
lines changed

17 files changed

+217
-283
lines changed

src/containers/blocks.jsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import makeToolboxXML from '../lib/make-toolbox-xml';
55
import PropTypes from 'prop-types';
66
import React from 'react';
77
import VMScratchBlocks from '../lib/blocks';
8-
import defineRubyBlocks from '../lib/define-ruby-blocks';
98
import VM from 'scratch-vm';
109

1110
import log from '../lib/log.js';
@@ -48,7 +47,7 @@ const DroppableBlocks = DropAreaHOC([
4847
class Blocks extends React.Component {
4948
constructor (props) {
5049
super(props);
51-
this.ScratchBlocks = defineRubyBlocks(VMScratchBlocks(props.vm));
50+
this.ScratchBlocks = VMScratchBlocks(props.vm);
5251
bindAll(this, [
5352
'attachVM',
5453
'detachVM',

src/lib/make-toolbox-xml.js

Lines changed: 1 addition & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -710,72 +710,6 @@ const myBlocks = function () {
710710
`;
711711
};
712712

713-
ScratchBlocks.Msg.CATEGORY_RUBY = 'Ruby';
714-
ScratchBlocks.ScratchMsgs.locales.en.CATEGORY_RUBY = 'Ruby';
715-
ScratchBlocks.ScratchMsgs.locales.ja.CATEGORY_RUBY = 'ルビー';
716-
ScratchBlocks.ScratchMsgs.locales['ja-Hira'].CATEGORY_RUBY = 'ルビー';
717-
718-
const ruby = function () {
719-
return `
720-
<category
721-
name="%{BKY_CATEGORY_RUBY}"
722-
id="ruby"
723-
colour="#CC0043"
724-
secondaryColour="#FF4D6A">
725-
<block type="ruby_statement">
726-
<value name="STATEMENT">
727-
<shadow type="text">
728-
<field name="TEXT"></field>
729-
</shadow>
730-
</value>
731-
</block>
732-
<block type="ruby_statement_with_block">
733-
<value name="STATEMENT">
734-
<shadow type="text">
735-
<field name="TEXT"></field>
736-
</shadow>
737-
</value>
738-
<value name="ARGS">
739-
<shadow type="text">
740-
<field name="TEXT"></field>
741-
</shadow>
742-
</value>
743-
</block>
744-
<block type="ruby_expression">
745-
<value name="EXPRESSION">
746-
<shadow type="text">
747-
<field name="TEXT"></field>
748-
</shadow>
749-
</value>
750-
</block>
751-
<block type="ruby_range">
752-
<value name="FROM">
753-
<shadow type="math_number">
754-
<field name="NUM">1</field>
755-
</shadow>
756-
</value>
757-
<value name="TO">
758-
<shadow type="math_number">
759-
<field name="NUM">10</field>
760-
</shadow>
761-
</value>
762-
</block>
763-
<block type="ruby_exclude_range">
764-
<value name="FROM">
765-
<shadow type="math_number">
766-
<field name="NUM">1</field>
767-
</shadow>
768-
</value>
769-
<value name="TO">
770-
<shadow type="math_number">
771-
<field name="NUM">10</field>
772-
</shadow>
773-
</value>
774-
</block>
775-
</category>
776-
`;
777-
};
778-
779713
const xmlOpen = '<xml style="display: none">';
780714
const xmlClose = '</xml>';
781715

@@ -818,7 +752,6 @@ const makeToolboxXML = function (isStage, targetId, categoriesXML = [],
818752
const operatorsXML = moveCategory('operators') || operators(isStage, targetId);
819753
const variablesXML = moveCategory('data') || variables(isStage, targetId);
820754
const myBlocksXML = moveCategory('procedures') || myBlocks(isStage, targetId);
821-
const rubyXML = moveCategory('ruby') || ruby(isStage, targetId);
822755

823756
const everything = [
824757
xmlOpen,
@@ -830,8 +763,7 @@ const makeToolboxXML = function (isStage, targetId, categoriesXML = [],
830763
sensingXML, gap,
831764
operatorsXML, gap,
832765
variablesXML, gap,
833-
myBlocksXML, gap,
834-
rubyXML
766+
myBlocksXML
835767
];
836768

837769
for (const extensionCategory of categoriesXML) {

src/lib/ruby-to-blocks-converter/index.js

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,15 @@ class RubyToBlocksConverter {
119119
throw new Error(`invalid block: ${block}`);
120120
}
121121
});
122+
Object.keys(this._context.blocks).forEach(blockId => {
123+
const block = this._context.blocks[blockId];
124+
if (this._isRubyBlock(block)) {
125+
throw new RubyToBlocksConverterError(
126+
block.node,
127+
`could not convert ${block.opcode}: ${this._getSource(block.node)}`
128+
);
129+
}
130+
});
122131
return true;
123132
} catch (e) {
124133
let error;
@@ -399,6 +408,10 @@ class RubyToBlocksConverter {
399408
return this._isBlock(block) && block.opcode === 'ruby_statement';
400409
}
401410

411+
_isRubyBlock (block) {
412+
return this._isBlock(block) && block.opcode.match(/^ruby_/);
413+
}
414+
402415
_getRubyStatement (block) {
403416
if (this._isRubyStatement(block)) {
404417
const textBlock = this._context.blocks[block.inputs.STATEMENT.block];
@@ -455,14 +468,16 @@ class RubyToBlocksConverter {
455468
return value;
456469
}
457470

458-
_createRubyExpressionBlock (expression) {
471+
_createRubyExpressionBlock (expression, node) {
459472
const block = this._createBlock('ruby_expression', 'value_boolean');
473+
block.node = node;
460474
this._addInput(block, 'EXPRESSION', this._createTextBlock(expression));
461475
return block;
462476
}
463477

464-
_createRubyStatementBlock (statement) {
478+
_createRubyStatementBlock (statement, node) {
465479
const block = this._createBlock('ruby_statement', 'statement');
480+
block.node = node;
466481
this._addInput(block, 'STATEMENT', this._createTextBlock(statement));
467482
return block;
468483
}
@@ -875,13 +890,13 @@ class RubyToBlocksConverter {
875890
rubyBlock = this._processStatement(rubyBlockNode);
876891
}
877892

878-
let block = this._callConvertersHandler('onSend', receiver, name, args, rubyBlockArgs, rubyBlock);
893+
let block = this._callConvertersHandler('onSend', receiver, name, args, rubyBlockArgs, rubyBlock, node);
879894
if (!block) {
880895
if ((this._isSelf(receiver) || receiver === Opal.nil) && !rubyBlock) {
881896
switch (name) {
882897
case 'wait':
883898
if (args.length === 0) {
884-
block = this._createRubyStatementBlock('wait');
899+
block = this._createRubyStatementBlock('wait', node);
885900
}
886901
break;
887902
}
@@ -893,11 +908,12 @@ class RubyToBlocksConverter {
893908

894909
if (rubyBlockNode) {
895910
block = this._createBlock('ruby_statement_with_block', 'statement');
911+
block.node = node;
896912
this._addTextInput(block, 'STATEMENT', this._getSource(node));
897913
this._addTextInput(block, 'ARGS', this._getSource(rubyBlockArgsNode));
898914
this._addSubstack(block, this._processStatement(rubyBlockNode));
899915
} else {
900-
block = this._createRubyStatementBlock(this._getSource(node));
916+
block = this._createRubyStatementBlock(this._getSource(node), node);
901917
}
902918
}
903919
return block;
@@ -958,6 +974,7 @@ class RubyToBlocksConverter {
958974

959975
const args = node.children.map(childNode => this._process(childNode));
960976
const block = this._createBlock('ruby_range', 'value_boolean');
977+
block.node = node;
961978
this._addNumberInput(block, 'FROM', 'math_number', args[0], 1);
962979
this._addNumberInput(block, 'TO', 'math_number', args[1], 10);
963980
return block;
@@ -968,6 +985,7 @@ class RubyToBlocksConverter {
968985

969986
const args = node.children.map(childNode => this._process(childNode));
970987
const block = this._createBlock('ruby_exclude_range', 'value_boolean');
988+
block.node = node;
971989
this._addNumberInput(block, 'FROM', 'math_number', args[0], 1);
972990
this._addNumberInput(block, 'TO', 'math_number', args[1], 10);
973991
return block;
@@ -1001,15 +1019,16 @@ class RubyToBlocksConverter {
10011019
const cond = this._processCondition(node.children[0]);
10021020
const statement = this._processStatement(node.children[1]);
10031021
let elseStatement;
1004-
if (node.children[2] !== Opal.nil || node.$loc().$else() !== Opal.nil) {
1022+
if (node.children[2] !== Opal.nil ||
1023+
(node.$loc().$else && node.$loc().$else() !== Opal.nil)) {
10051024
elseStatement = this._processStatement(node.children[2]);
10061025
}
10071026

10081027
let block = this._callConvertersHandler('onIf', cond, statement, elseStatement);
10091028
if (!block) {
10101029
this._restoreContext(saved);
10111030

1012-
block = this._createRubyStatementBlock(this._getSource(node));
1031+
block = this._createRubyStatementBlock(this._getSource(node), node);
10131032
}
10141033
return block;
10151034
}
@@ -1026,7 +1045,7 @@ class RubyToBlocksConverter {
10261045
if (!block) {
10271046
this._restoreContext(saved);
10281047

1029-
block = this._createRubyStatementBlock(this._getSource(node));
1048+
block = this._createRubyStatementBlock(this._getSource(node), node);
10301049
}
10311050
return block;
10321051
}
@@ -1044,7 +1063,7 @@ class RubyToBlocksConverter {
10441063
if (!block) {
10451064
this._restoreContext(saved);
10461065

1047-
block = this._createRubyStatementBlock(this._getSource(node));
1066+
block = this._createRubyStatementBlock(this._getSource(node), node);
10481067
}
10491068

10501069
return block;
@@ -1114,7 +1133,7 @@ class RubyToBlocksConverter {
11141133
if (!block) {
11151134
this._restoreContext(saved);
11161135

1117-
block = this._createRubyStatementBlock(this._getSource(node));
1136+
block = this._createRubyStatementBlock(this._getSource(node), node);
11181137
}
11191138

11201139
return block;
@@ -1141,7 +1160,7 @@ class RubyToBlocksConverter {
11411160
if (!block) {
11421161
this._restoreContext(saved);
11431162

1144-
block = this._createRubyStatementBlock(this._getSource(node));
1163+
block = this._createRubyStatementBlock(this._getSource(node), node);
11451164
}
11461165

11471166
return block;

src/lib/ruby-to-blocks-converter/microbit.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ const MicroBit = 'microbit';
88
*/
99
const MicroBitConverter = {
1010
// eslint-disable-next-line no-unused-vars
11-
onSend: function (receiver, name, args, rubyBlockArgs, rubyBlock) {
11+
onSend: function (receiver, name, args, rubyBlockArgs, rubyBlock, node) {
1212
let block;
1313
if ((this._isSelf(receiver) || receiver === Opal.nil) &&
1414
name === 'when' &&
@@ -61,7 +61,7 @@ const MicroBitConverter = {
6161
switch (name) {
6262
case 'microbit':
6363
if (args.length === 0) {
64-
block = this._createRubyExpressionBlock(MicroBit);
64+
block = this._createRubyExpressionBlock(MicroBit, node);
6565
}
6666
break;
6767
}

src/lib/ruby-to-blocks-converter/sensing.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ const Stage = 'stage';
2929
*/
3030
const SensingConverter = {
3131
// eslint-disable-next-line no-unused-vars
32-
onSend: function (receiver, name, args, rubyBlockArgs, rubyBlock) {
32+
onSend: function (receiver, name, args, rubyBlockArgs, rubyBlock, node) {
3333
let block;
3434
if ((this._isSelf(receiver) || receiver === Opal.nil) && !rubyBlock) {
3535
switch (name) {
@@ -109,12 +109,12 @@ const SensingConverter = {
109109
break;
110110
case 'sprite':
111111
if (args.length === 1 && this._isString(args[0])) {
112-
block = this._createRubyExpressionBlock(spriteCall(args[0]));
112+
block = this._createRubyExpressionBlock(spriteCall(args[0]), node);
113113
}
114114
break;
115115
case 'stage':
116116
if (args.length === 0) {
117-
block = this._createRubyExpressionBlock(Stage);
117+
block = this._createRubyExpressionBlock(Stage, node);
118118
}
119119
break;
120120
}
@@ -168,7 +168,7 @@ const SensingConverter = {
168168
break;
169169
case '::Time':
170170
if (name === 'now' && args.length === 0) {
171-
block = this._createRubyExpressionBlock(TimeNow);
171+
block = this._createRubyExpressionBlock(TimeNow, node);
172172
}
173173
break;
174174
}

test/helpers/expect-to-equal-blocks.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,12 @@ const convertAndExpectToEqualBlocks = function (converter, target, code, expecte
231231
expect(res).toBeTruthy();
232232
};
233233

234+
const convertAndExpectRubyBlockError = function (converter, target, code) {
235+
converter.targetCodeToBlocks(target, code);
236+
expect(converter.errors).toHaveLength(1);
237+
expect(converter.errors[0].text).toMatch(/ could not convert ruby_/);
238+
};
239+
234240
const expectToEqualRubyStatement = function (converter, expectedStatement) {
235241
const expected = [
236242
{
@@ -495,7 +501,7 @@ const expectNoArgsMethod = function (opcode, methodName, blockType = 'statement'
495501
`${methodName}("backdrop2")`,
496502
`${methodName}(x)`
497503
].forEach(c => {
498-
convertAndExpectToEqualRubyStatement(converter, target, c, c);
504+
convertAndExpectRubyBlockError(converter, target, c);
499505
});
500506
});
501507
});
@@ -505,6 +511,7 @@ export {
505511
toJson,
506512
expectToEqualBlocks,
507513
convertAndExpectToEqualBlocks,
514+
convertAndExpectRubyBlockError,
508515
expectToEqualRubyStatement,
509516
convertAndExpectToEqualRubyStatement,
510517
rubyToExpected,

test/helpers/selenium-helper.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class SeleniumHelper {
2323
'elementIsVisible',
2424
'findByText',
2525
'findByXpath',
26+
'notExistsByXpath',
2627
'getDriver',
2728
'getSauceDriver',
2829
'getLogs',
@@ -103,6 +104,11 @@ class SeleniumHelper {
103104
return this.findByXpath(`//body//${scope || '*'}//*[contains(text(), '${text}')]`);
104105
}
105106

107+
notExistsByXpath (xpath) {
108+
return this.driver.findElements(By.xpath(xpath))
109+
.then(elements => elements.length === 0 || elements.every(i => !i.isDisplayed()));
110+
}
111+
106112
loadUri (uri) {
107113
const WINDOW_WIDTH = 1024;
108114
const WINDOW_HEIGHT = 768;

0 commit comments

Comments
 (0)