From d419af44c501025dfdd0f784916cb9586a1957dc Mon Sep 17 00:00:00 2001 From: Andrey Shaveko Date: Fri, 23 Dec 2022 14:03:45 +0300 Subject: [PATCH 01/15] chore: update credits --- .../renderers/interactions/TextEntryInteraction.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/qtiCommonRenderer/renderers/interactions/TextEntryInteraction.js b/src/qtiCommonRenderer/renderers/interactions/TextEntryInteraction.js index eec0851f..9f1da30c 100644 --- a/src/qtiCommonRenderer/renderers/interactions/TextEntryInteraction.js +++ b/src/qtiCommonRenderer/renderers/interactions/TextEntryInteraction.js @@ -13,14 +13,16 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * Copyright (c) 2014 (original work) Open Assessment Technologies SA (under the project TAO-PRODUCT); + * Copyright (c) 2014-2022 Open Assessment Technologies SA (under the project TAO-PRODUCT); * */ /** * @author Sam Sipasseuth * @author Bertrand Chevrier + * @author Andrey Shaveko */ + import $ from 'jquery'; import _ from 'lodash'; import __ from 'i18n'; From b7544839aec044138fb348f1a0cf439bd074900e Mon Sep 17 00:00:00 2001 From: Andrey Shaveko Date: Fri, 23 Dec 2022 14:09:21 +0300 Subject: [PATCH 02/15] fix: es6 refactor and eslint suggested fixes --- .../interactions/TextEntryInteraction.js | 84 +++++++++---------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/src/qtiCommonRenderer/renderers/interactions/TextEntryInteraction.js b/src/qtiCommonRenderer/renderers/interactions/TextEntryInteraction.js index 9f1da30c..2bf4e933 100644 --- a/src/qtiCommonRenderer/renderers/interactions/TextEntryInteraction.js +++ b/src/qtiCommonRenderer/renderers/interactions/TextEntryInteraction.js @@ -38,11 +38,11 @@ import tooltip from 'ui/tooltip'; * Hide the tooltip for the text input * @param {jQuery} $input */ -var hideTooltip = function hideTooltip($input) { +function hideTooltip($input) { if ($input.data('$tooltip')) { $input.data('$tooltip').hide(); } -}; +} /** * Create/Show tooltip for the text input @@ -50,11 +50,11 @@ var hideTooltip = function hideTooltip($input) { * @param {String} theme * @param {String} message */ -var showTooltip = function showTooltip($input, theme, message) { +function showTooltip($input, theme, message) { if ($input.data('$tooltip')) { $input.data('$tooltip').updateTitleContent(message); } else { - var textEntryTooltip = tooltip.create($input, message, { + const textEntryTooltip = tooltip.create($input, message, { theme: theme, trigger: 'manual' }); @@ -63,7 +63,7 @@ var showTooltip = function showTooltip($input, theme, message) { } $input.data('$tooltip').show(); -}; +} /** * Init rendering, called after template injected into the DOM @@ -72,15 +72,13 @@ var showTooltip = function showTooltip($input, theme, message) { * * @param {object} interaction */ -var render = function render(interaction) { - var attributes = interaction.getAttributes(), - baseType = interaction.getResponseDeclaration().attr('baseType'), - $input = interaction.getContainer(), - expectedLength, - updateMaxCharsTooltip, - updatePatternMaskTooltip, - patternMask = interaction.attr('patternMask'), - maxChars = parseInt(patternMaskHelper.parsePattern(patternMask, 'chars'), 10); +function render(interaction) { + const attributes = interaction.getAttributes(); + const baseType = interaction.getResponseDeclaration().attr('baseType'); + const $input = interaction.getContainer(); + const patternMask = interaction.attr('patternMask'); + const maxChars = parseInt(patternMaskHelper.parsePattern(patternMask, 'chars'), 10); + let expectedLength; // Setting up baseType switch (baseType) { @@ -108,9 +106,10 @@ var render = function render(interaction) { } if (maxChars) { - updateMaxCharsTooltip = function updateMaxCharsTooltip() { - var count = $input.val().length; - var message, messageType; + const updateMaxCharsTooltip = () => { + const count = $input.val().length; + let message; + let messageType; if (count) { message = __('%d/%d', count, maxChars); @@ -145,8 +144,8 @@ var render = function render(interaction) { hideTooltip($input); }); } else if (attributes.patternMask) { - updatePatternMaskTooltip = function updatePatternMaskTooltip() { - var regex = new RegExp(attributes.patternMask); + const updatePatternMaskTooltip = () => { + const regex = new RegExp(attributes.patternMask); hideTooltip($input); @@ -176,11 +175,11 @@ var render = function render(interaction) { containerHelper.triggerResponseChangeEvent(interaction); }); } -}; +} -var resetResponse = function resetResponse(interaction) { +function resetResponse(interaction) { interaction.getContainer().val(''); -}; +} /** * Set the response to the rendered interaction. @@ -196,8 +195,8 @@ var resetResponse = function resetResponse(interaction) { * @param {object} interaction * @param {object} response */ -var setResponse = function setResponse(interaction, response) { - var responseValue; +function setResponse(interaction, response) { + let responseValue; try { responseValue = pciResponse.unserialize(response, interaction); @@ -206,7 +205,7 @@ var setResponse = function setResponse(interaction, response) { if (responseValue && responseValue.length) { interaction.getContainer().val(responseValue[0]); } -}; +} /** * Return the response of the rendered interaction @@ -220,13 +219,14 @@ var setResponse = function setResponse(interaction, response) { * @param {object} interaction * @returns {object} */ -var getResponse = function getResponse(interaction) { - var ret = { base: {} }, - value, - $input = interaction.getContainer(), - attributes = interaction.getAttributes(), - baseType = interaction.getResponseDeclaration().attr('baseType'), - numericBase = attributes.base || 10; +function getResponse(interaction) { + const ret = { base: {} }; + const $input = interaction.getContainer(); + const attributes = interaction.getAttributes(); + const baseType = interaction.getResponseDeclaration().attr('baseType'); + const numericBase = attributes.base || 10; + + let value; if ($input.hasClass('invalid') || (attributes.placeholderText && $input.val() === attributes.placeholderText)) { //invalid response or response equals to the placeholder text are considered empty @@ -244,11 +244,11 @@ var getResponse = function getResponse(interaction) { ret.base[baseType] = isNaN(value) && typeof value === 'number' ? '' : value; return ret; -}; +} -var destroy = function destroy(interaction) { +function destroy(interaction) { $('input.qti-textEntryInteraction').each(function(index, el) { - var $input = $(el); + const $input = $(el); if ($input.data('$tooltip')) { $input.data('$tooltip').dispose(); $input.removeData('$tooltip'); @@ -264,7 +264,7 @@ var destroy = function destroy(interaction) { //remove all references to a cache container containerHelper.reset(interaction); -}; +} /** * Set the interaction state. It could be done anytime with any state. @@ -272,14 +272,14 @@ var destroy = function destroy(interaction) { * @param {Object} interaction - the interaction instance * @param {Object} state - the interaction state */ -var setState = function setState(interaction, state) { +function setState(interaction, state) { if (_.isObject(state)) { if (state.response) { interaction.resetResponse(); interaction.setResponse(state.response); } } -}; +} /** * Get the interaction state. @@ -287,15 +287,15 @@ var setState = function setState(interaction, state) { * @param {Object} interaction - the interaction instance * @returns {Object} the interaction current state */ -var getState = function getState(interaction) { - var state = {}; - var response = interaction.getResponse(); +function getState(interaction) { + const state = {}; + const response = interaction.getResponse(); if (response) { state.response = response; } return state; -}; +} export default { qtiClass: 'textEntryInteraction', From 64a76effe454d5009111c0363b5b3b8216560850 Mon Sep 17 00:00:00 2001 From: Andrey Shaveko Date: Fri, 23 Dec 2022 14:11:10 +0300 Subject: [PATCH 03/15] fix: add error habdling for catch block --- .../renderers/interactions/TextEntryInteraction.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/qtiCommonRenderer/renderers/interactions/TextEntryInteraction.js b/src/qtiCommonRenderer/renderers/interactions/TextEntryInteraction.js index 2bf4e933..0d2702e4 100644 --- a/src/qtiCommonRenderer/renderers/interactions/TextEntryInteraction.js +++ b/src/qtiCommonRenderer/renderers/interactions/TextEntryInteraction.js @@ -33,6 +33,12 @@ import pciResponse from 'taoQtiItem/qtiCommonRenderer/helpers/PciResponse'; import patternMaskHelper from 'taoQtiItem/qtiCommonRenderer/helpers/patternMask'; import locale from 'util/locale'; import tooltip from 'ui/tooltip'; +import loggerFactory from 'core/logger'; + +/** + * Create a logger + */ + const logger = loggerFactory('taoQtiItem/qtiCommonRenderer/renderers/interactions/TextEntryInteraction.js'); /** * Hide the tooltip for the text input @@ -200,7 +206,9 @@ function setResponse(interaction, response) { try { responseValue = pciResponse.unserialize(response, interaction); - } catch (e) {} + } catch (e) { + logger.warn(`setResponse error ${e}`); + } if (responseValue && responseValue.length) { interaction.getContainer().val(responseValue[0]); From 431a3030a360e626fd73c7703f142019d0d12c1f Mon Sep 17 00:00:00 2001 From: Andrey Shaveko Date: Fri, 23 Dec 2022 14:33:21 +0300 Subject: [PATCH 04/15] fix: apply conversion on getResponse --- .../renderers/interactions/TextEntryInteraction.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/qtiCommonRenderer/renderers/interactions/TextEntryInteraction.js b/src/qtiCommonRenderer/renderers/interactions/TextEntryInteraction.js index 0d2702e4..00439ea1 100644 --- a/src/qtiCommonRenderer/renderers/interactions/TextEntryInteraction.js +++ b/src/qtiCommonRenderer/renderers/interactions/TextEntryInteraction.js @@ -34,11 +34,12 @@ import patternMaskHelper from 'taoQtiItem/qtiCommonRenderer/helpers/patternMask' import locale from 'util/locale'; import tooltip from 'ui/tooltip'; import loggerFactory from 'core/logger'; +import converter from 'util/converter'; /** * Create a logger */ - const logger = loggerFactory('taoQtiItem/qtiCommonRenderer/renderers/interactions/TextEntryInteraction.js'); +const logger = loggerFactory('taoQtiItem/qtiCommonRenderer/renderers/interactions/TextEntryInteraction.js'); /** * Hide the tooltip for the text input @@ -234,18 +235,20 @@ function getResponse(interaction) { const baseType = interaction.getResponseDeclaration().attr('baseType'); const numericBase = attributes.base || 10; + const inputValue = $input.val(); let value; - if ($input.hasClass('invalid') || (attributes.placeholderText && $input.val() === attributes.placeholderText)) { + if ($input.hasClass('invalid') || (attributes.placeholderText && inputValue === attributes.placeholderText)) { //invalid response or response equals to the placeholder text are considered empty value = ''; } else { + const convertedValue = converter.convert(inputValue.trim()); if (baseType === 'integer') { - value = locale.parseInt($input.val(), numericBase); + value = locale.parseInt(convertedValue, numericBase); } else if (baseType === 'float') { - value = locale.parseFloat($input.val()); + value = locale.parseFloat(convertedValue); } else if (baseType === 'string') { - value = $input.val(); + value = convertedValue; } } From 9376962d17e8230ac2d6150ddd67ec8a18035106 Mon Sep 17 00:00:00 2001 From: Andrey Shaveko Date: Fri, 23 Dec 2022 14:34:20 +0300 Subject: [PATCH 05/15] feat: add unit test for conversion --- .../interactions/textEntry/test.js | 75 ++++++++++++------- 1 file changed, 50 insertions(+), 25 deletions(-) diff --git a/test/qtiCommonRenderer/interactions/textEntry/test.js b/test/qtiCommonRenderer/interactions/textEntry/test.js index 152b3530..9faf69a8 100644 --- a/test/qtiCommonRenderer/interactions/textEntry/test.js +++ b/test/qtiCommonRenderer/interactions/textEntry/test.js @@ -23,12 +23,10 @@ define([ ) { 'use strict'; - var runner; - var fixtureContainerId = 'item-container'; - var outsideContainerId = 'outside-container'; + let runner; QUnit.module('Text Entry Interaction', { - afterEach: function(assert) { + afterEach: function() { if (runner) { runner.clear(); } @@ -36,7 +34,7 @@ define([ }); function getTooltipContent($input) { - var content = getTooltip($input); + const content = getTooltip($input); if (content) { return content.find('.tooltip-body').html(); } @@ -47,7 +45,7 @@ define([ } function getTooltip($input) { - var instance = getTooltipText($input); + const instance = getTooltipText($input); if (instance && instance.popperInstance.popper) { return $(instance.popperInstance.popper); } @@ -68,15 +66,15 @@ define([ } QUnit.test('Lenght constraint', function(assert) { - var ready = assert.async(); + const ready = assert.async(); - var $container = $('#fixture-length-constraint'); + const $container = $('#fixture-length-constraint'); assert.equal($container.length, 1, 'the item container exists'); assert.equal($container.children().length, 0, 'the container has no children'); runner = qtiItemRunner('qti', textEntryLengthConstrainedData) .on('render', function() { - var $input = $container.find('.qti-interaction.qti-textEntryInteraction'); + const $input = $container.find('.qti-interaction.qti-textEntryInteraction'); assert.equal( $input.length, @@ -116,16 +114,16 @@ define([ }); QUnit.test('Pattern constraint - incorrect', function(assert) { - var ready = assert.async(2); + const ready = assert.async(2); - var $container = $('#pattern-constraint-incorrect'); + const $container = $('#pattern-constraint-incorrect'); assert.equal($container.length, 1, 'the item container exists'); assert.equal($container.children().length, 0, 'the container has no children'); runner = qtiItemRunner('qti', textEntryPatternConstrainedData) .on('render', function() { - var $input = $container.find('.qti-interaction.qti-textEntryInteraction'); + const $input = $container.find('.qti-interaction.qti-textEntryInteraction'); assert.equal( $input.length, @@ -137,8 +135,8 @@ define([ $input.keyup(); ready(); }) - .on('responsechange', function(state) { - var $input = $container.find('.qti-interaction.qti-textEntryInteraction'); + .on('responsechange', function() { + const $input = $container.find('.qti-interaction.qti-textEntryInteraction'); assert.equal( getTooltipContent($input), __('This is not a valid answer'), @@ -152,16 +150,16 @@ define([ }); QUnit.test('Pattern constraint - correct', function(assert) { - var ready = assert.async(2); + const ready = assert.async(2); - var $container = $('#pattern-constraint-correct'); + const $container = $('#pattern-constraint-correct'); assert.equal($container.length, 1, 'the item container exists'); assert.equal($container.children().length, 0, 'the container has no children'); runner = qtiItemRunner('qti', textEntryPatternConstrainedData) .on('render', function() { - var $input = $container.find('.qti-interaction.qti-textEntryInteraction'); + const $input = $container.find('.qti-interaction.qti-textEntryInteraction'); assert.equal( $input.length, @@ -177,8 +175,8 @@ define([ $input.keyup(); ready(); }) - .on('responsechange', function(state) { - var $input = $container.find('.qti-interaction.qti-textEntryInteraction'); + .on('responsechange', function() { + const $input = $container.find('.qti-interaction.qti-textEntryInteraction'); assert.ok(!hasTooltip($input), 'the error tooltip is hidden in a correct response'); ready(); }) @@ -234,10 +232,10 @@ define([ }); QUnit.test('set/get response', function(assert) { - var ready = assert.async(); + const ready = assert.async(); - var $container = $('#set-get-response'); - var state = { RESPONSE: { response: { base: { string: 'PARIS' } } } }; + const $container = $('#set-get-response'); + const state = { RESPONSE: { response: { base: { string: 'PARIS' } } } }; assert.equal($container.length, 1, 'the item container exists'); assert.equal($container.children().length, 0, 'the container has no children'); @@ -245,7 +243,7 @@ define([ runner = qtiItemRunner('qti', textEntryData) .on('render', function() { ready(); - var $input = $container.find('.qti-interaction.qti-textEntryInteraction'); + const $input = $container.find('.qti-interaction.qti-textEntryInteraction'); assert.equal( $input.length, @@ -268,13 +266,40 @@ define([ .render($container); }); + QUnit.test('get response converts ambiguous chars', function(assert) { + const ready = assert.async(); + + const $container = $('#set-get-response'); + //here 12 is entered using unicode wide chars + const unicodeCharsString = ' 12 '; + const asciiCharsString = '12'; + const state = { RESPONSE: { response: { base: { string: unicodeCharsString } } } }; + + runner = qtiItemRunner('qti', textEntryData) + .on('render', function() { + ready(); + const $input = $container.find('.qti-interaction.qti-textEntryInteraction'); + + this.setState(state); + assert.equal($input.val(), unicodeCharsString, 'the text input has been correctly set'); + $input.keyup(); //Trigger the response changed event + }) + .on('statechange', function(retrivedState) { + assert.equal(retrivedState.RESPONSE.response.base.string, asciiCharsString, 'unicode string got converted'); + }) + .init() + .render($container); + }); + + + QUnit.module('Visual Test'); QUnit.test('Display and play', function(assert) { - var ready = assert.async(); + const ready = assert.async(); assert.expect(3); - var $container = $('#outside-container'); + const $container = $('#outside-container'); assert.equal($container.length, 1, 'the item container exists'); assert.equal($container.children().length, 0, 'the container has no children'); From 6a32d5edb94cddfdcb5a193a12fd9d962981810f Mon Sep 17 00:00:00 2001 From: Andrey Shaveko Date: Fri, 23 Dec 2022 14:36:15 +0300 Subject: [PATCH 06/15] chore: set port for testing server --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f3a0181d..f31d7c48 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ }, "scripts": { "test": "npx qunit-testrunner", - "test:keepAlive": "npx qunit-testrunner --keepalive", + "test:keepAlive": "npx qunit-testrunner --keepalive --port 5300", "test:cov": "npm run build:cov && npx qunit-testrunner --cov", "coverage": "nyc report", "coverage:html": "nyc report --reporter=lcov && open-cli coverage/lcov-report/index.html", From da109dc672d8ceb9543ded215d2196c29aad494d Mon Sep 17 00:00:00 2001 From: Andrey Shaveko Date: Fri, 23 Dec 2022 14:41:50 +0300 Subject: [PATCH 07/15] fix: refer tao-core-sdk branch dependency --- package-lock.json | 7 +++---- package.json | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index c965da58..e4234ecd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -556,9 +556,8 @@ "dev": true }, "@oat-sa/tao-core-sdk": { - "version": "1.21.1", - "resolved": "https://registry.npmjs.org/@oat-sa/tao-core-sdk/-/tao-core-sdk-1.21.1.tgz", - "integrity": "sha512-VI1JK8Qxn3dxTS0TfYdYVVtF6nriBf1ra2lFY+jhrnbmn6oPrODqW0eeTdYiFohL0Lit44YeUGxTQfcQHuTwkw==", + "version": "git+https://github.com/oat-sa/tao-core-sdk-fe.git#b34c4f450ac9a6e484ee953a1065ac0e627e09ca", + "from": "git+https://github.com/oat-sa/tao-core-sdk-fe.git#feature/TR-5014/text-converter", "dev": true, "requires": { "fastestsmallesttextencoderdecoder": "1.0.14", @@ -2560,7 +2559,7 @@ "idb-wrapper": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/idb-wrapper/-/idb-wrapper-1.7.0.tgz", - "integrity": "sha1-Cn+yxw4OF3+RGOZHPGdTVrXmKD4=", + "integrity": "sha512-X9Xgu7/c/HvMMxZ+TRJQ95q8Cv7QbEBz/3+SAgYSP6HpqEJyj3cRFIXRTN1mtSZxbdKbfAXBpxwi+VSJnfaexg==", "dev": true }, "ieee754": { diff --git a/package.json b/package.json index f31d7c48..83439a25 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "@oat-sa/prettier-config": "^0.1.1", "@oat-sa/rollup-plugin-wildcard-external": "^0.1.0", "@oat-sa/tao-core-libs": "^0.5.1", - "@oat-sa/tao-core-sdk": "^1.21.1", + "@oat-sa/tao-core-sdk": "https://github.com/oat-sa/tao-core-sdk-fe#feature/TR-5014/text-converter", "@oat-sa/tao-core-shared-libs": "^1.4.1", "@oat-sa/tao-core-ui": "^1.64.1", "@oat-sa/tao-item-runner": "^0.8.1", From 5dc204dae9f1eb723570267a0068b7fa3cc6b455 Mon Sep 17 00:00:00 2001 From: Andrey Shaveko Date: Fri, 23 Dec 2022 14:42:12 +0300 Subject: [PATCH 08/15] chore: comment update --- test/qtiCommonRenderer/interactions/textEntry/test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/qtiCommonRenderer/interactions/textEntry/test.js b/test/qtiCommonRenderer/interactions/textEntry/test.js index 9faf69a8..8d8c0005 100644 --- a/test/qtiCommonRenderer/interactions/textEntry/test.js +++ b/test/qtiCommonRenderer/interactions/textEntry/test.js @@ -270,7 +270,7 @@ define([ const ready = assert.async(); const $container = $('#set-get-response'); - //here 12 is entered using unicode wide chars + //here 12 is entered using unicode wide chars and leading spaces const unicodeCharsString = ' 12 '; const asciiCharsString = '12'; const state = { RESPONSE: { response: { base: { string: unicodeCharsString } } } }; From a7fd295b72360349e6fe30d30d433b7f374560cd Mon Sep 17 00:00:00 2001 From: Andrey Shaveko Date: Mon, 26 Dec 2022 14:08:49 +0300 Subject: [PATCH 09/15] feat: ExtendedTextInteraction coversion test case --- .../interactions/extendedText/test.js | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/test/qtiCommonRenderer/interactions/extendedText/test.js b/test/qtiCommonRenderer/interactions/extendedText/test.js index b13e74a5..d46bb389 100644 --- a/test/qtiCommonRenderer/interactions/extendedText/test.js +++ b/test/qtiCommonRenderer/interactions/extendedText/test.js @@ -560,6 +560,38 @@ define([ .render($container); }); + QUnit.test('cnverts ambiguous chars', (assert)=>{ + var ready = assert.async(); + + var $container = $(`#${fixtureContainerId}10`); + var response = ' 12 '; + const convertedResponse = ' 12 '; + + runner = qtiItemRunner('qti', itemDataXhtml) + .on('error', function(e) { + assert.ok(false, e); + ready(); + }) + .on('render', function() { + var self = this; + + var $interaction = $('.qti-extendedTextInteraction', $container); + + var editor = ckEditor.instances[$interaction.data('editor')]; + + editor.setData(response); + + assert.deepEqual( + self.getState(), + { RESPONSE: { response: { base: { string: convertedResponse } } } }, + 'A response is converted' + ); + }) + .init() + .render($container); + + }); + QUnit.test('destroys', function(assert) { var ready = assert.async(); assert.expect(8); From f3f15082f52d8cbe65ba95556eaddbdabb7a3c83 Mon Sep 17 00:00:00 2001 From: Andrey Shaveko Date: Mon, 26 Dec 2022 14:12:14 +0300 Subject: [PATCH 10/15] feat: ExtendedTextInteraction convert value --- .../interactions/ExtendedTextInteraction.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/qtiCommonRenderer/renderers/interactions/ExtendedTextInteraction.js b/src/qtiCommonRenderer/renderers/interactions/ExtendedTextInteraction.js index fd49332d..50fc1dd2 100644 --- a/src/qtiCommonRenderer/renderers/interactions/ExtendedTextInteraction.js +++ b/src/qtiCommonRenderer/renderers/interactions/ExtendedTextInteraction.js @@ -34,6 +34,7 @@ import ckEditor from 'ckeditor'; import ckConfigurator from 'taoQtiItem/qtiCommonRenderer/helpers/ckConfigurator'; import patternMaskHelper from 'taoQtiItem/qtiCommonRenderer/helpers/patternMask'; import tooltip from 'ui/tooltip'; +import converter from 'util/converter'; import loggerFactory from 'core/logger'; /** @@ -322,19 +323,20 @@ function getResponse(interaction) { values = []; $container.find('input').each(function (i) { - const $el = $(this); + const value = $(this).val(); - if (attributes.placeholderText && $el.val() === attributes.placeholderText) { + if (attributes.placeholderText && value === attributes.placeholderText) { values[i] = ''; } else { + const convertedValue = converter.conver(value); if (baseType === 'integer') { - values[i] = parseInt($el.val(), numericBase); + values[i] = parseInt(convertedValue, numericBase); values[i] = isNaN(values[i]) ? '' : values[i]; } else if (baseType === 'float') { - values[i] = parseFloat($el.val()); + values[i] = parseFloat(convertedValue); values[i] = isNaN(values[i]) ? '' : values[i]; } else if (baseType === 'string') { - values[i] = $el.val(); + values[i] = convertedValue; } } }); From 685eaeaa71385c062b683394b398301287164a2d Mon Sep 17 00:00:00 2001 From: Andrey Shaveko Date: Mon, 26 Dec 2022 14:56:40 +0300 Subject: [PATCH 11/15] fix: update fixture --- .../interactions/extendedText/test.html | 1 + .../interactions/extendedText/test.js | 65 ++++++++++--------- 2 files changed, 34 insertions(+), 32 deletions(-) diff --git a/test/qtiCommonRenderer/interactions/extendedText/test.html b/test/qtiCommonRenderer/interactions/extendedText/test.html index 60f3d3be..e9fa9049 100644 --- a/test/qtiCommonRenderer/interactions/extendedText/test.html +++ b/test/qtiCommonRenderer/interactions/extendedText/test.html @@ -29,6 +29,7 @@
+
diff --git a/test/qtiCommonRenderer/interactions/extendedText/test.js b/test/qtiCommonRenderer/interactions/extendedText/test.js index d46bb389..8fb8c9f1 100644 --- a/test/qtiCommonRenderer/interactions/extendedText/test.js +++ b/test/qtiCommonRenderer/interactions/extendedText/test.js @@ -560,38 +560,6 @@ define([ .render($container); }); - QUnit.test('cnverts ambiguous chars', (assert)=>{ - var ready = assert.async(); - - var $container = $(`#${fixtureContainerId}10`); - var response = ' 12 '; - const convertedResponse = ' 12 '; - - runner = qtiItemRunner('qti', itemDataXhtml) - .on('error', function(e) { - assert.ok(false, e); - ready(); - }) - .on('render', function() { - var self = this; - - var $interaction = $('.qti-extendedTextInteraction', $container); - - var editor = ckEditor.instances[$interaction.data('editor')]; - - editor.setData(response); - - assert.deepEqual( - self.getState(), - { RESPONSE: { response: { base: { string: convertedResponse } } } }, - 'A response is converted' - ); - }) - .init() - .render($container); - - }); - QUnit.test('destroys', function(assert) { var ready = assert.async(); assert.expect(8); @@ -649,6 +617,39 @@ define([ .render($container); }); + QUnit.test('converts the response', (assert)=>{ + var ready = assert.async(); + + var $container = $(`#${fixtureContainerId}11`); + var response = ' 12 '; + const convertedResponse = ' 12 '; + + runner = qtiItemRunner('qti', itemDataXhtml) + .on('error', function(e) { + assert.ok(false, e); + ready(); + }) + .on('render', function() { + var self = this; + + var $interaction = $('.qti-extendedTextInteraction', $container); + + var editor = ckEditor.instances[$interaction.data('editor')]; + + editor.setData(response); + + assert.deepEqual( + self.getState(), + { RESPONSE: { response: { base: { string: convertedResponse } } } }, + 'A response is converted' + ); + + ready(); + }) + .init() + .render($container); + + }); QUnit.module('Visual Test'); From d6a74ec0b9cab62e8a62414eb591b9a60afaa1ae Mon Sep 17 00:00:00 2001 From: Andrey Shaveko Date: Mon, 26 Dec 2022 14:57:06 +0300 Subject: [PATCH 12/15] fix: covert single response --- .../renderers/interactions/ExtendedTextInteraction.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/qtiCommonRenderer/renderers/interactions/ExtendedTextInteraction.js b/src/qtiCommonRenderer/renderers/interactions/ExtendedTextInteraction.js index 50fc1dd2..aada3e09 100644 --- a/src/qtiCommonRenderer/renderers/interactions/ExtendedTextInteraction.js +++ b/src/qtiCommonRenderer/renderers/interactions/ExtendedTextInteraction.js @@ -323,12 +323,12 @@ function getResponse(interaction) { values = []; $container.find('input').each(function (i) { - const value = $(this).val(); + const editorValue = $(this).val(); if (attributes.placeholderText && value === attributes.placeholderText) { values[i] = ''; } else { - const convertedValue = converter.conver(value); + const convertedValue = converter.convert(editorValue); if (baseType === 'integer') { values[i] = parseInt(convertedValue, numericBase); values[i] = isNaN(values[i]) ? '' : values[i]; @@ -347,11 +347,11 @@ function getResponse(interaction) { value = ''; } else { if (baseType === 'integer') { - value = parseInt(_getTextareaValue(interaction), numericBase); + value = parseInt(converter.convert(_getTextareaValue(interaction)), numericBase); } else if (baseType === 'float') { - value = parseFloat(_getTextareaValue(interaction)); + value = converter.convert(_getTextareaValue(interaction)); } else if (baseType === 'string') { - value = _getTextareaValue(interaction, true); + value = converter.convert(_getTextareaValue(interaction, true)); } } From fbb03629f03aecad3ea789c475f4d942f04c0fe9 Mon Sep 17 00:00:00 2001 From: Andrey Shaveko Date: Mon, 26 Dec 2022 15:01:15 +0300 Subject: [PATCH 13/15] fix: es6 & eslint --- .../interactions/extendedText/test.js | 100 +++++++++--------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/test/qtiCommonRenderer/interactions/extendedText/test.js b/test/qtiCommonRenderer/interactions/extendedText/test.js index 8fb8c9f1..c6d82413 100644 --- a/test/qtiCommonRenderer/interactions/extendedText/test.js +++ b/test/qtiCommonRenderer/interactions/extendedText/test.js @@ -10,13 +10,13 @@ define([ ], function ($, _, qtiItemRunner, itemDataPlain, itemDataXhtml, keystroker, ckEditor, ckConfigurator) { 'use strict'; - var runner; - var fixtureContainerId = 'item-container-'; + let runner; + const fixtureContainerId = 'item-container-'; /** PLAIN **/ QUnit.module('Extended Text Interaction - plain format', { - afterEach: function(assert) { + afterEach: function() { if (runner) { runner.clear(); } @@ -24,10 +24,10 @@ define([ }); QUnit.test('renders correctly', function(assert) { - var ready = assert.async(); + const ready = assert.async(); assert.expect(10); - var $container = $('#' + fixtureContainerId + '0'); + const $container = $(`#${fixtureContainerId}0`); assert.equal($container.length, 1, 'the item container exists'); assert.equal($container.children().length, 0, 'the container has no children'); @@ -85,17 +85,17 @@ define([ }); QUnit.test('enables to input a response', function(assert) { - var ready = assert.async(); + const ready = assert.async(); assert.expect(16); - var $container = $('#' + fixtureContainerId + '1'); - var responsesStack = [ + const $container = $(`#${fixtureContainerId}1`); + const responsesStack = [ { response: { base: { string: 't' } } }, { response: { base: { string: 'te' } } }, { response: { base: { string: 'tes' } } }, { response: { base: { string: 'test' } } } ]; - var stackPtr = 0; + let stackPtr = 0; assert.equal($container.length, 1, 'the item container exists'); assert.equal($container.children().length, 0, 'the container has no children'); @@ -184,10 +184,10 @@ define([ }); QUnit.test('destroys', function(assert) { - var ready = assert.async(); + const ready = assert.async(); assert.expect(5); - var $container = $('#' + fixtureContainerId + '3'); + const $container = $(`#${fixtureContainerId}3`); assert.equal($container.length, 1, 'the item container exists'); assert.equal($container.children().length, 0, 'the container has no children'); @@ -198,10 +198,10 @@ define([ ready(); }) .on('render', function() { - var self = this; + const self = this; //Call destroy manually - var interaction = this._item.getInteractions()[0]; + const interaction = this._item.getInteractions()[0]; interaction.renderer.destroy(interaction); assert.equal( @@ -235,10 +235,10 @@ define([ }); QUnit.test('resets the response', function(assert) { - var ready = assert.async(); + const ready = assert.async(); assert.expect(5); - var $container = $('#' + fixtureContainerId + '4'); + const $container = $(`#${fixtureContainerId}4`); assert.equal($container.length, 1, 'the item container exists'); assert.equal($container.children().length, 0, 'the container has no children'); @@ -249,7 +249,7 @@ define([ ready(); }) .on('render', function() { - var self = this; + const self = this; assert.equal( $container.find('.qti-interaction.qti-extendedTextInteraction').length, @@ -267,7 +267,7 @@ define([ ); //Call destroy manually - var interaction = self._item.getInteractions()[0]; + const interaction = self._item.getInteractions()[0]; interaction.renderer.resetResponse(interaction); _.delay(function() { @@ -288,7 +288,7 @@ define([ /** XHTML **/ QUnit.module('Extended Text Interaction - XHTML format', { - afterEach: function(assert) { + afterEach: function() { if (runner) { runner.clear(); } @@ -296,10 +296,10 @@ define([ }); QUnit.test('renders correctly', function(assert) { - var ready = assert.async(); + const ready = assert.async(); assert.expect(11); - var $container = $('#' + fixtureContainerId + '5'); + const $container = $(`#${fixtureContainerId}5`); assert.equal($container.length, 1, 'the item container exists'); assert.equal($container.children().length, 0, 'the container has no children'); @@ -361,11 +361,11 @@ define([ }); QUnit.test('enables to input a response', function(assert) { - var ready = assert.async(); + const ready = assert.async(); assert.expect(6); - var $container = $('#' + fixtureContainerId + '6'); - var response = 'test'; + const $container = $(`#${fixtureContainerId}6`); + const response = 'test'; assert.equal($container.length, 1, 'the item container exists'); assert.equal($container.children().length, 0, 'the container has no children'); @@ -376,14 +376,14 @@ define([ ready(); }) .on('render', function() { - var $interaction = $('.qti-extendedTextInteraction', $container); + const $interaction = $('.qti-extendedTextInteraction', $container); assert.equal( $interaction.length, 1, 'the container contains a text interaction .qti-extendedTextInteraction' ); - var editor = ckEditor.instances[$interaction.data('editor')]; + const editor = ckEditor.instances[$interaction.data('editor')]; assert.ok(typeof editor === 'object', 'the interaction is link to the ck instance'); @@ -403,10 +403,10 @@ define([ }); QUnit.test('display rtl mode on ckeditor', function (assert) { - var ready = assert.async(); + const ready = assert.async(); assert.expect(3); - var $container = $('#' + fixtureContainerId + '10'); + const $container = $(`#${fixtureContainerId}10`); const ckOptions = { resize_enabled: true, @@ -422,14 +422,14 @@ define([ ready(); }) .on('render', () => { - var $interaction = $('.qti-extendedTextInteraction', $container); + const $interaction = $('.qti-extendedTextInteraction', $container); assert.equal( $interaction.length, 1, 'the container contains a text interaction .qti-extendedTextInteraction' ); - var editor = ckEditor.replace($container[0], ckOptions); + const editor = ckEditor.replace($container[0], ckOptions); ckConfigurator.getConfig(editor, "extendedText", ckOptions); editor.on('configLoaded', function () { _.delay(() => { @@ -508,11 +508,11 @@ define([ }); QUnit.test('resets the response', function(assert) { - var ready = assert.async(); + const ready = assert.async(); assert.expect(6); - var $container = $('#' + fixtureContainerId + '9'); - var response = 'test'; + const $container = $(`#${fixtureContainerId}9`); + const response = 'test'; assert.equal($container.length, 1, 'the item container exists'); assert.equal($container.children().length, 0, 'the container has no children'); @@ -523,17 +523,17 @@ define([ ready(); }) .on('render', function() { - var self = this; + const self = this; - var interaction = self._item.getInteractions()[0]; - var $interaction = $('.qti-extendedTextInteraction', $container); + const interaction = self._item.getInteractions()[0]; + const $interaction = $('.qti-extendedTextInteraction', $container); assert.equal( $interaction.length, 1, 'the container contains a text interaction .qti-extendedTextInteraction' ); - var editor = ckEditor.instances[$interaction.data('editor')]; + const editor = ckEditor.instances[$interaction.data('editor')]; editor.setData(response); @@ -561,10 +561,10 @@ define([ }); QUnit.test('destroys', function(assert) { - var ready = assert.async(); + const ready = assert.async(); assert.expect(8); - var $container = $('#' + fixtureContainerId + '8'); + const $container = $(`#${fixtureContainerId}8`); assert.equal($container.length, 1, 'the item container exists'); assert.equal($container.children().length, 0, 'the container has no children'); @@ -575,17 +575,17 @@ define([ ready(); }) .on('render', function() { - var self = this; + const self = this; //Call destroy manually - var interaction = self._item.getInteractions()[0]; - var $interaction = $('.qti-extendedTextInteraction', $container); + const interaction = self._item.getInteractions()[0]; + const $interaction = $('.qti-extendedTextInteraction', $container); assert.equal( $interaction.length, 1, 'the container contains a text interaction .qti-extendedTextInteraction' ); - var editorName = $interaction.data('editor'); + const editorName = $interaction.data('editor'); assert.ok(typeof editorName === 'string' && editorName.length > 0, 'the editor name is set'); assert.ok(typeof ckEditor.instances[editorName] === 'object', 'the editor instance is available'); @@ -618,10 +618,10 @@ define([ }); QUnit.test('converts the response', (assert)=>{ - var ready = assert.async(); + const ready = assert.async(); - var $container = $(`#${fixtureContainerId}11`); - var response = ' 12 '; + const $container = $(`#${fixtureContainerId}11`); + const response = ' 12 '; const convertedResponse = ' 12 '; runner = qtiItemRunner('qti', itemDataXhtml) @@ -630,11 +630,11 @@ define([ ready(); }) .on('render', function() { - var self = this; + const self = this; - var $interaction = $('.qti-extendedTextInteraction', $container); + const $interaction = $('.qti-extendedTextInteraction', $container); - var editor = ckEditor.instances[$interaction.data('editor')]; + const editor = ckEditor.instances[$interaction.data('editor')]; editor.setData(response); @@ -654,10 +654,10 @@ define([ QUnit.module('Visual Test'); QUnit.test('Display and play', function(assert) { - var ready = assert.async(); + const ready = assert.async(); assert.expect(1); - var $container = $('#outside-container'); + const $container = $('#outside-container'); assert.equal($container.length, 1, 'the item container exists'); From 10b7c05a35cca726d58e00536aef48d7c74d7397 Mon Sep 17 00:00:00 2001 From: Andrey Shaveko Date: Tue, 27 Dec 2022 18:29:26 +0300 Subject: [PATCH 14/15] chore: update to release version of tao-core-sdk-fe --- package-lock.json | 5 +++-- package.json | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index e4234ecd..1945d766 100644 --- a/package-lock.json +++ b/package-lock.json @@ -556,8 +556,9 @@ "dev": true }, "@oat-sa/tao-core-sdk": { - "version": "git+https://github.com/oat-sa/tao-core-sdk-fe.git#b34c4f450ac9a6e484ee953a1065ac0e627e09ca", - "from": "git+https://github.com/oat-sa/tao-core-sdk-fe.git#feature/TR-5014/text-converter", + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@oat-sa/tao-core-sdk/-/tao-core-sdk-1.22.0.tgz", + "integrity": "sha512-e2cAYI2mJfZ6rlzph9bs352riCZsmfztddjtIM5Mjn5HZvPj8zSiQYHz6t4lI/Yrkfsa2a6vFpkvDpk/QUinzg==", "dev": true, "requires": { "fastestsmallesttextencoderdecoder": "1.0.14", diff --git a/package.json b/package.json index 83439a25..0ae10421 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "@oat-sa/prettier-config": "^0.1.1", "@oat-sa/rollup-plugin-wildcard-external": "^0.1.0", "@oat-sa/tao-core-libs": "^0.5.1", - "@oat-sa/tao-core-sdk": "https://github.com/oat-sa/tao-core-sdk-fe#feature/TR-5014/text-converter", + "@oat-sa/tao-core-sdk": "^1.22.0", "@oat-sa/tao-core-shared-libs": "^1.4.1", "@oat-sa/tao-core-ui": "^1.64.1", "@oat-sa/tao-item-runner": "^0.8.1", From 231b566c6bb188fc334add9b827eaef73eccb899 Mon Sep 17 00:00:00 2001 From: Andrey Shaveko Date: Tue, 27 Dec 2022 18:35:00 +0300 Subject: [PATCH 15/15] chore: bump version --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1945d766..f46e5ecf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@oat-sa/tao-item-runner-qti", - "version": "1.8.0", + "version": "1.9.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 0ae10421..18171284 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@oat-sa/tao-item-runner-qti", - "version": "1.8.0", + "version": "1.9.0", "displayName": "TAO Item Runner QTI", "description": "TAO QTI Item Runner modules", "files": [