From 1bd0a27e0bfbbda025d6a6ec3a527c95ae6eac04 Mon Sep 17 00:00:00 2001 From: Mateusz Hyndle Date: Tue, 14 Jul 2015 17:03:04 +0200 Subject: [PATCH] EZP-23767: create new translation basing on existing one --- Resources/config/css.yml | 2 + Resources/config/yui.yml | 16 + .../css/theme/views/actions/translate.css | 11 + .../css/theme/views/languageselectionbox.css | 62 +++ .../public/css/views/actions/translate.css | 5 + .../public/css/views/languageselectionbox.css | 88 +++ Resources/public/js/apps/ez-platformuiapp.js | 13 + .../plugins/ez-languageselectionboxplugin.js | 42 ++ .../views/actions/ez-translateactionview.js | 61 ++- .../js/views/ez-languageselectionboxview.js | 413 +++++++++++++++ .../services/ez-contenteditviewservice.js | 155 +++++- .../ez-languageselectionboxviewservice.js | 55 ++ .../services/ez-locationviewviewservice.js | 27 + .../public/templates/languageselectionbox.hbt | 32 ++ .../public/templates/translateaction.hbt | 1 + Resources/views/PlatformUI/shell.html.twig | 8 +- .../ez-languageselectionboxplugin-tests.js | 79 +++ .../ez-languageselectionboxplugin.html | 44 ++ .../assets/ez-translateactionview-tests.js | 122 ++++- .../views/actions/ez-translateactionview.html | 4 +- .../ez-languageselectionboxview-tests.js | 500 ++++++++++++++++++ .../js/views/ez-languageselectionboxview.html | 86 +++ .../assets/ez-contenteditviewservice-tests.js | 399 +++++++++++++- .../services/ez-contenteditviewservice.html | 2 +- 24 files changed, 2203 insertions(+), 24 deletions(-) create mode 100644 Resources/public/css/theme/views/languageselectionbox.css create mode 100644 Resources/public/css/views/languageselectionbox.css create mode 100644 Resources/public/js/apps/plugins/ez-languageselectionboxplugin.js create mode 100644 Resources/public/js/views/ez-languageselectionboxview.js create mode 100644 Resources/public/js/views/services/ez-languageselectionboxviewservice.js create mode 100644 Resources/public/templates/languageselectionbox.hbt create mode 100644 Tests/js/apps/plugins/assets/ez-languageselectionboxplugin-tests.js create mode 100644 Tests/js/apps/plugins/ez-languageselectionboxplugin.html create mode 100644 Tests/js/views/assets/ez-languageselectionboxview-tests.js create mode 100644 Tests/js/views/ez-languageselectionboxview.html diff --git a/Resources/config/css.yml b/Resources/config/css.yml index 5613122b5..2b7a5f38c 100644 --- a/Resources/config/css.yml +++ b/Resources/config/css.yml @@ -15,6 +15,7 @@ system: - 'bundles/ezplatformui/css/layout.css' - 'bundles/ezplatformui/css/views/navigationhub.css' - 'bundles/ezplatformui/css/views/confirmbox.css' + - 'bundles/ezplatformui/css/views/languageselectionbox.css' - 'bundles/ezplatformui/css/views/notificationhub.css' - 'bundles/ezplatformui/css/views/notification.css' - 'bundles/ezplatformui/css/views/universaldiscovery.css' @@ -90,6 +91,7 @@ system: - 'bundles/ezplatformui/css/theme/views/loginform.css' - 'bundles/ezplatformui/css/theme/views/bar.css' - 'bundles/ezplatformui/css/theme/views/confirmbox.css' + - 'bundles/ezplatformui/css/theme/views/languageselectionbox.css' - 'bundles/ezplatformui/css/theme/views/notificationhub.css' - 'bundles/ezplatformui/css/theme/views/notification.css' - 'bundles/ezplatformui/css/theme/views/universaldiscovery.css' diff --git a/Resources/config/yui.yml b/Resources/config/yui.yml index 654e2c1e1..1efab3493 100644 --- a/Resources/config/yui.yml +++ b/Resources/config/yui.yml @@ -58,6 +58,8 @@ system: - 'ez-universaldiscoveryview' - 'ez-confirmboxviewservice' - 'ez-confirmboxview' + - 'ez-languageselectionboxviewservice' + - 'ez-languageselectionboxview' - 'ez-notificationhubviewservice' - 'ez-notificationhubview' - 'ez-usermodel' @@ -66,6 +68,7 @@ system: - 'ez-domstateplugin' - 'ez-universaldiscoveryplugin' - 'ez-confirmboxplugin' + - 'ez-languageselectionboxplugin' - 'ez-notificationhubplugin' - 'ez-positionplugin' - 'ez-updatetreeplugin' @@ -88,6 +91,7 @@ system: - 'ez-savedraftplugin' - 'ez-publishdraftplugin' - 'ez-discarddraftplugin' + - 'array-extras' path: %ez_platformui.public_dir%/js/views/services/ez-contenteditviewservice.js ez-contentcreateviewservice: requires: ['ez-contenteditviewservice'] @@ -116,6 +120,9 @@ system: ez-confirmboxviewservice: requires: ['ez-viewservice'] path: %ez_platformui.public_dir%/js/views/services/ez-confirmboxviewservice.js + ez-languageselectionboxviewservice: + requires: ['ez-viewservice'] + path: %ez_platformui.public_dir%/js/views/services/ez-languageselectionboxviewservice.js ez-notificationhubviewservice: requires: ['ez-viewservice', 'ez-notificationlist'] path: %ez_platformui.public_dir%/js/views/services/ez-notificationhubviewservice.js @@ -222,6 +229,12 @@ system: confirmboxview-ez-template: type: 'template' path: %ez_platformui.public_dir%/templates/confirmbox.hbt + ez-languageselectionboxview: + requires: ['ez-templatebasedview', 'languageselectionboxview-ez-template'] + path: %ez_platformui.public_dir%/js/views/ez-languageselectionboxview.js + languageselectionboxview-ez-template: + type: 'template' + path: %ez_platformui.public_dir%/templates/languageselectionbox.hbt ez-notificationhubview: requires: ['ez-view', 'ez-notificationview', 'ez-notificationlist', 'ez-height-change'] path: %ez_platformui.public_dir%/js/views/ez-notificationhubview.js @@ -746,6 +759,9 @@ system: ez-confirmboxplugin: requires: ['plugin', 'base', 'ez-pluginregistry'] path: %ez_platformui.public_dir%/js/apps/plugins/ez-confirmboxplugin.js + ez-languageselectionboxplugin: + requires: ['plugin', 'base', 'ez-pluginregistry'] + path: %ez_platformui.public_dir%/js/apps/plugins/ez-languageselectionboxplugin.js ez-universaldiscoveryplugin: requires: ['plugin', 'base', 'ez-pluginregistry'] path: %ez_platformui.public_dir%/js/apps/plugins/ez-universaldiscoveryplugin.js diff --git a/Resources/public/css/theme/views/actions/translate.css b/Resources/public/css/theme/views/actions/translate.css index 8d07cd4a3..2328df560 100644 --- a/Resources/public/css/theme/views/actions/translate.css +++ b/Resources/public/css/theme/views/actions/translate.css @@ -49,3 +49,14 @@ border-radius: 0.5em; font-weight: bold; } + +.ez-view-translateactionview .ez-newtranslation-button { + background: #B8E986; + color: #333333; + font-size: 90%; + font-weight: bold; +} + +.ez-view-translateactionview .ez-newtranslation-button:hover { + background: #B8E986; +} diff --git a/Resources/public/css/theme/views/languageselectionbox.css b/Resources/public/css/theme/views/languageselectionbox.css new file mode 100644 index 000000000..0094be3b3 --- /dev/null +++ b/Resources/public/css/theme/views/languageselectionbox.css @@ -0,0 +1,62 @@ +/** + * Copyright (C) eZ Systems AS. All rights reserved. + * For full copyright and license information view LICENSE file distributed with this source code. + */ + +.is-languageselectionbox-hidden .ez-languageselectionbox-container { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + + background: #000; + -webkit-transform: translateY(-100%); + transform: translateY(-100%); +} + +.ez-languageselectionbox-container { + background: rgba(0, 0, 0, 0.6); + transition: all 0.3s; + + -webkit-transform: translateY(0); + transform: translateY(0); +} + +.ez-view-languageselectionboxview { + background: #D8D8D8; + border: 1px solid #aaa; + border-radius: 3px; +} + +.ez-view-languageselectionboxview .ez-languageselectionbox-title { + font-size: 130%; + font-weight: normal; + color: #666; +} + +.ez-view-languageselectionboxview .ez-languageselectionbox-languages { + background: #fff; + border: solid 1px #aaa; + border-radius: 3px; +} + +.ez-view-languageselectionboxview .ez-translation { + cursor: pointer; +} + +.ez-view-languageselectionboxview .ez-translation:hover { + background: #DDF5FF; +} + +.ez-view-languageselectionboxview .ez-translation.is-translation-selected { + background: #CCE4FF; +} + +.ez-view-languageselectionboxview .ez-languageselectionbox-close-icon:after { + color: #444; + font-size: 150%; +} + +.ez-view-languageselectionboxview .ez-languageselectionbox-confirm { + font-weight: bold; +} diff --git a/Resources/public/css/views/actions/translate.css b/Resources/public/css/views/actions/translate.css index 699b093e3..5b762ac37 100644 --- a/Resources/public/css/views/actions/translate.css +++ b/Resources/public/css/views/actions/translate.css @@ -71,3 +71,8 @@ display: block; padding: 0.1em 0.5em; } + +.ez-view-translateactionview .ez-newtranslation-button { + width: 17em; + margin: 0.5em; +} diff --git a/Resources/public/css/views/languageselectionbox.css b/Resources/public/css/views/languageselectionbox.css new file mode 100644 index 000000000..356043513 --- /dev/null +++ b/Resources/public/css/views/languageselectionbox.css @@ -0,0 +1,88 @@ +/** + * Copyright (C) eZ Systems AS. All rights reserved. + * For full copyright and license information view LICENSE file distributed with this source code. + */ + +.ez-languageselectionbox-container { + position: fixed; + width: 100%; + height: 100%; + top: 0; + left: 0; + z-index: 21000; + + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; +} + +.is-languageselectionbox-hidden .ez-languageselectionbox-container { + display: none; +} + +.ez-view-languageselectionboxview { + position: relative; + display: inline-block; + margin: auto; + padding: 1.5em 2.2em; +} + +.ez-view-languageselectionboxview .ez-languageselectionbox-title { + margin: 0; + padding-bottom: 0.2em; + text-align: left; +} + +.ez-view-languageselectionboxview .ez-languageselectionbox-close-icon { + position: absolute; + top: 0.2em; + right: 0.2em; +} + +.ez-view-languageselectionboxview .ez-languageselectionbox-basetranslation { + display: block; + text-align: right; + margin: 1em 0; +} + +.ez-view-languageselectionboxview .ez-languageselectionbox-languages { + display: block; + width: 30em; + overflow: hidden; + padding: 10px 0; +} + +.ez-view-languageselectionboxview .ez-translation { + float: left; + width: 12em; + margin: 0 1em; + padding: 0.3em 0.5em; + list-style-type: none; + line-height: 1.8em; +} + +.ez-view-languageselectionboxview .ez-languageselectionbox-existingtranslations-container { + display: none; +} + +.ez-view-languageselectionboxview .ez-languageselectionbox-basetranslation-area { + display: none; +} + +.ez-view-languageselectionboxview.is-base-translation-allowed .ez-languageselectionbox-basetranslation-area { + display: block; +} + +.ez-view-languageselectionboxview.is-base-translations-list-visible .ez-languageselectionbox-existingtranslations-container { + display: block; +} + +.ez-view-languageselectionboxview .ez-languageselectionbox-tools { + text-align: right; + margin: 2em 0 0 0; +} + +.ez-view-languageselectionboxview .ez-languageselectionbox-confirm { + margin-left: 2em; +} diff --git a/Resources/public/js/apps/ez-platformuiapp.js b/Resources/public/js/apps/ez-platformuiapp.js index 4b370eba5..58c0ed06c 100644 --- a/Resources/public/js/apps/ez-platformuiapp.js +++ b/Resources/public/js/apps/ez-platformuiapp.js @@ -84,6 +84,12 @@ YUI.add('ez-platformuiapp', function (Y) { container: '.ez-confirmbox-container', hideClass: 'is-confirmbox-hidden', }, + languageSelectionBox: { + type: Y.eZ.LanguageSelectionBoxView, + service: Y.eZ.LanguageSelectionBoxViewService, + container: '.ez-languageselectionbox-container', + hideClass: 'is-languageselectionbox-hidden', + }, notificationHub: { type: Y.eZ.NotificationHubView, service: Y.eZ.NotificationHubViewService, @@ -732,6 +738,13 @@ YUI.add('ez-platformuiapp', function (Y) { sideViews: {'navigationHub': true, 'discoveryBar': false}, view: 'studioPlusPresentationView', callbacks: ['open', 'checkUser', 'handleSideViews', 'handleMainView'] + }, { + name: "translateContent", + path: '/edit/:id/:languageCode/:baseLanguageCode', + service: Y.eZ.ContentEditViewService, + sideViews: {'navigationHub': false, 'discoveryBar': false}, + view: 'contentEditView', + callbacks: ['open', 'checkUser', 'handleSideViews', 'handleMainView'] }, { name: "editContent", path: '/edit/:id/:languageCode', diff --git a/Resources/public/js/apps/plugins/ez-languageselectionboxplugin.js b/Resources/public/js/apps/plugins/ez-languageselectionboxplugin.js new file mode 100644 index 000000000..37c4151dd --- /dev/null +++ b/Resources/public/js/apps/plugins/ez-languageselectionboxplugin.js @@ -0,0 +1,42 @@ +/* + * Copyright (C) eZ Systems AS. All rights reserved. + * For full copyright and license information view LICENSE file distributed with this source code. + */ +YUI.add('ez-languageselectionboxplugin', function (Y) { + "use strict"; + /** + * Provides the language selection box plugin + * + * @module ez-languageselectionboxplugin + */ + Y.namespace('eZ.Plugin'); + + /** + * The language selection box plugin. It's a plugin the application to set up the + * `languageSelect`, `languageSelected` and `cancelLanguageSelection` event handlers. + * + * @namespace eZ.Plugin + * @class LanguageSelectionBox + * @constructor + * @extends Plugin.Base + */ + Y.eZ.Plugin.LanguageSelectionBox = Y.Base.create('languageSelectionBoxPlugin', Y.Plugin.Base, [], { + initializer: function () { + var app = this.get('host'); + + app.on('*:languageSelect', function (e) { + app.showSideView('languageSelectionBox', e.config); + }); + + app.on(['*:languageSelected', '*:cancelLanguageSelection'], function (e) { + app.hideSideView('languageSelectionBox'); + }); + }, + }, { + NS: 'languageSelectionBox', + }); + + Y.eZ.PluginRegistry.registerPlugin( + Y.eZ.Plugin.LanguageSelectionBox, ['platformuiApp'] + ); +}); diff --git a/Resources/public/js/views/actions/ez-translateactionview.js b/Resources/public/js/views/actions/ez-translateactionview.js index 624c7873e..2b8571e10 100644 --- a/Resources/public/js/views/actions/ez-translateactionview.js +++ b/Resources/public/js/views/actions/ez-translateactionview.js @@ -11,6 +11,12 @@ YUI.add('ez-translateactionview', function (Y) { */ Y.namespace('eZ'); + var events = { + '.ez-newtranslation-button': { + 'tap': '_newTranslationLanguageSelectionBox', + } + }; + /** * Translate Action View * @@ -21,6 +27,7 @@ YUI.add('ez-translateactionview', function (Y) { */ Y.eZ.TranslateActionView = Y.Base.create('translateActionView', Y.eZ.ButtonActionView, [Y.eZ.Expandable], { initializer: function () { + this.events = Y.merge(this.events, events); this.after({ 'translateAction': this._toggleExpanded, 'expandedChange': this._setClickOutsideEventHandler, @@ -103,7 +110,7 @@ YUI.add('ez-translateactionview', function (Y) { _getTranslateButtonHint: function () { var translations = this.get('content').get('currentVersion').getTranslationsList(), countAll = translations.length, - moreTranslations = Y.clone(translations); + moreTranslations = Y.Object.values(Y.merge(translations)); moreTranslations.splice(2, countAll-2); @@ -112,6 +119,58 @@ YUI.add('ez-translateactionview', function (Y) { } return moreTranslations.join(', '); + }, + + /** + * Tap event handler on New Translation button. It opens language selection box. + * + * @method _newTranslationLanguageSelectionBox + * @private + * @param {EventFacade} e + */ + _newTranslationLanguageSelectionBox: function (e) { + e.preventDefault(); + this.fire('languageSelect', { + config: { + title: "Select a language for your new translation:", + languageSelectedHandler: Y.bind(this._newTranslation, this), + cancelLanguageSelectionHandler: null, + canBaseTranslation: true, + existingTranslations: this.get('content').get('currentVersion').getTranslationsList() + }, + }); + this._hideView(); + }, + + /** + * Fires `translate` event after making a selection on LanguageSelectionBox + * + * @method _newTranslation + * @private + * @param {EventFacade} e + */ + _newTranslation: function (e) { + var languageCode = e.selectedLanguageCode, + isBaseLanguage = e.baseTranslation, + data = { + content: this.get('content'), + toLanguageCode: languageCode, + }; + + if (isBaseLanguage && e.selectedBaseLanguageCode !== null){ + data.baseLanguageCode = e.selectedBaseLanguageCode; + } + + /** + * Fired when content is being translated + * + * @event translateContent + * @param {Object} data + * @param {eZ.Content} data.content content object which will be translated + * @param {String} data.toLanguageCode language to which content will be translated + * @param {String} data.baseLanguageCode optional language on which translation will be basing + */ + this.fire('translateContent', data); } }, { ATTRS: { diff --git a/Resources/public/js/views/ez-languageselectionboxview.js b/Resources/public/js/views/ez-languageselectionboxview.js new file mode 100644 index 000000000..9efd5cc7e --- /dev/null +++ b/Resources/public/js/views/ez-languageselectionboxview.js @@ -0,0 +1,413 @@ +/* + * Copyright (C) eZ Systems AS. All rights reserved. + * For full copyright and license information view LICENSE file distributed with this source code. + */ +YUI.add('ez-languageselectionboxview', function (Y) { + "use strict"; + /** + * Provides the language selection box view class + * + * @module ez-languageselectionboxview + */ + Y.namespace('eZ'); + + var LANGUAGE_SELECTED = 'languageSelected', + CANCEL_LANGUAGE_SELECTION = 'cancelLanguageSelection', + BASE_TRANSLATION_AVAILABLE_CLASS = 'is-base-translation-allowed', + BASE_TRANSLATIONS_LIST_VISIBLE_CLASS = 'is-base-translations-list-visible', + TRANSLATION_HIGHLIGHT_CLASS = 'is-translation-selected'; + + /** + * The language selection box view. + * + * @namespace eZ + * @class LanguageSelectionBoxView + * @constructor + * @extends eZ.TemplateBasedView + */ + Y.eZ.LanguageSelectionBoxView = Y.Base.create('languageSelectionBoxView', Y.eZ.TemplateBasedView, [], { + events: { + '.ez-languageselectionbox-close': { + 'tap': '_cancelLanguageSelection', + }, + '.ez-languageselectionbox-confirm': { + 'tap': '_confirmLanguageSelection', + }, + '.ez-new-translation': { + 'tap': '_selectNewTranslation' + }, + '.ez-base-translation': { + 'tap': '_selectBaseTranslation' + }, + '.ez-base-translation-checkbox': { + 'change': '_toggleBaseTranslation' + }, + }, + + initializer: function () { + this.on(['languageSelectedHandlerChange', 'cancelLanguageSelectionHandlerChange'], function (e) { + this._syncEventHandler(e.attrName.replace(/Handler$/, ''), e.prevVal, e.newVal); + }); + this._publishEvents(); + this.after('activeChange', function () { + if ( this.get('active') ) { + this.reset('baseTranslation'); + this.reset('selectedLanguageCode'); + this.reset('selectedBaseLanguageCode'); + this.render(); + } + }); + this.on('canBaseTranslationChange', function (e) { + this._uiSetBaseTranslationVisibility(e.newVal); + }); + this.on('selectedLanguageCodeChange', function (e) { + if ( this.get('active') ) { + this._uiHighlightTranslation('new', e.newVal); + } + }); + this.after('selectedLanguageCodeChange', function (e) { + this._uiSetConfirmButtonState(); + }); + this.on('selectedBaseLanguageCodeChange', function (e) { + if ( this.get('active') ) { + this._uiHighlightTranslation('base', e.newVal); + } + }); + this.on('baseTranslationChange', function (e) { + if ( this.get('active') ) { + this._uiBaseTranslationState(e.newVal); + } + }); + }, + + /** + * Tap event handler on language from new translations list + * + * @method _selectNewTranslation + * @protected + * @param {EventFacade} e + */ + _selectNewTranslation: function (e) { + var languageCode = e.target.getAttribute('data-languagecode'); + + this.set('selectedLanguageCode', languageCode); + }, + + /** + * Tap event handler on language from existing translations list + * + * @method _selectBaseTranslation + * @protected + * @param {EventFacade} e + */ + _selectBaseTranslation: function (e) { + var languageCode = e.target.getAttribute('data-languagecode'); + + this.set('selectedBaseLanguageCode', languageCode); + }, + + /** + * Tap event handler on switcher dictating if new translation will base + * on already existing one or not + * + * @method _toggleBaseTranslation + * @protected + */ + _toggleBaseTranslation: function (e) { + this.set('baseTranslation', e.target.get('checked')); + }, + + /** + * Publishes the cancelLanguageSelection and languageSelected events + * + * @method _publishEvents + * @protected + */ + _publishEvents: function () { + this.publish(LANGUAGE_SELECTED, { + bubbles: true, + emitFacade: true, + preventable: false, + defaultFn: this._resetState, + }); + this.publish(CANCEL_LANGUAGE_SELECTION, { + bubbles: true, + emitFacade: true, + preventable: false, + defaultFn: this._resetState, + }); + }, + + /** + * languageSelectedHandlerChange and cancelLanguageSelectionHandlerChange event + * handler. It makes sure the potential previous event handler are + * removed and it adds the new handlers if any. + * + * @method _syncEventHandler + * @private + * @param {String} eventName event name + * @param {Function|Null} oldHandler the previous event handler + * @param {Function|Null} newHandler the new event handler + */ + _syncEventHandler: function (eventName, oldHandler, newHandler) { + if ( oldHandler ) { + this.detach(eventName, oldHandler); + } + if ( newHandler ) { + this.on(eventName, newHandler); + } + }, + + /** + * Resets the state of the languageSelectionBox view + * + * @method _resetState + * @protected + */ + _resetState: function () { + this.reset('baseTranslation'); + this.reset('selectedLanguageCode'); + this.reset('selectedBaseLanguageCode'); + }, + + /** + * Highlights the selected translation + * + * @method _uiHighlightTranslation + * @protected + * @param {String} section + * @param {String} languageCode + */ + _uiHighlightTranslation: function (section, languageCode) { + this.get('container') + .all('.ez-' + section + '-translation') + .removeClass(TRANSLATION_HIGHLIGHT_CLASS); + + if ( languageCode !== null ) { + this.get('container') + .one('.ez-' + section + '-translation[data-languagecode="' + languageCode + '"]') + .addClass(TRANSLATION_HIGHLIGHT_CLASS); + } + }, + + /** + * Sets the state for base translation checkbox + * + * @method _uiBaseTranslationState + * @protected + * @param {String} baseTranslation + */ + _uiBaseTranslationState: function (baseTranslation) { + var c = this.get('container'), + baseCheckbox = c.one('.ez-base-translation-checkbox'); + + baseCheckbox.set('checked', baseTranslation); + if (baseTranslation) { + c.addClass(BASE_TRANSLATIONS_LIST_VISIBLE_CLASS); + } else { + c.removeClass(BASE_TRANSLATIONS_LIST_VISIBLE_CLASS); + } + }, + + /** + * Sets visibility of whole part containing base translations + * + * @method _uiSetBaseTranslationVisibility + * @protected + * @param {Boolean} canBaseTranslation + */ + _uiSetBaseTranslationVisibility: function (canBaseTranslation) { + var c = this.get('container'); + + if (canBaseTranslation) { + c.addClass(BASE_TRANSLATION_AVAILABLE_CLASS); + } else { + c.removeClass(BASE_TRANSLATION_AVAILABLE_CLASS); + } + }, + + /** + * `selectedLanguageCodeChange` event handler. It enables/disables the button + * depending on new translation selection + * + * @method _uiSetConfirmButtonState + * @protected + */ + _uiSetConfirmButtonState: function () { + var confirmButton = this.get('container').one('.ez-languageselectionbox-confirm'); + + confirmButton.set('disabled', !this.get('selectedLanguageCode')); + }, + + render: function () { + var container = this.get('container'); + + container.setHTML(this.template({ + title: this.get('title'), + newTranslations: this.get('newTranslations'), + existingTranslations: this.get('existingTranslations'), + canBaseTranslation: this.get('canBaseTranslation'), + })); + + return this; + }, + + /** + * Cancel the languageSelectionBox by firing the `cancelLanguageSelect` event + * + * @protected + * @method _cancelLanguageSelection + */ + _cancelLanguageSelection: function () { + /** + * Fired when language selection is being cancelled + * + * @event cancelLanguageSelection + */ + this.fire(CANCEL_LANGUAGE_SELECTION); + }, + + /** + * Confirm the languageSelectionBox's selection by firing the `languageSelected` event + * + * @protected + * @method _confirmLanguageSelection + */ + _confirmLanguageSelection: function () { + var data = { + baseTranslation: this.get('baseTranslation'), + selectedLanguageCode: this.get('selectedLanguageCode'), + selectedBaseLanguageCode: this.get('selectedBaseLanguageCode') + }; + + /** + * Fired when language selection is being confirmed + * + * @event languageSelected + * @param {Object} data + * @param {Boolean} data.baseTranslation defines if translation will be basing on already existing language + * @param {String} data.selectedLanguageCode language code of selected language + * @param {Null|String} data.selectedBaseLanguageCode language on which translation will be based + */ + this.fire(LANGUAGE_SELECTED, data); + }, + + /** + * Returns list of languages that are available but content doesn't have translation + * in these languages + * + * @protected + * @method _getNewTranslations + * @return {Array} + */ + _getNewTranslations: function () { + var translations = Y.Object.keys(this.get('availableTranslations')), + existingTranslations = this.get('existingTranslations'); + + return Y.Array.reject(translations, function (value) { + return existingTranslations.indexOf(value) >= 0; + }); + }, + }, { + ATTRS: { + /** + * Title of the languageSelectionBox + * + * @attribute title + * @default "" + * @type {String} + */ + title: { + value: "", + }, + + /** + * languageSelected event handler + * + * @attribute languageSelectedHandler + * @type {Function|Null} + * @default null + */ + languageSelectedHandler: { + value: null, + }, + + /** + * cancelLanguageSelection event handler + * + * @attribute cancelLanguageSelectionHandler + * @type {Function|Null} + * @default null + */ + cancelLanguageSelectionHandler: { + value: null, + }, + + /** + * List of available new translations + * + * @attribute newTranslations + * @type {Array} + */ + newTranslations: { + getter: '_getNewTranslations' + }, + + /** + * Already existing translations of content + * + * @attribute existingTranslations + * @type {Array|Null} + * @default null + */ + existingTranslations: { + value: null + }, + + /** + * Enables or disables possibility of basing new translation on already existing one + * + * @attribute canBaseTranslation + * @type {Boolean} + * @default true + */ + canBaseTranslation: { + value: true + }, + + /** + * Defines if new translation will be based on already existing one + * + * @attribute baseTranslation + * @type {Boolean} + * @default false + */ + baseTranslation: { + value: false + }, + + /** + * Selected language from new translations list + * + * @attribute selectedLanguageCode + * @type {string|Null} + * @default null + */ + selectedLanguageCode: { + value: null + }, + + /** + * Selected language from existing translations list on which + * new translation will be based + * + * @attribute selectedBaseLanguageCode + * @type {string|Null} + * @default null + */ + selectedBaseLanguageCode: { + value: null + } + }, + }); +}); diff --git a/Resources/public/js/views/services/ez-contenteditviewservice.js b/Resources/public/js/views/services/ez-contenteditviewservice.js index c8ead89cb..8dd5b29fa 100644 --- a/Resources/public/js/views/services/ez-contenteditviewservice.js +++ b/Resources/public/js/views/services/ez-contenteditviewservice.js @@ -24,14 +24,18 @@ YUI.add('ez-contenteditviewservice', function (Y) { Y.eZ.ContentEditViewService = Y.Base.create('contentEditViewService', Y.eZ.ViewService, [], { initializer: function () { this.on('*:closeView', this._handleCloseView); - this.after('*:requestChange', this._setLanguageCode); + this.after('*:requestChange', function () { + this._setLanguageCode(); + this._setBaseLanguageCode(); + }); this._setLanguageCode(); + this._setBaseLanguageCode(); }, /** * Loads the content, the main location, the content type and the owner - * of the currently edited content + * of the currently edited content, after that it sets version fields * * @method _load * @protected @@ -40,16 +44,26 @@ YUI.add('ez-contenteditviewservice', function (Y) { _load: function (next) { var request = this.get('request'), service = this, - languageCode = this.get('languageCode'); + languageCode = this.get('languageCode'), + baseLanguageCode = this.get('baseLanguageCode'), + languageCodeForLoadContent = baseLanguageCode ? baseLanguageCode : languageCode; this.get('version').reset(); - this._loadContent(request.params.id, languageCode, function () { + this._loadContent(request.params.id, languageCodeForLoadContent, function () { var tasks, - version = service.get('version'), content = service.get('content'), + translationExists, resources; - version.set('fields', content.get('fields')); + translationExists = service._checkIfTranslationExists(content, languageCodeForLoadContent); + + if (baseLanguageCode && !translationExists) { + service._error( + "Could not load the content with id '" + content.get('contentId') + + "' and languageCode '" + baseLanguageCode + "'" + ); + return; + } resources = content.get('resources'); @@ -60,11 +74,113 @@ YUI.add('ez-contenteditviewservice', function (Y) { service._loadContentType(resources.ContentType, tasks.add()); tasks.done(function () { + service._setVersionFields(content, translationExists); next(service); }); }); }, + /** + * Checks if given languageCode is included in translations list of given content + * + * @method _checkIfTranslationExists + * @private + * @param {Y.eZ.Content} content + * @param {String} languageCode + * @return {Boolean} + */ + _checkIfTranslationExists: function (content, languageCode) { + var translationExists; + + translationExists = Y.Array.find( + content.get('currentVersion').getTranslationsList(), + function (translation) { + return (translation === languageCode); + } + ); + + return !!translationExists; + }, + + /** + * Sets fields of edited version + * + * @method _setVersionFields + * @private + * @param {Y.eZ.Content} content + * @param {Boolean} translationExists defines if fields will be set for existing translation + */ + _setVersionFields: function (content, translationExists) { + var fields, + version = this.get('version'); + + fields = this._getFieldsForEdit(content, translationExists); + + version.set('fields', fields); + }, + + /** + * Returns object containing fields definitions for given content. + * If editing content in context of creating new translation it returns fields based on default field + * defitnitions of ContentType if no baseLanguageCode was set, otherwise if baseLanguageCode was set + * it returns fields cloned from loaded content with setting proper languageCode. + * If editing content in context of editing existing translation it returns fields from loaded content + * which is default behaviour. + * + * @method _getFieldsForEdit + * @private + * @param {Y.eZ.Content} content + * @param {Boolean} translationExists + * @return {Object} + */ + _getFieldsForEdit: function (content, translationExists) { + var baseLanguageCode = this.get('baseLanguageCode'), + languageCode = this.get('languageCode'), + contentFields = content.get('fields'), + setDefaultFields = false, + fields; + + if (!baseLanguageCode && !translationExists) { + setDefaultFields = true; + } + + if (setDefaultFields) { + fields = this._getDefaultFields(languageCode); + } else { + fields = Y.clone(contentFields); + + Y.each(fields, function (field) { + field.languageCode = languageCode; + }); + } + + return fields; + }, + + /** + * Returns collection of default fields for ContentType of edited content and sets + * for them given languageCode + * + * @method _getDefaultFields + * @private + * @param {String} languageCode + * @return {Object} + */ + _getDefaultFields: function (languageCode) { + var contentType = this.get('contentType'), + defaultFields = {}; + + Y.Object.each(contentType.get('fieldDefinitions'), function (fieldDef, identifier) { + defaultFields[identifier] = { + fieldDefinitionIdentifier: identifier, + fieldValue: fieldDef.defaultValue, + languageCode: languageCode + }; + }); + + return defaultFields; + }, + /** * Loads a content by its id and language code * @@ -184,6 +300,20 @@ YUI.add('ez-contenteditviewservice', function (Y) { this.set('languageCode', this.get('request').params.languageCode); }, + /** + * Set baseLanguageCode attribute basing on parameter from request + * + * @method _setBaseLanguageCode + * @protected + */ + _setBaseLanguageCode: function () { + if (this.get('request').params.baseLanguageCode) { + this.set('baseLanguageCode', this.get('request').params.baseLanguageCode); + } else { + this.reset('baseLanguageCode'); + } + }, + /** * Returns uri for user redirection. * @@ -300,7 +430,18 @@ YUI.add('ez-contenteditviewservice', function (Y) { * @attribute languageCode * @type String */ - languageCode: {} + languageCode: {}, + + /** + * The language code on which new translation is basing. + * + * @attribute baseLanguageCode + * @default null + * @type String + */ + baseLanguageCode: { + value: null + } } }); }); diff --git a/Resources/public/js/views/services/ez-languageselectionboxviewservice.js b/Resources/public/js/views/services/ez-languageselectionboxviewservice.js new file mode 100644 index 000000000..04b871fe8 --- /dev/null +++ b/Resources/public/js/views/services/ez-languageselectionboxviewservice.js @@ -0,0 +1,55 @@ +/* + * Copyright (C) eZ Systems AS. All rights reserved. + * For full copyright and license information view LICENSE file distributed with this source code. + */ +YUI.add('ez-languageselectionboxviewservice', function (Y) { + "use strict"; + /** + * Provides the language selection box view service class + * + * @module ez-languageselectionboxviewservice + */ + + /** + * The language selection box view service + * + * @namespace eZ + * @class LanguageSelectionBoxViewService + * @constructor + * @extends eZ.TemplateBasedView + */ + Y.eZ.LanguageSelectionBoxViewService = Y.Base.create('languageSelectionBoxViewService', Y.eZ.ViewService, [], { + getViewParameters: function () { + var config = Y.merge(this.get('config')); + + config.availableTranslations = this.get('availableTranslations'); + + return config; + } + }, { + ATTRS: { + /** + * List of available translations. List contains language objects. + * + * @attribute availableTranslations + * @type {Object} + */ + availableTranslations: { + value: { + 'eng-GB': {id: 2, languageCode: 'eng-GB', name: 'English (United Kingdom)', enabled: true}, + 'nno-NO': {id: 4, languageCode: 'nno-NO', name: 'Norwegian (Nynorsk)', enabled: true}, + 'chi-CN': {id: 8, languageCode: 'chi-CN', name: 'Simplified Chinese', enabled: true}, + 'cze-CZ': {id: 16, languageCode: 'cze-CZ', name: 'Czech', enabled: true}, + 'eng-US': {id: 32, languageCode: 'eng-US', name: 'English (American)', enabled: true}, + 'esl-ES': {id: 64, languageCode: 'esl-ES', name: 'Spanish (Spain)', enabled: true}, + 'fre-FR': {id: 128, languageCode: 'fre-FR', name: 'French (France)', enabled: true}, + 'ita-IT': {id: 256, languageCode: 'ita-IT', name: 'Italian', enabled: true}, + 'jpn-JP': {id: 512, languageCode: 'jpn-JP', name: 'Japanese', enabled: true}, + 'swe-SE': {id: 1024, languageCode: 'swe-SE', name: 'Swedish', enabled: true}, + 'pol-PL': {id: 2048, languageCode: 'pol-PL', name: 'Polish', enabled: true}, + 'ger-DE': {id: 4096, languageCode: 'ger-DE', name: 'German', enabled: true}, + } + }, + } + }); +}); diff --git a/Resources/public/js/views/services/ez-locationviewviewservice.js b/Resources/public/js/views/services/ez-locationviewviewservice.js index f956f8196..d603ec2c2 100644 --- a/Resources/public/js/views/services/ez-locationviewviewservice.js +++ b/Resources/public/js/views/services/ez-locationviewviewservice.js @@ -26,6 +26,7 @@ YUI.add('ez-locationviewviewservice', function (Y) { this.on('*:editAction', this._editContent); this.on('*:sendToTrashAction', this._sendContentToTrashConfirmBox); this.on('*:moveAction', this._selectLocation); + this.on('*:translateContent', this._translateContent); this.after('*:requestChange', this._setLanguageCode); this._setLanguageCode(); @@ -207,6 +208,32 @@ YUI.add('ez-locationviewviewservice', function (Y) { }); }, + /** + * translate event handler, makes the application to navigate to edit content available + * in the facade with given language and base language + * + * @method _translateContent + * @protected + * @param {EventFacade} e + */ + _translateContent: function (e) { + var app = this.get('app'), + routeName = 'editContent', + routeParams = { + id: e.content.get('id'), + languageCode: e.toLanguageCode, + }; + + if (e.baseLanguageCode) { + routeParams.baseLanguageCode = e.baseLanguageCode; + routeName = 'translateContent'; + } + + app.navigate( + app.routeUri(routeName, routeParams) + ); + }, + /** * Fire 'notify' event * diff --git a/Resources/public/templates/languageselectionbox.hbt b/Resources/public/templates/languageselectionbox.hbt new file mode 100644 index 000000000..d2a140617 --- /dev/null +++ b/Resources/public/templates/languageselectionbox.hbt @@ -0,0 +1,32 @@ + +

{{ title }}

+ + + +
+
+ +
+ +
+

Select a base language:

+
    + {{#each existingTranslations}} +
  • {{ this }}
  • + {{/each}} +
+
+
+ +

+ Cancel + +

\ No newline at end of file diff --git a/Resources/public/templates/translateaction.hbt b/Resources/public/templates/translateaction.hbt index 8c441afee..7e9a8be6c 100644 --- a/Resources/public/templates/translateaction.hbt +++ b/Resources/public/templates/translateaction.hbt @@ -24,4 +24,5 @@ + diff --git a/Resources/views/PlatformUI/shell.html.twig b/Resources/views/PlatformUI/shell.html.twig index 91619a75c..dcac8677e 100644 --- a/Resources/views/PlatformUI/shell.html.twig +++ b/Resources/views/PlatformUI/shell.html.twig @@ -28,9 +28,10 @@
{{ 'loading.application'|trans }}
-
+
+
@@ -71,6 +72,11 @@ "ezcountry": {{parameters.countriesInfo|json_encode|raw}} } }, + "translateContent": { + "fieldEditViews": { + "ezcountry": {{parameters.countriesInfo|json_encode|raw}} + } + }, "editContent": { "fieldEditViews": { "ezcountry": {{parameters.countriesInfo|json_encode|raw}}, diff --git a/Tests/js/apps/plugins/assets/ez-languageselectionboxplugin-tests.js b/Tests/js/apps/plugins/assets/ez-languageselectionboxplugin-tests.js new file mode 100644 index 000000000..58d6845d0 --- /dev/null +++ b/Tests/js/apps/plugins/assets/ez-languageselectionboxplugin-tests.js @@ -0,0 +1,79 @@ +/* + * Copyright (C) eZ Systems AS. All rights reserved. + * For full copyright and license information view LICENSE file distributed with this source code. + */ +YUI.add('ez-languageselectionboxplugin-tests', function (Y) { + var registerTest, + eventsTest, + Assert = Y.Assert; + + eventsTest = new Y.Test.Case({ + name: 'eZ Language Selection Box Plugin event tests', + + setUp: function () { + var that = this, + App = Y.Base.create('testApp', Y.Base, [], { + showSideView: function (name, config) { + that.showSideViewName = name; + that.showSideViewConfig = config; + }, + hideSideView: function (name) { + that.hideSideViewName = name; + }, + }); + this.app = new App(); + this.plugin = new Y.eZ.Plugin.LanguageSelectionBox({ + host: this.app, + }); + }, + + tearDown: function () { + this.plugin.destroy(); + delete this.plugin; + this.app.destroy(); + delete this.app; + delete this.showSideViewName; + delete this.showSideViewConfig; + delete this.hideSideViewName; + }, + + "Should show the language selection box side view": function () { + var eventConfig = {}; + + this.app.fire('whatever:languageSelect', {config: eventConfig}); + Assert.areEqual( + "languageSelectionBox", this.showSideViewName, + "The language selection box should have been shown" + ); + Assert.areEqual( + eventConfig, this.showSideViewConfig, + "The language selection box should have been shown with the event config" + ); + }, + + "Should hide the language selection box side view (languageSelected)": function () { + this.app.fire('whatever:languageSelected'); + Assert.areEqual( + "languageSelectionBox", this.hideSideViewName, + "The language selection box should have been hidden" + ); + }, + + "Should hide the language selection box side view (cancelLanguageSelection)": function () { + this.app.fire('whatever:cancelLanguageSelection'); + Assert.areEqual( + "languageSelectionBox", this.hideSideViewName, + "The language selection box should have been hidden" + ); + }, + + }); + + registerTest = new Y.Test.Case(Y.eZ.Test.PluginRegisterTest); + registerTest.Plugin = Y.eZ.Plugin.LanguageSelectionBox; + registerTest.components = ['platformuiApp']; + + Y.Test.Runner.setName("eZ Language Selection Box Plugin tests"); + Y.Test.Runner.add(eventsTest); + Y.Test.Runner.add(registerTest); +}, '', {requires: ['test', 'base', 'ez-languageselectionboxplugin', 'ez-pluginregister-tests']}); diff --git a/Tests/js/apps/plugins/ez-languageselectionboxplugin.html b/Tests/js/apps/plugins/ez-languageselectionboxplugin.html new file mode 100644 index 000000000..62b69f981 --- /dev/null +++ b/Tests/js/apps/plugins/ez-languageselectionboxplugin.html @@ -0,0 +1,44 @@ + + + +eZ Language Selection Box Plugin tests + + + +
+ + + + + + + diff --git a/Tests/js/views/actions/assets/ez-translateactionview-tests.js b/Tests/js/views/actions/assets/ez-translateactionview-tests.js index 325d98193..ae114a099 100644 --- a/Tests/js/views/actions/assets/ez-translateactionview-tests.js +++ b/Tests/js/views/actions/assets/ez-translateactionview-tests.js @@ -3,7 +3,7 @@ * For full copyright and license information view LICENSE file distributed with this source code. */ YUI.add('ez-translateactionview-tests', function (Y) { - var viewTest, eventTest, renderTest, hideTest, hintTest, + var viewTest, eventTest, renderTest, domEventTest, hideTest, hintTest, Mock = Y.Mock, Assert = Y.Assert; viewTest = new Y.Test.Case( @@ -114,6 +114,125 @@ YUI.add('ez-translateactionview-tests', function (Y) { }, }); + domEventTest = new Y.Test.Case({ + name: 'eZ Translate Action View DOM event test', + + setUp: function () { + this.contentMock = new Mock(); + this.locationMock = new Mock(); + this.versionMock = new Mock(); + this.translationsList = ['eng-GB', 'pol-PL', 'ger-DE']; + + Mock.expect(this.contentMock, { + method: 'get', + args: ['currentVersion'], + returns: this.versionMock + }); + Mock.expect(this.versionMock, { + method: 'getTranslationsList', + returns: this.translationsList + }); + Mock.expect(this.locationMock, { + method: 'toJSON', + returns: {} + }); + Mock.expect(this.contentMock, { + method: 'toJSON', + returns: {} + }); + + this.view = new Y.eZ.TranslateActionView({ + container: '.container', + actionId: 'translate', + label: 'Translations', + disabled: false, + content: this.contentMock, + location: this.locationMock + }); + + this.view.render(); + }, + + tearDown: function () { + this.view.destroy(); + delete this.view; + }, + + 'Should fire languageSelect event': function () { + var that = this, + newTranslationButton = this.view.get('container').one('.ez-newtranslation-button'), + languageSelectFired = false; + + this.view.on('languageSelect', function (e) { + languageSelectFired = true; + + Assert.areSame( + that.translationsList, + e.config.existingTranslations, + 'The config of should pass the proper lista of translations' + ); + Assert.isTrue( + e.config.canBaseTranslation, + 'The canBaseTranslation in config should be set to true' + ); + }); + + newTranslationButton.simulateGesture('tap', function () { + that.resume(function () { + Assert.isTrue( + languageSelectFired, + "The languageSelect event should have been fired" + ); + }); + }); + this.wait(); + }, + + "Should fire translateContent event": function () { + var that = this, + newTranslationButton = this.view.get('container').one('.ez-newtranslation-button'), + translateContentFired = false, + selectedLanguageCode = 'fre-FR', + selectedBaseLanguageCode = 'eng-GB', + baseTranslation = true; + + this.view.on('languageSelect', function (e) { + var config = { + selectedLanguageCode: selectedLanguageCode, + selectedBaseLanguageCode: selectedBaseLanguageCode, + baseTranslation: baseTranslation, + }; + + e.config.languageSelectedHandler(config); + }); + + this.view.on('translateContent', function (e) { + translateContentFired = true; + + Assert.areSame( + selectedLanguageCode, + e.toLanguageCode, + 'The selectedLanguageCode should match toLanguageCode in event facade' + ); + Assert.areSame( + selectedBaseLanguageCode, + e.baseLanguageCode, + 'The selectedBaseLanguageCode should match baseLanguageCode in event facade' + ); + }); + + newTranslationButton.simulateGesture('tap', function () { + that.resume(function () { + Assert.isTrue( + translateContentFired, + "The translateContent event should have been fired" + ); + }); + }); + this.wait(); + } + }); + hideTest = new Y.Test.Case({ name: 'eZ Translate Action View hide test', @@ -252,6 +371,7 @@ YUI.add('ez-translateactionview-tests', function (Y) { Y.Test.Runner.add(viewTest); Y.Test.Runner.add(eventTest); Y.Test.Runner.add(renderTest); + Y.Test.Runner.add(domEventTest); Y.Test.Runner.add(hideTest); Y.Test.Runner.add(hintTest); }, '', {requires: ['test', 'ez-translateactionview', 'ez-genericbuttonactionview-tests', 'node-event-simulate']}); diff --git a/Tests/js/views/actions/ez-translateactionview.html b/Tests/js/views/actions/ez-translateactionview.html index 058f49052..d43b71ed3 100644 --- a/Tests/js/views/actions/ez-translateactionview.html +++ b/Tests/js/views/actions/ez-translateactionview.html @@ -19,7 +19,9 @@ {{/if}}
-
+
+ +
diff --git a/Tests/js/views/assets/ez-languageselectionboxview-tests.js b/Tests/js/views/assets/ez-languageselectionboxview-tests.js new file mode 100644 index 000000000..65b77a98d --- /dev/null +++ b/Tests/js/views/assets/ez-languageselectionboxview-tests.js @@ -0,0 +1,500 @@ +/* + * Copyright (C) eZ Systems AS. All rights reserved. + * For full copyright and license information view LICENSE file distributed with this source code. + */ +YUI.add('ez-languageselectionboxview-tests', function (Y) { + var renderTest, domEventTest, eventHandlersTest, confirmButtonStateTest, eventsTest, + Assert = Y.Assert, + availableTranslations = { + 'eng-GB': {id: 2, languageCode: 'eng-GB', name: 'English (United Kingdom)', enabled: true}, + 'nno-NO': {id: 4, languageCode: 'nno-NO', name: 'Norwegian (Nynorsk)', enabled: true}, + 'fre-FR': {id: 128, languageCode: 'fre-FR', name: 'French (France)', enabled: true}, + 'pol-PL': {id: 2048, languageCode: 'pol-PL', name: 'Polish', enabled: true}, + 'ger-DE': {id: 4096, languageCode: 'ger-DE', name: 'German', enabled: true}, + }; + + renderTest = new Y.Test.Case({ + name: "eZ Language Selection Box View render test", + + setUp: function () { + this.title = 'Artur Boruc'; + this.existingTranslations = ['eng-GB', 'nno-NO']; + this.expectedNewTranslations = ['fre-FR', 'pol-PL', 'ger-DE']; + this.canBaseTranslation = true; + this.view = new Y.eZ.LanguageSelectionBoxView({ + container: '.container', + title: this.title, + existingTranslations: this.existingTranslations, + availableTranslations: availableTranslations, + canBaseTranslation: this.canBaseTranslation + }); + }, + + tearDown: function () { + this.view.destroy(); + delete this.view; + }, + + "Should use a template": function () { + var templateCalled = false, + origTpl; + + origTpl = this.view.template; + this.view.template = function () { + templateCalled = true; + return origTpl.apply(this, arguments); + }; + this.view.render(); + Assert.isTrue(templateCalled, "The template should have used to render the view"); + }, + + "Test available variables in the template": function () { + var origTpl = this.view.template, + that = this; + + this.view.template = function (variables) { + Assert.isObject(variables, "The template should receive some variables"); + Assert.areEqual(4, Y.Object.keys(variables).length, "The template should receive 4 variables"); + Assert.areSame( + that.title, variables.title, + "The title should be available in the template" + ); + Assert.isArray( + variables.newTranslations, + "The array containing new translations should be available in the template" + ); + Assert.areSame( + that.existingTranslations, variables.existingTranslations, + "The array containing existing translations should be available in the template" + ); + Assert.areSame( + that.canBaseTranslation, variables.canBaseTranslation, + "The canBaseTranslation should be available in the template" + ); + return origTpl.apply(this, arguments); + }; + this.view.render(); + }, + }); + + domEventTest = new Y.Test.Case({ + name: "eZ Language Selection Box View DOM event test", + + setUp: function () { + this.title = 'Miroslav Klose'; + this.existingTranslations = ['eng-GB', 'nno-NO']; + this.expectedNewTranslations = ['fre-FR', 'pol-PL', 'ger-DE']; + this.canBaseTranslation = true; + this.view = new Y.eZ.LanguageSelectionBoxView({ + container: '.container', + title: this.title, + existingTranslations: this.existingTranslations, + availableTranslations: availableTranslations, + canBaseTranslation: this.canBaseTranslation + }); + }, + + tearDown: function () { + this.view.destroy(); + delete this.view; + }, + + "Should fire the cancelLanguageSelection event": function () { + var cancel = this.view.get('container').one('.ez-languageselectionbox-close'), + that = this, + cancelFired = false; + + this.view.on('cancelLanguageSelection', function (e) { + cancelFired = true; + }); + cancel.simulateGesture('tap', function () { + that.resume(function () { + Assert.isTrue( + cancelFired, + "The cancelLanguageSelection event should have been fired" + ); + }); + }); + this.wait(); + }, + + "Should fire the languageSelected event": function () { + var conf = this.view.get('container').one('.ez-languageselectionbox-confirm'), + selectedLanguageCode = 'pol-PL', + that = this, + languageSelectedFired = false; + + this.view._set('selectedLanguageCode', selectedLanguageCode); + this.view.on('languageSelected', function (e) { + languageSelectedFired = true; + }); + conf.simulateGesture('tap', function () { + that.resume(function () { + Assert.isTrue( + languageSelectedFired, + "The languageSelected event should have been fired" + ); + }); + }); + this.wait(); + }, + + _attributeChangeTest: function (element, attributeName, expectedAttributeValue) { + var attributeChangeFired = false, + that = this; + + this.view.on(attributeName + 'Change', function (e) { + attributeChangeFired = true; + }); + element.simulateGesture('tap', function () { + that.resume(function () { + Assert.isTrue( + attributeChangeFired, + "The " + attributeName + "Change event should have been fired" + ); + Assert.areSame( + that.view.get(attributeName), + expectedAttributeValue, + "The " + attributeName + " attribute should be the same which was selected" + ); + }); + }); + this.wait(); + }, + + "Should set the selectedLanguageCode attribute": function () { + var selector = '.ez-new-translation', + element = this.view.get('container').one(selector), + attributeName = 'selectedLanguageCode', + expectedAttributeValue = element.getAttribute('data-languagecode'); + + this._attributeChangeTest(element, attributeName, expectedAttributeValue); + }, + + "Should set the selectedBaseLanguageCode attribute": function () { + var selector = '.ez-base-translation', + element = this.view.get('container').one(selector), + attributeName = 'selectedBaseLanguageCode', + expectedAttributeValue = element.getAttribute('data-languagecode'); + + this._attributeChangeTest(element, attributeName, expectedAttributeValue); + }, + + "Should set the baseTranslation attribute": function () { + var attributeChangeFired = false, + checkbox = this.view.get('container').one('.ez-base-translation-checkbox'), + that = this; + + this.view.on('baseTranslationChange', function (e) { + attributeChangeFired = true; + }); + checkbox.simulateGesture('tap', function (e) { + that.resume(function () { + Assert.isTrue( + attributeChangeFired, + "The baseTranslationChange event should have been fired" + ); + Assert.areSame( + that.view.get('baseTranslation'), + checkbox.get('checked'), + "The baseTranslation attribute should be proper for checkbox state" + ); + }); + }); + this.wait(); + }, + }); + + eventHandlersTest = new Y.Test.Case({ + name: "eZ Language Selection Box View event handlers tests", + + setUp: function () { + this.title = 'Unforgiven'; + this.existingTranslations = ['eng-GB', 'nno-NO']; + this.expectedNewTranslations = ['fre-FR', 'pol-PL', 'ger-DE']; + this.canBaseTranslation = true; + this.view = new Y.eZ.LanguageSelectionBoxView({ + container: '.container', + title: this.title, + existingTranslations: this.existingTranslations, + availableTranslations: availableTranslations, + canBaseTranslation: this.canBaseTranslation + }); + this.handler1 = false; + this.handler2 = false; + }, + + tearDown: function () { + this.view.destroy(); + delete this.view; + }, + + _eventHandler1: function () { + this.handler1 = true; + }, + + _eventHandler2: function () { + this.handler2 = true; + }, + + "Should set the languageSelected event handler": function () { + this.view.set('languageSelectedHandler', Y.bind(this._eventHandler1, this)); + this.view.fire('languageSelected'); + + Assert.isTrue( + this.handler1, + "The languageSelectedHandler should have been called" + ); + }, + + "Should set the cancelLanguageSelection event handler": function () { + this.view.set('cancelLanguageSelectionHandler', Y.bind(this._eventHandler1, this)); + this.view.fire('cancelLanguageSelection'); + + Assert.isTrue( + this.handler1, + "The cancelLanguageSelectionHandler should have been called" + ); + }, + + "Should update the languageSelected event handler": function () { + this.view.set('languageSelectedHandler', Y.bind(this._eventHandler1, this)); + this.view.set('languageSelectedHandler', Y.bind(this._eventHandler2, this)); + this.view.fire('languageSelected'); + + Assert.isFalse( + this.handler1, + "The first languageSelectedHandler should not have been called" + ); + Assert.isTrue( + this.handler2, + "The second languageSelectedHandler should have been called" + ); + }, + + "Should update the cancelLanguageSelection event handler": function () { + this.view.set('cancelLanguageSelectionHandler', Y.bind(this._eventHandler1, this)); + this.view.set('cancelLanguageSelectionHandler', Y.bind(this._eventHandler2, this)); + this.view.fire('cancelLanguageSelection'); + + Assert.isFalse( + this.handler1, + "The first cancelLanguageSelectionHandler should not have been called" + ); + Assert.isTrue( + this.handler2, + "The second cancelLanguageSelectionHandler should have been called" + ); + }, + }); + + eventsTest = new Y.Test.Case({ + name: "eZ Language Selection Box View events tests", + + setUp: function () { + this.title = 'Nothing Else Matters'; + this.existingTranslations = ['eng-GB', 'nno-NO']; + this.expectedNewTranslations = ['fre-FR', 'pol-PL', 'ger-DE']; + this.canBaseTranslation = true; + this.view = new Y.eZ.LanguageSelectionBoxView({ + container: '.container', + title: this.title, + existingTranslations: this.existingTranslations, + availableTranslations: availableTranslations, + canBaseTranslation: this.canBaseTranslation, + }); + this.defaultBaseTranslation = this.view.get('baseTranslation'); + }, + + tearDown: function () { + this.view.destroy(); + delete this.view; + }, + + "Should reset attributes and render the view": function () { + this.view.set('baseTranslation', true); + this.view.set('selectedLanguageCode', 'pol-PL'); + this.view.set('selectedBaseLanguageCode', 'eng-GB'); + + this.view.set('active', true); + + Assert.areSame( + this.defaultBaseTranslation, + this.view.get('baseTranslation'), + "The canBaseTranslation attribute should have been reseted" + ); + Assert.isNull( + this.view.get('selectedLanguageCode'), + "The selectedLanguageCode attribute should have been reseted" + ); + Assert.isNull( + this.view.get('selectedBaseLanguageCode'), + "The selectedBaseLanguageCode attribute should have been reseted" + ); + }, + + "Should not reset attributes nor render the view": function () { + var baseTranslation = true, + selectedLanguageCode = 'pol-PL', + selectedBaseLanguageCode = 'eng-GB'; + + this.view.set('baseTranslation', baseTranslation); + this.view.set('selectedLanguageCode', selectedLanguageCode); + this.view.set('selectedBaseLanguageCode', selectedBaseLanguageCode); + + this.view.set('active', false); + + Assert.areSame( + baseTranslation, + this.view.get('baseTranslation'), + "The baseTranslation attribute should not have been reseted" + ); + Assert.areSame( + selectedLanguageCode, + this.view.get('selectedLanguageCode'), + "The selectedNewTranslation attribute should not have been reseted" + ); + Assert.areSame( + selectedBaseLanguageCode, + this.view.get('selectedBaseLanguageCode'), + "The selectedBaseTranslation attribute should not have been reseted" + ); + }, + + "Should show base translations section": function () { + var c = this.view.get('container'); + + this.view.set('canBaseTranslation', true); + + Assert.isTrue( + c.hasClass('is-base-translation-allowed'), + "The event should have been fired" + ); + }, + + "Should hide base translations section": function () { + var c = this.view.get('container'); + + this["Should show base translations section"](); + + this.view.set('canBaseTranslation', false); + + Assert.isFalse( + c.hasClass('is-base-translation-allowed'), + "The event should have been fired" + ); + }, + + _highlightSelectedLanguageTest: function (section, languageCode) { + var c = this.view.get('container'), + highlightClass = 'is-translation-selected'; + + Assert.isTrue( + c.one('.ez-' + section + '-translation[data-languagecode="' + languageCode + '"]') + .hasClass(highlightClass), + "The selected translation should have been highlighted" + ); + Assert.areEqual( + 1, + c.all('.ez-' + section + '-translation.' + highlightClass).size(), + 'There should be only one translation highlighted' + ); + }, + + "Should highlight selected language": function () { + var selectedLanguageCode1 = 'pol-PL', + selectedLanguageCode2 = 'ger-DE'; + + this.view.set('active', true); + this.view.set('selectedLanguageCode', selectedLanguageCode1); + this.view.set('selectedLanguageCode', selectedLanguageCode2); + + this._highlightSelectedLanguageTest('new', selectedLanguageCode2); + }, + + "Should highlight selected base translation": function () { + var selectedBaseLanguageCode1 = 'nno-NO', + selectedBaseLanguageCode2 = 'eng-GB'; + + this.view.set('active', true); + this.view.set('selectedBaseLanguageCode', selectedBaseLanguageCode1); + this.view.set('selectedBaseLanguageCode', selectedBaseLanguageCode2); + + this._highlightSelectedLanguageTest('base', selectedBaseLanguageCode2); + }, + + "Should show list of base translations": function () { + var c = this.view.get('container'); + + this.view.set('active', true); + this.view.set('baseTranslation', true); + + Assert.isTrue( + c.hasClass('is-base-translations-list-visible'), + "The list of base translations should be visible" + ); + }, + + "Should hide list of base translations": function () { + var c = this.view.get('container'); + + this["Should show list of base translations"](); + this.view.set('baseTranslation', false); + + Assert.isFalse( + c.hasClass('is-base-translations-list-visible'), + "The list of base translations should not be visible" + ); + }, + }); + + confirmButtonStateTest = new Y.Test.Case({ + name: "eZ Language Selection Box View confirm button state test", + + setUp: function () { + this.title = 'Robert Lewandowski'; + this.existingTranslations = ['eng-GB', 'nno-NO']; + this.expectedNewTranslations = ['fre-FR', 'pol-PL', 'ger-DE']; + this.canBaseTranslation = true; + this.view = new Y.eZ.LanguageSelectionBoxView({ + container: '.container', + title: this.title, + existingTranslations: this.existingTranslations, + availableTranslations: availableTranslations, + canBaseTranslation: this.canBaseTranslation + }); + this.view.render(); + }, + + tearDown: function () { + this.view.destroy(); + delete this.view; + }, + + "Should enable the confirm button": function () { + this.view._set('selectedLanguageCode', 'Kamil Glik'); + + Assert.isFalse( + this.view.get('container').one('.ez-languageselectionbox-confirm').get('disabled'), + "The confirm button should be enabled" + ); + }, + + "Should disabled the confirm button": function () { + this["Should enable the confirm button"](); + this.view._set('selectedLanguageCode', null); + + Assert.isTrue( + this.view.get('container').one('.ez-languageselectionbox-confirm').get('disabled'), + "The confirm button should be disabled" + ); + } + }); + + Y.Test.Runner.setName("eZ Language Selection Box View tests"); + Y.Test.Runner.add(renderTest); + Y.Test.Runner.add(domEventTest); + Y.Test.Runner.add(eventHandlersTest); + Y.Test.Runner.add(eventsTest); + Y.Test.Runner.add(confirmButtonStateTest); +}, '', {requires: ['test', 'base', 'view', 'node-event-simulate', 'ez-languageselectionboxview']}); diff --git a/Tests/js/views/ez-languageselectionboxview.html b/Tests/js/views/ez-languageselectionboxview.html new file mode 100644 index 000000000..3e4b9b09c --- /dev/null +++ b/Tests/js/views/ez-languageselectionboxview.html @@ -0,0 +1,86 @@ + + + +eZ Language Selection Box view tests + + + +
+ + + + + + + + diff --git a/Tests/js/views/services/assets/ez-contenteditviewservice-tests.js b/Tests/js/views/services/assets/ez-contenteditviewservice-tests.js index 85c1ea558..2e3471350 100644 --- a/Tests/js/views/services/assets/ez-contenteditviewservice-tests.js +++ b/Tests/js/views/services/assets/ez-contenteditviewservice-tests.js @@ -12,14 +12,32 @@ YUI.add('ez-contenteditviewservice-tests', function (Y) { setUp: function () { this.viewLocationRoute = '/view/something'; this.locationId = 'something'; - this.languageCode = 'pol-PL'; + this.versionTranslationsList = ['eng-GB', 'pol-PL']; + this.languageCode = 'eng-GB'; + this.baseLanguageCode = 'pol-PL'; + this.newLanguageCode = 'ger-DE'; this.request = {params: {id: "/api/ezp/v2/content/objects/59", languageCode: this.languageCode}}; + this.requestBaseLanguage = { + params: { + id: "/api/ezp/v2/content/objects/59", + languageCode: this.newLanguageCode, + baseLanguageCode: this.baseLanguageCode + } + }; this.capiMock = new Y.Test.Mock(); this.resources = { 'Owner': '/api/ezp/v2/user/users/14', 'MainLocation': '/api/ezp/v2/content/locations/1/2/61', 'ContentType': '/api/ezp/v2/content/types/23' }; + this.fieldDefinitions = { + 'name': { + "id": 230, + "identifier": "name", + "fieldType": "ezstring", + "defaultValue": 'default name' + } + }; this.mocks = ['content', 'mainLocation', 'contentType', 'owner']; this.content = new Y.Test.Mock(); @@ -27,11 +45,23 @@ YUI.add('ez-contenteditviewservice-tests', function (Y) { this.contentType = new Y.Test.Mock(); this.owner = new Y.Test.Mock(); this.version = new Y.Test.Mock(); + this.contentCurrentVersion = new Y.Test.Mock(); this.app = new Y.Test.Mock(); - this.fields = {}; + this.fields = { + name: { + languageCode: this.languageCode, + fieldValue: 'Didier Drogba' + } + }; + this.fieldsForBaseTranslation = { + name: { + languageCode: this.languageCode, + fieldValue: 'Roman Dmowski' + } + }; }, - "Should load content in active language": function () { + "Should load content using languageCode": function () { var service, that = this; @@ -69,6 +99,291 @@ YUI.add('ez-contenteditviewservice-tests', function (Y) { Y.Mock.verify(this.content); }, + "Should load content using baseLanguageCode": function () { + var service, + that = this; + + Y.Mock.expect(this.version, { + method: 'reset' + }); + Y.Mock.expect(this.content, { + method: 'set', + args: ['id', this.requestBaseLanguage.params.id] + }); + + Y.Mock.expect(this.content, { + method: 'load', + args: [Y.Mock.Value.Object, Y.Mock.Value.Function], + run: function (options, callback) { + Assert.areEqual( + that.baseLanguageCode, + options.languageCode, + "Language code should be the same as baseLanguageCode in request" + ); + } + }); + + service = new Y.eZ.ContentEditViewService({ + capi: this.capiMock, + request: this.requestBaseLanguage, + app: this.app, + location: this.mainLocation, + content: this.content, + version: this.version, + }); + + service.load(); + + Y.Mock.verify(this.content); + }, + + "Should fire the 'error' event when translation on which translation is based doesn't exist": function () { + var service, + that = this, + errorTriggered = false, + newTranslation = 'jpn-JP', + notExistingTranslation = 'fre-FR', + contentAlwaysAvailable = false, + callback = function () {}, + request = { + params: { + id: "/api/ezp/v2/content/objects/59", + languageCode: newTranslation, + baseLanguageCode: notExistingTranslation + } + }, + runLoadCallback = function (options, callback) { + Y.Assert.areSame( + options.api, cevlTest.capiMock, + "The 'api' property should be the CAPI" + ); + callback(false); + }; + + Y.Mock.expect(this.version, { + method: 'reset' + }); + Y.Mock.expect(this.version, { + method: 'set', + args: ['fields', Y.Mock.Value.Object] + }); + Y.Mock.expect(this.content, { + method: 'get', + callCount: 4, + args: [Y.Mock.Value.String], + run: function (attr) { + if ( attr === 'resources' ) { + return that.resources; + } else if ( attr === 'fields' ) { + return that.fields; + } else if ( attr === 'currentVersion' ) { + return that.contentCurrentVersion; + } else if ( attr === 'alwaysAvailable' ) { + return contentAlwaysAvailable; + } else if ( attr === 'contentId' ) { + return request.params.id; + } else { + Y.fail("Unexpected call to content.get(" + attr + ")"); + } + } + }); + Y.Mock.expect(this.content, { + method: 'load', + args: [Y.Mock.Value.Object, Y.Mock.Value.Function] + }); + Y.Array.each(this.mocks, function (val) { + Y.Mock.expect(cevlTest[val], { + method: 'load', + args: [Y.Mock.Value.Object, Y.Mock.Value.Function], + run: runLoadCallback + }); + }); + Y.Object.each(this.resources, function (val, key) { + var attr = key.charAt(0).toLowerCase() + key.substr(1); + Y.Mock.expect(cevlTest[attr], { + method: 'set', + args: ['id', val] + }); + }); + Y.Mock.expect(this.contentCurrentVersion, { + method: 'getTranslationsList', + args: [], + returns: this.versionTranslationsList + }); + Y.Mock.expect(this.content, { + method: 'set', + args: ['id', this.request.params.id] + }); + + service = new Y.eZ.ContentEditViewService({ + capi: this.capiMock, + request: request, + app: this.app, + location: this.mainLocation, + content: this.content, + version: this.version, + }); + + service.on('error', function (e) { + errorTriggered = true; + }); + + service.load(callback); + + Y.Assert.isTrue(errorTriggered, 'Should fire `error` event'); + }, + + _testSetFields: function (request, expectedFields) { + var service, + that = this, + contentAlwaysAvailable = false, + runLoadCallback = function (options, callback) { + Y.Assert.areSame( + options.api, cevlTest.capiMock, + "The 'api' property should be the CAPI" + ); + callback(false); + }, + callback = function () {}; + + Y.Mock.expect(this.version, { + method: 'reset' + }); + Y.Mock.expect(this.content, { + method: 'get', + callCount: 4, + args: [Y.Mock.Value.String], + run: function (attr) { + if ( attr === 'resources' ) { + return that.resources; + } else if ( attr === 'fields' ) { + if (request.params.baseLanguageCode) { + return that.fieldsForBaseTranslation; + } + return that.fields; + } else if ( attr === 'currentVersion' ) { + return that.contentCurrentVersion; + } else if ( attr === 'alwaysAvailable' ) { + return contentAlwaysAvailable; + } else if ( attr === 'contentId' ) { + return request.params.id; + } else { + Y.fail("Unexpected call to content.get(" + attr + ")"); + } + } + }); + Y.Mock.expect(this.content, { + method: 'load', + args: [Y.Mock.Value.Object, Y.Mock.Value.Function] + }); + Y.Array.each(this.mocks, function (val) { + Y.Mock.expect(cevlTest[val], { + method: 'load', + args: [Y.Mock.Value.Object, Y.Mock.Value.Function], + run: runLoadCallback + }); + }); + Y.Object.each(this.resources, function (val, key) { + var attr = key.charAt(0).toLowerCase() + key.substr(1); + Y.Mock.expect(cevlTest[attr], { + method: 'set', + args: ['id', val] + }); + }); + Y.Mock.expect(this.contentCurrentVersion, { + method: 'getTranslationsList', + args: [], + returns: this.versionTranslationsList + }); + Y.Mock.expect(this.content, { + method: 'set', + args: ['id', this.request.params.id] + }); + Y.Mock.expect(this.contentType, { + method: 'get', + args: ['fieldDefinitions'], + returns: this.fieldDefinitions + }); + Y.Mock.expect(this.version, { + method: 'set', + args: ['fields', Y.Mock.Value.Object], + run: function (attr, fields) { + Y.Object.each(fields, function (field, identifier) { + Y.Assert.areSame( + field.fieldValue, + expectedFields[identifier].fieldValue, + "The field value should be the same as expected" + ); + Y.Assert.areSame( + field.languageCode, + expectedFields[identifier].languageCode, + "The field languageCode should be the same as expected" + ); + }); + } + }); + + service = new Y.eZ.ContentEditViewService({ + capi: this.capiMock, + request: request, + app: this.app, + location: this.mainLocation, + content: this.content, + version: this.version, + contentType: this.contentType, + }); + + service.load(callback); + }, + + "Should set default version fields for given content type": function () { + var newTranslation = 'ger-DE', + expectedFields = { + name: { + languageCode: newTranslation, + fieldValue: this.fieldDefinitions.name.defaultValue + } + }, + request = { + params: { + id: "/api/ezp/v2/content/objects/59", + languageCode: newTranslation, + } + }; + this._testSetFields(request, expectedFields); + }, + + "Should set values from content loaded with base language code": function () { + var newTranslation = 'jpn-JP', + baseLanguageCode = this.baseLanguageCode, + expectedFields = { + name: { + languageCode: newTranslation, + fieldValue: this.fieldsForBaseTranslation.name.fieldValue + } + }, + request = { + params: { + id: "/api/ezp/v2/content/objects/59", + languageCode: newTranslation, + baseLanguageCode: baseLanguageCode + } + }; + this._testSetFields(request, expectedFields); + }, + + "Should set values from content loaded with existing language code": function () { + var existingTranslation = this.languageCode, + expectedFields = this.fields, + request = { + params: { + id: "/api/ezp/v2/content/objects/59", + languageCode: existingTranslation, + } + }; + this._testSetFields(request, expectedFields); + }, + "Should load the content, the location, the content type and the owner": function () { var response = {}, service, callback, callbackCalled = false, @@ -81,31 +396,56 @@ YUI.add('ez-contenteditviewservice-tests', function (Y) { callback(false); }; + Y.Mock.expect(this.contentCurrentVersion, { + method: 'getTranslationsList', + args: [], + returns: this.versionTranslationsList + }); Y.Mock.expect(this.content, { method: 'set', args: ['id', this.request.params.id] }); Y.Mock.expect(this.version, { method: 'set', - args: ['fields', this.fields] + args: ['fields', Y.Mock.Value.Object], + run: function(attr, fields) { + Y.Assert.areSame( + fields.name.languageCode, + that.fields.name.languageCode, + 'The languageCode should match' + ); + Y.Assert.areSame( + fields.name.fieldValue, + that.fields.name.fieldValue, + 'The fieldValue should match' + ); + } }); Y.Mock.expect(this.version, { method: 'reset' }); Y.Mock.expect(this.content, { method: 'get', - callCount: 2, + callCount: 3, args: [Y.Mock.Value.String], run: function (attr) { if ( attr === 'resources' ) { return that.resources; } else if ( attr === 'fields' ) { return that.fields; + } else if ( attr === 'currentVersion' ) { + return that.contentCurrentVersion; } else { Y.fail("Unexpected call to content.get(" + attr + ")"); } } }); + Y.Mock.expect(this.contentType, { + method: 'get', + callCount: 2, + args: ['fieldDefinitions'], + returns: that.fieldDefinitions + }); Y.Object.each(this.resources, function (val, key) { var attr = key.charAt(0).toLowerCase() + key.substr(1); @@ -151,7 +491,6 @@ YUI.add('ez-contenteditviewservice-tests', function (Y) { Y.Mock.verify(this.app); Y.Mock.verify(this.content); - Y.Mock.verify(this.contentType); Y.Mock.verify(this.mainLocation); Y.Mock.verify(this.owner); Y.Mock.verify(this.version); @@ -161,7 +500,8 @@ YUI.add('ez-contenteditviewservice-tests', function (Y) { "Should fire the 'error' event when the content loading fails": function () { var service, callback, - errorTriggered = false; + errorTriggered = false, + that = this; Y.Mock.expect(this.version, { method: 'reset' @@ -179,6 +519,12 @@ YUI.add('ez-contenteditviewservice-tests', function (Y) { } }); + Y.Mock.expect(this.contentType, { + method: 'get', + args: ['fieldDefinitions'], + returns: that.fieldDefinitions + }); + callback = function () { Y.Assert.fail("The load callback should not be called"); }; @@ -190,6 +536,7 @@ YUI.add('ez-contenteditviewservice-tests', function (Y) { location: this.mainLocation, content: this.content, version: this.version, + contentType: this.contentType, }); service.on('error', function (e) { @@ -218,6 +565,11 @@ YUI.add('ez-contenteditviewservice-tests', function (Y) { callback(true); }; + Y.Mock.expect(this.contentCurrentVersion, { + method: 'getTranslationsList', + args: [], + returns: this.versionTranslationsList + }); Y.Mock.expect(this.version, { method: 'reset' }); @@ -227,22 +579,29 @@ YUI.add('ez-contenteditviewservice-tests', function (Y) { }); Y.Mock.expect(this.version, { method: 'set', - args: ['fields', this.fields] + args: ['fields', Y.Mock.Value.Object] }); Y.Mock.expect(this.content, { method: 'get', - callCount: 2, + callCount: 4, args: [Y.Mock.Value.String], run: function (attr) { if ( attr === 'resources' ) { return that.resources; } else if ( attr === 'fields' ) { return that.fields; + } else if ( attr === 'currentVersion' ) { + return that.contentCurrentVersion; } else { Y.fail("Unexpected call to content.get(" + attr + ")"); } } }); + Y.Mock.expect(this.contentType, { + method: 'get', + args: ['fieldDefinitions'], + returns: that.fieldDefinitions + }); Y.Object.each(this.resources, function (val, key) { var attr = key.charAt(0).toLowerCase() + key.substr(1); @@ -284,11 +643,8 @@ YUI.add('ez-contenteditviewservice-tests', function (Y) { service.load(callback); Y.Mock.verify(this.app); - Y.Mock.verify(this.content); - Y.Mock.verify(this.contentType); Y.Mock.verify(this.mainLocation); Y.Mock.verify(this.owner); - Y.Mock.verify(this.version); Y.Assert.isTrue(errorTriggered, "The error event should have been triggered"); }, @@ -336,6 +692,25 @@ YUI.add('ez-contenteditviewservice-tests', function (Y) { 'Should redirect to the closeRedirectionUrl value': function () { this.service.fire('test:closeView'); Y.Mock.verify(this.app); + }, + + 'Should set languageCode and baseLanguageCode': function () { + var baseLanguageCode = 'eng-GB', + languageCode = 'jpn-JP', + newRequest = {params: {languageCode: languageCode, baseLanguageCode: baseLanguageCode}}; + + this.service.set('request', newRequest); + this.service.fire('test:requestChange'); + Y.Assert.areSame( + baseLanguageCode, + this.service.get('baseLanguageCode'), + "The baseLanguageCode attribute should be set" + ); + Y.Assert.areSame( + languageCode, + this.service.get('languageCode'), + "The languageCode attribute should be set" + ); } }); diff --git a/Tests/js/views/services/ez-contenteditviewservice.html b/Tests/js/views/services/ez-contenteditviewservice.html index 19d2f2cec..01d9f48dc 100644 --- a/Tests/js/views/services/ez-contenteditviewservice.html +++ b/Tests/js/views/services/ez-contenteditviewservice.html @@ -26,7 +26,7 @@ filter: loaderFilter, modules: { "ez-contenteditviewservice": { - requires: ['ez-viewservice', 'parallel', 'fake-models'], + requires: ['ez-viewservice', 'parallel', 'fake-models', 'array-extras'], fullpath: "../../../../Resources/public/js/views/services/ez-contenteditviewservice.js" }, "ez-viewservice": {