Files
blockly/tests/mocha/generator_test.js
Christopher Allen 130989763c refactor(generators): Restructure generator modules to contain side effects (#7173)
* refactor(generators): Move lang.js -> lang/lang_gernator.js

  Move the LangGenerator definitions into their respective
  subdirectories and add a _generator suffix to their filenames,
  i.e. generators/javascript.js  becomes
  generators/javascript/javascript_generator.js.

  This is to keep related code together and allow the `lang/all.js`
  entrypoints to be moved to the top level generators/ directory.

  No goog module IDs were changed, so playground and test code
  that accesses this modules by filename does not need to be modified.

* refactor(generators) Move lang/all.js -> lang.js

  - Move the entrypoints in generators/*/all.js to correspondingly-named
    files in generators/ instead—i.e., generators/javascript/all.js
    becomes generators/javascript.js.

  - Update build_tasks.js accordingly.

* fix(generators): Add missing exports for LuaGenerator, PhpGenerator

  These were inadvertently omitted from #7161 and #7162, respectively.

* refactor(generators): Make block generator modules side-effect free

  - Move declaration of <lang>Generator instance from
    generators/<lang>/<lang>_generator.js to generators/<lang>.js.
  - Move .addReservedWords() calls from generators/<lang>/*.js to
    generators/<lang>.js
  - Modify generators/<lang>/*.js to export block generator functions
    individually, rather than installing on <lang>Generator instance.
  - Modify generators/<lang>.js to import and install block generator
    functions on <lang>Generator instance.

* fix(tests): Fix tests broken by restructuring of generators

  Where these tests needed block generator functions preinstalled
  they should have been importing the Blockly.<Lang>.all module.

  Where they do not need the provided block generator functions
  they can now create their own empty <Lang>Generator instances.

* chore: Update renamings file

  - Fix a malformation in previous entries that was not detected by
    the renaming file validator test.
  - Add entries describing the work done in this and related recent
    PRs.

* fix: Correct minor errors in PR #7173

  - Fix a search-and-replace error in renamings.json5
  - Fix an incorrect-but-usable import in generator_test.js
2023-06-20 23:22:44 +01:00

197 lines
5.5 KiB
JavaScript

/**
* @license
* Copyright 2020 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
goog.declareModuleId('Blockly.test.generator');
import * as Blockly from '../../build/src/core/blockly.js';
const {DartGenerator} = goog.require('Blockly.Dart');
const {JavascriptGenerator} = goog.require('Blockly.JavaScript');
const {LuaGenerator} = goog.require('Blockly.Lua');
const {PhpGenerator} = goog.require('Blockly.PHP');
const {PythonGenerator} = goog.require('Blockly.Python');
import {
sharedTestSetup,
sharedTestTeardown,
} from './test_helpers/setup_teardown.js';
suite('Generator', function () {
setup(function () {
sharedTestSetup.call(this);
this.workspace = new Blockly.Workspace();
});
teardown(function () {
sharedTestTeardown.call(this);
});
suite('prefix', function () {
setup(function () {
this.generator = new Blockly.CodeGenerator('INTERCAL');
});
test('Nothing', function () {
chai.assert.equal(this.generator.prefixLines('', ''), '');
});
test('One word', function () {
chai.assert.equal(this.generator.prefixLines('Hello', '@'), '@Hello');
});
test('One line', function () {
chai.assert.equal(
this.generator.prefixLines('Hello\n', '12'),
'12Hello\n'
);
});
test('Two lines', function () {
chai.assert.equal(
this.generator.prefixLines('Hello\nWorld\n', '***'),
'***Hello\n***World\n'
);
});
});
suite('blockToCode', function () {
setup(function () {
Blockly.defineBlocksWithJsonArray([
{
'type': 'stack_block',
'message0': '',
'previousStatement': null,
'nextStatement': null,
},
{
'type': 'row_block',
'message0': '%1',
'args0': [
{
'type': 'input_value',
'name': 'INPUT',
},
],
'output': null,
'nextStatement': null,
},
]);
const rowBlock = this.workspace.newBlock('row_block');
const stackBlock = this.workspace.newBlock('stack_block');
this.blockToCodeTest = function (
generator,
blockDisabled,
opt_thisOnly,
expectedCode,
opt_message
) {
generator.forBlock['row_block'] = function (_) {
return 'row_block';
};
generator.forBlock['stack_block'] = function (_) {
return 'stack_block';
};
rowBlock.nextConnection.connect(stackBlock.previousConnection);
rowBlock.disabled = blockDisabled;
const code = generator.blockToCode(rowBlock, opt_thisOnly);
delete generator.forBlock['stack_block'];
delete generator.forBlock['row_block'];
chai.assert.equal(code, expectedCode, opt_message);
};
});
const testCase = [
[new DartGenerator(), 'Dart'],
[new JavascriptGenerator(), 'JavaScript'],
[new LuaGenerator(), 'Lua'],
[new PhpGenerator(), 'PHP'],
[new PythonGenerator(), 'Python'],
];
suite('Trivial', function () {
testCase.forEach(function (testCase) {
const generator = testCase[0];
const name = testCase[1];
test(name, function () {
generator.init(this.workspace);
this.blockToCodeTest(generator, false, true, 'row_block');
this.blockToCodeTest(
generator,
false,
false,
'row_blockstack_block',
'thisOnly=false'
);
});
});
});
suite('Disabled block', function () {
testCase.forEach(function (testCase) {
const generator = testCase[0];
const name = testCase[1];
test(name, function () {
this.blockToCodeTest(generator, true, true, '');
this.blockToCodeTest(
generator,
true,
false,
'stack_block',
'thisOnly=false'
);
});
});
});
suite('Nested block', function () {
setup(function () {
Blockly.defineBlocksWithJsonArray([
{
'type': 'test_loop_block',
'message0': 'Repeat Loop',
'message1': '%1',
'args1': [
{
'type': 'input_statement',
'name': 'DO',
},
],
'previousStatement': null,
'nextStatement': null,
},
]);
const blockA = this.workspace.newBlock('test_loop_block');
const blockB = this.workspace.newBlock('test_loop_block');
const blockC = this.workspace.newBlock('test_loop_block');
this.loopTest = function (
generator,
opt_thisOnly,
expectedCode,
opt_message
) {
generator.forBlock['test_loop_block'] = function (block) {
return '{' + generator.statementToCode(block, 'DO') + '}';
};
blockA.getInput('DO').connection.connect(blockB.previousConnection);
blockA.nextConnection.connect(blockC.previousConnection);
const code = generator.blockToCode(blockA, opt_thisOnly);
chai.assert.equal(code, expectedCode, opt_message);
};
});
testCase.forEach(function (testCase) {
const generator = testCase[0];
const name = testCase[1];
test(name, function () {
this.loopTest(generator, true, '{ {}}');
this.loopTest(generator, false, '{ {}}{}', 'thisOnly=false');
});
});
});
});
});