Skip to content

Commit cc2d342

Browse files
authored
Merge pull request #349 from magento-obsessive-owls/PB-170
[Owls] PB-170: TinyMCE Performance is very poor with multiple instances on Stage
2 parents 82a65f4 + 426c596 commit cc2d342

File tree

39 files changed

+2212
-391
lines changed

39 files changed

+2212
-391
lines changed

app/code/Magento/PageBuilder/Model/Stage/Config.php

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
use Magento\Framework\UrlInterface;
1212

1313
/**
14-
* Provide config for page builder
14+
* Provide configuration to the admin JavaScript app
15+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
1516
*
1617
* @api
1718
*/
@@ -80,9 +81,18 @@ class Config
8081
*/
8182
private $rootContainerConfig;
8283

84+
/**
85+
* @var \Magento\Widget\Model\Widget\Config
86+
*/
87+
private $widgetConfig;
88+
89+
/**
90+
* @var \Magento\Variable\Model\Variable\Config
91+
*/
92+
private $variableConfig;
93+
8394
/**
8495
* Config constructor.
85-
*
8696
* @param \Magento\PageBuilder\Model\ConfigInterface $config
8797
* @param Config\UiComponentConfig $uiComponentConfig
8898
* @param UrlInterface $urlBuilder
@@ -94,6 +104,8 @@ class Config
94104
* @param \Magento\PageBuilder\Model\WidgetInitializerConfig $widgetInitializerConfig
95105
* @param array $rootContainerConfig
96106
* @param array $data
107+
* @param \Magento\Widget\Model\Widget\Config|null $widgetConfig
108+
* @param \Magento\Variable\Model\Variable\Config|null $variableConfig
97109
*
98110
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
99111
*/
@@ -108,7 +120,9 @@ public function __construct(
108120
\Magento\PageBuilder\Model\Wysiwyg\InlineEditingSupportedAdapterList $inlineEditingChecker,
109121
\Magento\PageBuilder\Model\WidgetInitializerConfig $widgetInitializerConfig,
110122
array $rootContainerConfig = [],
111-
array $data = []
123+
array $data = [],
124+
\Magento\Widget\Model\Widget\Config $widgetConfig = null,
125+
\Magento\Variable\Model\Variable\Config $variableConfig = null
112126
) {
113127
$this->config = $config;
114128
$this->uiComponentConfig = $uiComponentConfig;
@@ -121,6 +135,10 @@ public function __construct(
121135
$this->widgetInitializerConfig = $widgetInitializerConfig;
122136
$this->rootContainerConfig = $rootContainerConfig;
123137
$this->data = $data;
138+
$this->widgetConfig = $widgetConfig ?? \Magento\Framework\App\ObjectManager::getInstance()
139+
->get(\Magento\Widget\Model\Widget\Config::class);
140+
$this->variableConfig = $variableConfig ?? \Magento\Framework\App\ObjectManager::getInstance()
141+
->get(\Magento\Variable\Model\Variable\Config::class);
124142
}
125143

126144
/**
@@ -141,8 +159,39 @@ public function getConfig()
141159
'column_grid_max' => $this->scopeConfig->getValue(self::XML_PATH_COLUMN_GRID_MAX),
142160
'can_use_inline_editing_on_stage' => $this->isWysiwygProvisionedForEditingOnStage(),
143161
'widgets' => $this->widgetInitializerConfig->getConfig(),
144-
'breakpoints' => $this->widgetInitializerConfig->getBreakpoints()
162+
'breakpoints' => $this->widgetInitializerConfig->getBreakpoints(),
163+
'tinymce' => $this->getTinyMceConfig(),
164+
];
165+
}
166+
167+
/**
168+
* Retrieve the TinyMCE required configuration
169+
*
170+
* @return array
171+
*/
172+
private function getTinyMceConfig()
173+
{
174+
$config = [
175+
'widgets' => [],
176+
'variables' => []
145177
];
178+
179+
// Retrieve widget configuration
180+
$widgetConfig = $this->widgetConfig->getConfig(new \Magento\Framework\DataObject());
181+
$options = $widgetConfig->getData('plugins');
182+
if (isset($options[0]) && $options[0]['name'] === 'magentowidget') {
183+
$config['widgets'] = $options[0]['options'];
184+
}
185+
186+
// Retrieve variable configuration
187+
$variableConfig = $this->variableConfig->getWysiwygPluginSettings(new \Magento\Framework\DataObject());
188+
if (isset($variableConfig['plugins']) && isset($variableConfig['plugins'][0])
189+
&& $variableConfig['plugins'][0]['name'] === 'magentovariable'
190+
) {
191+
$config['variables'] = $variableConfig['plugins'][0]['options'];
192+
}
193+
194+
return $config;
146195
}
147196

148197
/**

app/code/Magento/PageBuilder/Test/Mftf/ActionGroup/OverlayActionGroup.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,8 @@
161161
</arguments>
162162
<!-- Validate bottom edge of overlay -->
163163
<comment userInput="Validate bottom edge of overlay" stepKey="commentValidateBottomEdgeOfOverlay"/>
164-
<executeJS function="return {{page.wrapperJS(index)}}.getBoundingClientRect().top+{{padding.paddingTop}}+120" stepKey="wrapperTopPaddingContent"/>
164+
<!-- 30px padding top, 50px min height, 30px padding bottom -->
165+
<executeJS function="return {{page.wrapperJS(index)}}.getBoundingClientRect().top+{{padding.paddingTop}}+30+50+30" stepKey="wrapperTopPaddingContent"/>
165166
<executeJS function="return {{page.overlayJS(index)}}.getBoundingClientRect().bottom" stepKey="overlayBottomPosition"/>
166167
<executeJS function="return Math.round(({$wrapperTopPaddingContent}/{$overlayBottomPosition})*100)/100" stepKey="overlayBottomRatio"/>
167168
<assertEquals stepKey="assertOverlayBottomRatio">

app/code/Magento/PageBuilder/Test/Mftf/ActionGroup/WYSIWYGActionGroup.xml

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,15 @@
6565
<waitForElementVisible selector="{{TinyMCESection.InsertVariableIcon}}" stepKey="waitForInsertVariable1"/>
6666
<click selector="{{TinyMCESection.InsertVariableIcon}}" stepKey="clickInsertVariable1"/>
6767
</actionGroup>
68+
<actionGroup name="seeVariableTinyMCE">
69+
<arguments>
70+
<argument name="section" defaultValue="TextOnStage"/>
71+
<argument name="index" defaultValue="1" type="string"/>
72+
<argument name="labelValue" defaultValue=""/>
73+
</arguments>
74+
<waitForElementVisible selector="{{section.text(index, labelValue)}}" stepKey="waitForVariable"/>
75+
<seeElement selector="{{section.text(index, labelValue)}}" stepKey="seeVariable"/>
76+
</actionGroup>
6877
<actionGroup name="addVariableToTinyMCE3" extends="addVariableToTinyMCE">
6978
<arguments>
7079
<argument name="variable" defaultValue=""/>
@@ -243,4 +252,104 @@
243252
<waitForPageLoad stepKey="waitForPageLoad1"/>
244253
<click selector="{{PageBuilderPanel.searchPanel}}" stepKey="loseFocusFromEditor"/>
245254
</actionGroup>
255+
<actionGroup name="formatTextTinyMCE">
256+
<arguments>
257+
<argument name="section" defaultValue="WYSIWYGOnPageBuilderInline"/>
258+
<!-- Receives pagebuilder_tinymce_format -->
259+
<argument name="format" defaultValue="TinyMCEFormatHeading1"/>
260+
</arguments>
261+
<waitForElementVisible selector="{{section.formatSelector}}" stepKey="waitForFormatList"/>
262+
<click selector="{{section.formatSelector}}" stepKey="expandFormatList"/>
263+
<waitForElementVisible selector="{{section.formatOption(format.label)}}" stepKey="waitForFormatOptionVisible"/>
264+
<click selector="{{section.formatOption(format.label)}}" stepKey="clickFormatOption"/>
265+
<waitForElementNotVisible selector="{{section.formatOption(format.label)}}" stepKey="waitForFormatInvisible"/>
266+
</actionGroup>
267+
<actionGroup name="waitForTinyMCEInFocus">
268+
<arguments>
269+
<argument name="section" defaultValue="TextOnStage"/>
270+
<argument name="index" defaultValue="1" type="string"/>
271+
</arguments>
272+
<waitForElementVisible selector="{{section.tinymceInFocus(index)}}" stepKey="waitForTinyMCEInFocus"/>
273+
</actionGroup>
274+
<actionGroup name="clickDirectiveTinyMCE">
275+
<arguments>
276+
<argument name="section" defaultValue="TextOnStage"/>
277+
<argument name="index" defaultValue="1" type="string"/>
278+
<argument name="labelValue" defaultValue=""/>
279+
</arguments>
280+
<waitForElementVisible selector="{{section.directive(index, labelValue)}}" stepKey="waitForDirective"/>
281+
<click selector="{{section.directive(index, labelValue)}}" stepKey="clickDirective"/>
282+
</actionGroup>
283+
<actionGroup name="seeDirectiveFocusedTinyMCE">
284+
<arguments>
285+
<argument name="section" defaultValue="TextOnStage"/>
286+
<argument name="index" defaultValue="1" type="string"/>
287+
<argument name="labelValue" defaultValue=""/>
288+
</arguments>
289+
<waitForElementVisible selector="{{section.directiveFocused(index, labelValue)}}" stepKey="waitForDirectiveFocused"/>
290+
<seeElement selector="{{section.directiveFocused(index, labelValue)}}" stepKey="verifyDirectiveIsFocused"/>
291+
</actionGroup>
292+
<actionGroup name="scrollToTinyMCE">
293+
<arguments>
294+
<argument name="section" defaultValue="TextOnStage"/>
295+
<argument name="index" defaultValue="1" type="string"/>
296+
</arguments>
297+
<scrollTo selector="{{section.tinymce(index)}}" stepKey="scrollToTinyMCE"/>
298+
<waitForElementVisible selector="{{section.tinymce(index)}}" stepKey="waitForTinyMCEVisible"/>
299+
</actionGroup>
300+
<actionGroup name="assertSelectedText">
301+
<arguments>
302+
<argument name="expectedSelectedText"/>
303+
</arguments>
304+
<executeJS function="return window.getSelection().toString()" stepKey="selectionString"/>
305+
<assertEquals stepKey="assertSelectionText">
306+
<expectedResult type="string">{{expectedSelectedText.selection}}</expectedResult>
307+
<actualResult type="variable">selectionString</actualResult>
308+
</assertEquals>
309+
</actionGroup>
310+
<actionGroup name="doubleClickVariableTinyMCE">
311+
<arguments>
312+
<argument name="section" defaultValue="TextOnStage"/>
313+
<argument name="index" defaultValue="1" type="string"/>
314+
<argument name="variable"/>
315+
</arguments>
316+
<waitForElementVisible selector="{{section.directive(index, variable.editPanelValue)}}" stepKey="waitForVariableVisible"/>
317+
<doubleClick selector="{{section.directive(index, variable.editPanelValue)}}" stepKey="doubleClickOnVariablePlaceholder"/>
318+
<waitForPageLoad stepKey="waitForPageLoad"/>
319+
<waitForElementVisible selector="{{VariableSection.CancelBtnEnabled}}" stepKey="waitForCancelButton"/>
320+
<waitForElementVisible selector="{{VariableSection.Radio(variable.variableName)}}" stepKey="waitForVariableAfterDoubleClick"/>
321+
</actionGroup>
322+
<actionGroup name="closeVariablePanelTinyMCE">
323+
<waitForElementVisible selector="{{VariableSection.CancelBtnEnabled}}" stepKey="waitForCancelButton"/>
324+
<click selector="{{VariableSection.CancelBtnEnabled}}" stepKey="clickCancelButton"/>
325+
<waitForPageLoad stepKey="waitForPageLoad"/>
326+
<waitForElementNotVisible selector="{{VariableSection.CancelBtnEnabled}}" stepKey="waitForVariableCancelNotVisible"/>
327+
</actionGroup>
328+
<actionGroup name="doubleClickWidgetTinyMCE">
329+
<arguments>
330+
<argument name="section" defaultValue="TextOnStage"/>
331+
<argument name="index" defaultValue="1" type="string"/>
332+
<argument name="widget"/>
333+
</arguments>
334+
<waitForElementVisible selector="{{section.directive('1', TinyMCEWidgetCMSPageLink.editPanelValue)}}" stepKey="waitForWidgetVisible"/>
335+
<doubleClick selector="{{section.directive('1', TinyMCEWidgetCMSPageLink.editPanelValue)}}" stepKey="doubleClickOnWidgetPlaceholder"/>
336+
<waitForPageLoad stepKey="waitForPageLoad"/>
337+
<waitForElementVisible selector="{{WidgetSection.CancelBtnEnabled}}" stepKey="waitForCancelButtonVisible"/>
338+
</actionGroup>
339+
<actionGroup name="closeWidgetPanelTinyMCE">
340+
<waitForElementVisible selector="{{WidgetSection.CancelBtnEnabled}}" stepKey="waitForCancelButton"/>
341+
<click selector="{{WidgetSection.CancelBtnEnabled}}" stepKey="clickCancelButton"/>
342+
<waitForPageLoad stepKey="waitForPageLoad"/>
343+
<waitForElementNotVisible selector="{{WidgetSection.CancelBtnEnabled}}" stepKey="waitForCancelButtonNotVisible"/>
344+
</actionGroup>
345+
<actionGroup name="focusTinyMCE">
346+
<arguments>
347+
<argument name="section" defaultValue="TextOnStage"/>
348+
<argument name="index" defaultValue="1" type="string"/>
349+
</arguments>
350+
<waitForElementVisible selector="{{section.tinymce(index)}}" stepKey="waitForTinyMCE"/>
351+
<click selector="{{section.tinymce(index)}}" stepKey="focusOnTextEditorArea"/>
352+
<waitForPageLoad stepKey="waitForPageLoad"/>
353+
<waitForElementVisible selector="{{section.tinymceInFocus(index)}}" stepKey="waitForTinyMCEInFocus"/>
354+
</actionGroup>
246355
</actionGroups>

app/code/Magento/PageBuilder/Test/Mftf/Data/TextData.xml

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@
1616
<data key="cmsPageLinkName" unique="suffix">cms-page-link-</data>
1717
<data key="value">test string</data>
1818
</entity>
19+
<entity name="PageBuilderTextHeadingProperty" type="pagebuilder_text_property">
20+
<data key="name">Text</data>
21+
<data key="section">General</data>
22+
<data key="fieldName">text</data>
23+
<data key="cmsPageLinkName" unique="suffix">cms-page-link-</data>
24+
<data key="value">This is a heading</data>
25+
</entity>
1926
<entity name="PageBuilderTextContentTypeDefault" type="pagebuilder_text_property">
2027
<data key="name">Text</data>
2128
<data key="section">General</data>
@@ -72,4 +79,62 @@
7279
<data key="expectedString1">test str</data>
7380
<data key="expectedString2">ing</data>
7481
</entity>
82+
<!-- TinyMCE Formats -->
83+
<entity name="TinyMCEFormatParagraph" type="pagebuilder_tinymce_format">
84+
<data key="label">Paragraph</data>
85+
<data key="tagName">p</data>
86+
</entity>
87+
<entity name="TinyMCEFormatHeading1" type="pagebuilder_tinymce_format">
88+
<data key="label">Heading 1</data>
89+
<data key="tagName">h1</data>
90+
</entity>
91+
<entity name="TinyMCEFormatHeading2" type="pagebuilder_tinymce_format">
92+
<data key="label">Heading 2</data>
93+
<data key="tagName">h2</data>
94+
</entity>
95+
<entity name="TinyMCEFormatHeading3" type="pagebuilder_tinymce_format">
96+
<data key="label">Heading 3</data>
97+
<data key="tagName">h3</data>
98+
</entity>
99+
<entity name="TinyMCEFormatHeading4" type="pagebuilder_tinymce_format">
100+
<data key="label">Heading 4</data>
101+
<data key="tagName">h4</data>
102+
</entity>
103+
<entity name="TinyMCEFormatHeading5" type="pagebuilder_tinymce_format">
104+
<data key="label">Heading 5</data>
105+
<data key="tagName">h5</data>
106+
</entity>
107+
<entity name="TinyMCEFormatHeading6" type="pagebuilder_tinymce_format">
108+
<data key="label">Heading 6</data>
109+
<data key="tagName">h6</data>
110+
</entity>
111+
<entity name="TinyMCEFormatImportant" type="pagebuilder_tinymce_format">
112+
<data key="label">Important</data>
113+
<data key="tagName">div</data>
114+
</entity>
115+
<entity name="TinyMCEFormatPreformatted" type="pagebuilder_tinymce_format">
116+
<data key="label">Preformatted</data>
117+
<data key="tagName">div</data>
118+
</entity>
119+
<!-- TinyMCE Selections -->
120+
<entity name="TinyMCEPartialHeadingSelection" type="pagebuilder_text_selection">
121+
<data key="startX">15</data>
122+
<data key="endX">115</data>
123+
<data key="startY">15</data>
124+
<data key="endY">15</data>
125+
<data key="selection">his is a h</data>
126+
</entity>
127+
<entity name="TinyMCEPartialTextSelection" type="pagebuilder_text_selection">
128+
<data key="startX">18</data>
129+
<data key="endX">55</data>
130+
<data key="startY">15</data>
131+
<data key="endY">15</data>
132+
<data key="selection">t strin</data>
133+
</entity>
134+
<entity name="TinyMCEHeadingVariableTextSelection" type="pagebuilder_multiple_text_selection">
135+
<data key="selection">his is a heading
136+
Base URL
137+
138+
test strin</data>
139+
</entity>
75140
</entities>

app/code/Magento/PageBuilder/Test/Mftf/Section/PageBuilderBannerSection.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
<element name="messageContentWidget" type="text" selector="(//div[@data-content-type='banner'])[{{arg1}}]//div[@data-element='content']//a[contains(@href,'{{arg2}}{{arg3}}')]" parameterized="true"/>
4242
<element name="messageContentTextArea" type="text" selector="(//div[@data-content-type='banner'])[{{arg1}}]//div[@data-element='wrapper']//div[@data-element='content'][contains(text(),'{{arg2}}')]" parameterized="true"/>
4343
<element name="messageContentTextAreaImage" type="text" selector="(//div[@data-content-type='banner'])[{{arg1}}]//div[@data-element='wrapper']//div[@data-element='content']//img[contains(@src, {{arg2}})]" parameterized="true"/>
44-
<element name="messageContentHeightJS" type="text" selector="return document.evaluate(&quot;(//div[@data-content-type='banner'])[{{arg1}}]//div[@data-element='content']//div[contains(text(),'{{arg2}}')]&quot;, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue.clientHeight;" parameterized="true"/>
44+
<element name="messageContentHeightJS" type="text" selector="return document.evaluate(&quot;(//div[@data-content-type='banner'])[{{arg1}}]//div[contains(@class, 'pagebuilder-collage-content') or contains(@class, 'pagebuilder-poster-content')]//*[contains(text(),'{{arg2}}')]&quot;, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue.clientHeight;" parameterized="true"/>
4545
<element name="linkUrl" type="button" selector="(//div[@data-content-type='banner'])[{{arg1}}]/a[@data-element='link'][contains(@href,'{{arg2}}')]" parameterized="true"/>
4646
<element name="openInNewTab" type="button" selector="(//div[@data-content-type='banner'])[{{arg1}}]/a[@data-element='link'][contains(@target,'_blank')]" parameterized="true"/>
4747
<element name="button" type="button" selector="(//div[@data-content-type='banner'])[{{arg1}}]//div[@data-element='wrapper']//button" parameterized="true"/>
@@ -85,8 +85,8 @@
8585
<element name="imageOnStage" type="text" selector="(//div[contains(@class,'pagebuilder-banner') and contains(@class,'pagebuilder-content-type')])[{{arg1}}]//img[contains(@src,'{{var1}}')]" parameterized="true"/>
8686
<element name="imageSourceByIndex" type="text" selector="(//div[@data-content-type='banner'])[{{arg1}}]/div[contains(@style,'{{arg2}}')]" parameterized="true"/>
8787
<element name="uploadImageInput" type="button" selector="//div[contains(@class,'pagebuilder-image-uploader-container')]//input[@name='background_image']"/>
88-
<element name="variablePlaceholder" type="text" selector="(//div[contains(@class,'pagebuilder-banner')])[{{arg}}]//*[contains(@class, 'magento-variable magento-placeholder')]" parameterized="true"/>
89-
<element name="widgetPlaceholder" type="text" selector="(//div[contains(@class,'pagebuilder-banner')])[{{arg}}]//*[contains(@class, 'magento-placeholder magento-widget')]" parameterized="true"/>
88+
<element name="variablePlaceholder" type="text" selector="(//div[contains(@class,'pagebuilder-banner')])[{{arg}}]//*[contains(@class, 'magento-variable') and contains(@class, 'magento-placeholder')]" parameterized="true"/>
89+
<element name="widgetPlaceholder" type="text" selector="(//div[contains(@class,'pagebuilder-banner')])[{{arg}}]//*[contains(@class, 'magento-placeholder') and contains(@class, 'magento-widget')]" parameterized="true"/>
9090
<element name="tinymce" type="text" selector="(//div[contains(@class,'pagebuilder-banner')])[{{arg}}]//div[contains(@class, 'inline-wysiwyg')]" parameterized="true"/>
9191
<element name="tinymceInFocus" type="text" selector="(//div[contains(@class,'pagebuilder-banner')])[{{arg}}]//div[contains(@class, 'inline-wysiwyg') and contains(@class, 'mce-edit-focus')]" parameterized="true"/>
9292
<!-- Appearance Configuration -->

0 commit comments

Comments
 (0)