diff --git a/js/ui/context_menu/ui.menu_base.js b/js/ui/context_menu/ui.menu_base.js
index 3c328fa2246d..1b37aedff58a 100644
--- a/js/ui/context_menu/ui.menu_base.js
+++ b/js/ui/context_menu/ui.menu_base.js
@@ -30,7 +30,7 @@ const SINGLE_SELECTION_MODE = 'single';
const DEFAULT_DELAY = { 'show': 50, 'hide': 300 };
const DX_MENU_ITEM_CAPTION_URL_CLASS = `${DX_MENU_ITEM_CAPTION_CLASS}-with-url`;
const DX_ICON_WITH_URL_CLASS = 'dx-icon-with-url';
-const DX_ITEM_URL_CLASS = 'dx-item-url';
+const ITEM_URL_CLASS = 'dx-item-url';
class MenuBase extends HierarchicalCollectionWidget {
@@ -183,29 +183,21 @@ class MenuBase extends HierarchicalCollectionWidget {
_getLinkContainer(iconContainer, textContainer, { linkAttr, url }) {
iconContainer?.addClass(DX_ICON_WITH_URL_CLASS);
textContainer?.addClass(DX_MENU_ITEM_CAPTION_URL_CLASS);
- const linkAttributes = isObject(linkAttr) ? linkAttr : {};
- return $('')
- .addClass(DX_ITEM_URL_CLASS)
- .attr({ ...linkAttributes, href: url })
- .append(iconContainer)
- .append(textContainer);
+
+ return super._getLinkContainer(iconContainer, textContainer, { linkAttr, url });
}
_addContent($container, itemData) {
const { html, url } = itemData;
- const iconContainer = this._getIconContainer(itemData);
- const textContainer = this._getTextContainer(itemData);
-
- $container.html(html);
if(url) {
- const link = this._getLinkContainer(iconContainer, textContainer, itemData);
+ $container.html(html);
+ const link = this._getLinkContainer(this._getIconContainer(itemData), this._getTextContainer(itemData), itemData);
$container.append(link);
} else {
- $container
- .append(iconContainer)
- .append(textContainer);
+ super._addContent($container, itemData);
}
+
$container.append(this._getPopoutContainer(itemData));
this._addContentClasses(itemData, $container.parent());
}
@@ -561,7 +553,7 @@ class MenuBase extends HierarchicalCollectionWidget {
_itemClick(actionArgs) {
const args = actionArgs.args[0];
- const link = args.event.target.getElementsByClassName(DX_ITEM_URL_CLASS)[0];
+ const link = args.event.target.getElementsByClassName(ITEM_URL_CLASS)[0];
if(args.itemData.url && link) {
link.click();
}
diff --git a/js/ui/hierarchical_collection/ui.hierarchical_collection_widget.js b/js/ui/hierarchical_collection/ui.hierarchical_collection_widget.js
index 86e827cefaf7..a6d17f3931b5 100644
--- a/js/ui/hierarchical_collection/ui.hierarchical_collection_widget.js
+++ b/js/ui/hierarchical_collection/ui.hierarchical_collection_widget.js
@@ -7,10 +7,11 @@ import { getImageContainer } from '../../core/utils/icon';
import HierarchicalDataAdapter from './ui.data_adapter';
import CollectionWidget from '../collection/ui.collection_widget.edit';
import { BindableTemplate } from '../../core/templates/bindable_template';
-import { isFunction } from '../../core/utils/type';
+import { isFunction, isObject } from '../../core/utils/type';
import { noop } from '../../core/utils/common';
const DISABLED_STATE_CLASS = 'dx-state-disabled';
+const ITEM_URL_CLASS = 'dx-item-url';
const HierarchicalCollectionWidget = CollectionWidget.inherit({
@@ -94,6 +95,15 @@ const HierarchicalCollectionWidget = CollectionWidget.inherit({
.append(this._getTextContainer(itemData));
},
+ _getLinkContainer: function(iconContainer, textContainer, { linkAttr, url }) {
+ const linkAttributes = isObject(linkAttr) ? linkAttr : {};
+ return $('')
+ .addClass(ITEM_URL_CLASS)
+ .attr({ ...linkAttributes, href: url })
+ .append(iconContainer)
+ .append(textContainer);
+ },
+
_getIconContainer: function(itemData) {
return itemData.icon ? getImageContainer(itemData.icon) : undefined;
},
diff --git a/js/ui/tree_view/ui.tree_view.base.js b/js/ui/tree_view/ui.tree_view.base.js
index 04935fabc08d..e9e19ecb437c 100644
--- a/js/ui/tree_view/ui.tree_view.base.js
+++ b/js/ui/tree_view/ui.tree_view.base.js
@@ -54,6 +54,7 @@ const DISABLED_STATE_CLASS = 'dx-state-disabled';
const SELECTED_ITEM_CLASS = 'dx-state-selected';
const EXPAND_EVENT_NAMESPACE = 'dxTreeView_expand';
const DATA_ITEM_ID = 'data-item-id';
+const ITEM_URL_CLASS = 'dx-item-url';
const TreeViewBase = HierarchicalCollectionWidget.inherit({
@@ -769,6 +770,22 @@ const TreeViewBase = HierarchicalCollectionWidget.inherit({
return deferred.promise();
},
+ _getItemExtraPropNames() {
+ return ['url', 'linkAttr'];
+ },
+
+ _addContent: function($container, itemData) {
+ const { html, url } = itemData;
+
+ if(url) {
+ $container.html(html);
+ const link = this._getLinkContainer(this._getIconContainer(itemData), this._getTextContainer(itemData), itemData);
+ $container.append(link);
+ } else {
+ this.callBase($container, itemData);
+ }
+ },
+
_renderSublevel: function($node, node, childNodes) {
const $nestedNodeContainer = this._renderNodeContainer($node, node);
@@ -1415,11 +1432,24 @@ const TreeViewBase = HierarchicalCollectionWidget.inherit({
});
},
+ _itemClick: function(actionArgs) {
+ const args = actionArgs.args[0];
+ const target = args.event.target[0] || args.event.target;
+ const link = target.getElementsByClassName(ITEM_URL_CLASS)[0];
+
+ if(args.itemData.url && link) {
+ link.click();
+ }
+ },
+
_itemClickHandler: function(e, $item) {
const itemData = this._getItemData($item);
const node = this._getNodeByElement($item);
-
- this._itemDXEventHandler(e, 'onItemClick', { node: this._dataAdapter.getPublicNode(node) });
+ this._itemDXEventHandler(e, 'onItemClick', {
+ node: this._dataAdapter.getPublicNode(node),
+ }, {
+ beforeExecute: this._itemClick,
+ });
if(this.option('selectByClick') && !e.isDefaultPrevented()) {
this._updateItemSelection(!node.internalFields.selected, itemData, e);
diff --git a/scss/widgets/base/treeView/_common.scss b/scss/widgets/base/treeView/_common.scss
index db9713a7e783..b0c7895228b6 100644
--- a/scss/widgets/base/treeView/_common.scss
+++ b/scss/widgets/base/treeView/_common.scss
@@ -78,16 +78,16 @@ $tree-view-icon-size: 24px;
display: block;
cursor: pointer;
- .dx-treeview-item-content > .dx-icon {
- display: inline-block;
- width: $tree-view-icon-size;
- height: $tree-view-icon-size;
- vertical-align: middle;
- margin-right: 5px;
- background-size: $tree-view-icon-size $tree-view-icon-size;
- }
-
.dx-treeview-item-content {
+ .dx-icon {
+ display: inline-block;
+ width: $tree-view-icon-size;
+ height: $tree-view-icon-size;
+ vertical-align: middle;
+ margin-right: 5px;
+ background-size: $tree-view-icon-size $tree-view-icon-size;
+ }
+
span {
vertical-align: middle;
}
@@ -127,8 +127,10 @@ $tree-view-icon-size: 24px;
}
.dx-treeview-item {
- .dx-treeview-item-content > .dx-icon {
- margin-right: 0;
+ .dx-treeview-item-content {
+ .dx-icon {
+ margin-right: 0;
+ }
}
}
}
diff --git a/scss/widgets/base/treeView/_index.scss b/scss/widgets/base/treeView/_index.scss
index 04ed323bbd82..913ba18ee46e 100644
--- a/scss/widgets/base/treeView/_index.scss
+++ b/scss/widgets/base/treeView/_index.scss
@@ -33,8 +33,10 @@
}
.dx-treeview-item {
- .dx-treeview-item-content > .dx-icon {
- margin-left: 5px;
+ .dx-treeview-item-content {
+ .dx-icon {
+ margin-left: 5px;
+ }
}
}
diff --git a/scss/widgets/generic/treeView/_index.scss b/scss/widgets/generic/treeView/_index.scss
index e35b480c6b68..340f186b5d53 100644
--- a/scss/widgets/generic/treeView/_index.scss
+++ b/scss/widgets/generic/treeView/_index.scss
@@ -142,6 +142,12 @@ $generic-treeview-toggle-item-visibility-offset: -4px;
> .dx-treeview-item {
background-color: $treeview-focused-bg;
color: $treeview-focus-color;
+
+ .dx-item-content {
+ .dx-item-url {
+ color: unset;
+ }
+ }
}
}
}
@@ -150,8 +156,10 @@ $generic-treeview-toggle-item-visibility-offset: -4px;
padding: $generic-treeview-item-padding;
min-height: $generic-treeview-min-item-height;
- .dx-treeview-item-content > .dx-icon {
- @include dx-icon-sizing($generic-base-icon-size);
+ .dx-treeview-item-content {
+ .dx-icon {
+ @include dx-icon-sizing($generic-base-icon-size);
+ }
}
&.dx-state-hover {
diff --git a/scss/widgets/material/treeView/_index.scss b/scss/widgets/material/treeView/_index.scss
index 3246a04f003d..ae78a2b083f4 100644
--- a/scss/widgets/material/treeView/_index.scss
+++ b/scss/widgets/material/treeView/_index.scss
@@ -137,8 +137,10 @@ $material-treeview-item-with-checkbox-offset: $material-treeview-checkbox-offset
min-height: $material-treeview-min-item-height;
line-height: math.div($material-treeview-min-item-height, 2) - 2;
- .dx-treeview-item-content > .dx-icon {
- @include dx-icon-sizing($material-base-icon-size);
+ .dx-treeview-item-content {
+ .dx-icon {
+ @include dx-icon-sizing($material-base-icon-size);
+ }
}
&.dx-state-hover {
diff --git a/testing/testcafe/model/menu/index.ts b/testing/testcafe/model/menu/index.ts
index a76619e6609a..d89ae021408c 100644
--- a/testing/testcafe/model/menu/index.ts
+++ b/testing/testcafe/model/menu/index.ts
@@ -6,16 +6,19 @@ import ContextMenu from '../contextMenu';
const CLASS = {
menu: 'dx-menu',
item: 'dx-menu-item',
+ adaptiveItem: 'dx-treeview-item',
contextMenu: 'dx-context-menu',
+ hamburgerButton: 'dx-menu-hamburger-button',
};
export default class Menu extends Widget {
items: Selector;
- constructor() {
+ constructor(adaptivityEnabled = false) {
super(`.${CLASS.menu}`);
- this.items = Selector(`.${CLASS.item}`).filterVisible();
+ const itemClass = adaptivityEnabled ? `.${CLASS.adaptiveItem}` : `.${CLASS.item}`;
+ this.items = Selector(itemClass).filterVisible();
}
// eslint-disable-next-line class-methods-use-this
@@ -25,6 +28,10 @@ export default class Menu extends Widget {
return this.items.nth(index);
}
+ getHamburgerButton(): Selector {
+ return this.element.find(`.${CLASS.hamburgerButton}`);
+ }
+
// eslint-disable-next-line class-methods-use-this
isElementFocused(element: Selector): Promise {
return element.hasClass('dx-state-focused');
diff --git a/testing/testcafe/tests/navigation/drawer/etalons/drawer_overlap_shading_FileManager_#container.png b/testing/testcafe/tests/navigation/drawer/etalons/drawer_overlap_shading_FileManager_#container.png
index 235ed1e31315..4a5059e641c8 100644
Binary files a/testing/testcafe/tests/navigation/drawer/etalons/drawer_overlap_shading_FileManager_#container.png and b/testing/testcafe/tests/navigation/drawer/etalons/drawer_overlap_shading_FileManager_#container.png differ
diff --git a/testing/testcafe/tests/navigation/drawer/etalons/drawer_overlap_shading_FileManager_#popup1.png b/testing/testcafe/tests/navigation/drawer/etalons/drawer_overlap_shading_FileManager_#popup1.png
index 82f1fb95a514..d82a8c003420 100644
Binary files a/testing/testcafe/tests/navigation/drawer/etalons/drawer_overlap_shading_FileManager_#popup1.png and b/testing/testcafe/tests/navigation/drawer/etalons/drawer_overlap_shading_FileManager_#popup1.png differ
diff --git a/testing/testcafe/tests/navigation/drawer/etalons/drawer_push_shading_FileManager_#container.png b/testing/testcafe/tests/navigation/drawer/etalons/drawer_push_shading_FileManager_#container.png
index 235ed1e31315..4a5059e641c8 100644
Binary files a/testing/testcafe/tests/navigation/drawer/etalons/drawer_push_shading_FileManager_#container.png and b/testing/testcafe/tests/navigation/drawer/etalons/drawer_push_shading_FileManager_#container.png differ
diff --git a/testing/testcafe/tests/navigation/drawer/etalons/drawer_push_shading_FileManager_#popup1.png b/testing/testcafe/tests/navigation/drawer/etalons/drawer_push_shading_FileManager_#popup1.png
index 82f1fb95a514..d82a8c003420 100644
Binary files a/testing/testcafe/tests/navigation/drawer/etalons/drawer_push_shading_FileManager_#popup1.png and b/testing/testcafe/tests/navigation/drawer/etalons/drawer_push_shading_FileManager_#popup1.png differ
diff --git a/testing/testcafe/tests/navigation/drawer/etalons/drawer_shrink_shading_FileManager_#container.png b/testing/testcafe/tests/navigation/drawer/etalons/drawer_shrink_shading_FileManager_#container.png
index 235ed1e31315..4a5059e641c8 100644
Binary files a/testing/testcafe/tests/navigation/drawer/etalons/drawer_shrink_shading_FileManager_#container.png and b/testing/testcafe/tests/navigation/drawer/etalons/drawer_shrink_shading_FileManager_#container.png differ
diff --git a/testing/testcafe/tests/navigation/drawer/etalons/drawer_shrink_shading_FileManager_#popup1.png b/testing/testcafe/tests/navigation/drawer/etalons/drawer_shrink_shading_FileManager_#popup1.png
index 82f1fb95a514..d82a8c003420 100644
Binary files a/testing/testcafe/tests/navigation/drawer/etalons/drawer_shrink_shading_FileManager_#popup1.png and b/testing/testcafe/tests/navigation/drawer/etalons/drawer_shrink_shading_FileManager_#popup1.png differ
diff --git a/testing/testcafe/tests/navigation/menu/etalons/Items mode with link focus (generic-light).png b/testing/testcafe/tests/navigation/menu/etalons/Items mode with link focus (generic-light).png
new file mode 100644
index 000000000000..dcf8f05cb624
Binary files /dev/null and b/testing/testcafe/tests/navigation/menu/etalons/Items mode with link focus (generic-light).png differ
diff --git a/testing/testcafe/tests/navigation/menu/etalons/Items mode with link focus (material-blue-light).png b/testing/testcafe/tests/navigation/menu/etalons/Items mode with link focus (material-blue-light).png
new file mode 100644
index 000000000000..16e35dfa6046
Binary files /dev/null and b/testing/testcafe/tests/navigation/menu/etalons/Items mode with link focus (material-blue-light).png differ
diff --git a/testing/testcafe/tests/navigation/menu/etalons/Items should have links if item.url is set (generic-light).png b/testing/testcafe/tests/navigation/menu/etalons/Items should have links if item.url is set (generic-light).png
index e0aa630ef698..25f4d919d252 100644
Binary files a/testing/testcafe/tests/navigation/menu/etalons/Items should have links if item.url is set (generic-light).png and b/testing/testcafe/tests/navigation/menu/etalons/Items should have links if item.url is set (generic-light).png differ
diff --git a/testing/testcafe/tests/navigation/menu/etalons/Items with link and icon focus (generic-light).png b/testing/testcafe/tests/navigation/menu/etalons/Items with link and icon focus (generic-light).png
new file mode 100644
index 000000000000..40f9ad9721e0
Binary files /dev/null and b/testing/testcafe/tests/navigation/menu/etalons/Items with link and icon focus (generic-light).png differ
diff --git a/testing/testcafe/tests/navigation/menu/etalons/Items with link and icon focus (material-blue-light).png b/testing/testcafe/tests/navigation/menu/etalons/Items with link and icon focus (material-blue-light).png
new file mode 100644
index 000000000000..1c893e76120e
Binary files /dev/null and b/testing/testcafe/tests/navigation/menu/etalons/Items with link and icon focus (material-blue-light).png differ
diff --git a/testing/testcafe/tests/navigation/menu/etalons/Items with link should have correct focus style (generic-light).png b/testing/testcafe/tests/navigation/menu/etalons/Items with link should have correct focus style (generic-light).png
index df888dd30c65..212eebfe66fe 100644
Binary files a/testing/testcafe/tests/navigation/menu/etalons/Items with link should have correct focus style (generic-light).png and b/testing/testcafe/tests/navigation/menu/etalons/Items with link should have correct focus style (generic-light).png differ
diff --git a/testing/testcafe/tests/navigation/menu/etalons/Items with links (generic-light).png b/testing/testcafe/tests/navigation/menu/etalons/Items with links (generic-light).png
new file mode 100644
index 000000000000..dbb4e088cb00
Binary files /dev/null and b/testing/testcafe/tests/navigation/menu/etalons/Items with links (generic-light).png differ
diff --git a/testing/testcafe/tests/navigation/menu/etalons/Items with links (material-blue-light).png b/testing/testcafe/tests/navigation/menu/etalons/Items with links (material-blue-light).png
new file mode 100644
index 000000000000..f1f0805c8dec
Binary files /dev/null and b/testing/testcafe/tests/navigation/menu/etalons/Items with links (material-blue-light).png differ
diff --git a/testing/testcafe/tests/navigation/menu/etalons/Items without link should have correct focus style (generic-light).png b/testing/testcafe/tests/navigation/menu/etalons/Items without link should have correct focus style (generic-light).png
index 6dddfd901ede..df11a50df260 100644
Binary files a/testing/testcafe/tests/navigation/menu/etalons/Items without link should have correct focus style (generic-light).png and b/testing/testcafe/tests/navigation/menu/etalons/Items without link should have correct focus style (generic-light).png differ
diff --git a/testing/testcafe/tests/navigation/menu/etalons/Items without links (generic-light).png b/testing/testcafe/tests/navigation/menu/etalons/Items without links (generic-light).png
new file mode 100644
index 000000000000..7c4afcdd7cc0
Binary files /dev/null and b/testing/testcafe/tests/navigation/menu/etalons/Items without links (generic-light).png differ
diff --git a/testing/testcafe/tests/navigation/menu/etalons/Items without links (material-blue-light).png b/testing/testcafe/tests/navigation/menu/etalons/Items without links (material-blue-light).png
new file mode 100644
index 000000000000..e9a7fde8da90
Binary files /dev/null and b/testing/testcafe/tests/navigation/menu/etalons/Items without links (material-blue-light).png differ
diff --git a/testing/testcafe/tests/navigation/menu/link.ts b/testing/testcafe/tests/navigation/menu/link.ts
index 771c1d02b846..90d621f4ac31 100644
--- a/testing/testcafe/tests/navigation/menu/link.ts
+++ b/testing/testcafe/tests/navigation/menu/link.ts
@@ -73,3 +73,73 @@ test('Items should have links if item.url is set', async (t) => {
}],
}, '#menu');
});
+
+test('Adaptive mode: items should have links if item.url is set', async (t) => {
+ const { takeScreenshot, compareResults } = createScreenshotsComparer(t);
+ const menu = new Menu(true);
+
+ await t.click(menu.getHamburgerButton())
+ .click(menu.items(0));
+
+ await testScreenshot(t, takeScreenshot, 'Items with links.png', { element: '#container' });
+
+ await t.pressKey('down');
+
+ await testScreenshot(t, takeScreenshot, 'Items without links.png', { element: '#container' });
+
+ await t
+ .pressKey('down')
+ .pressKey('down');
+
+ await testScreenshot(t, takeScreenshot, 'Items with link and icon focus.png', { element: '#container' });
+
+ await t.pressKey('down');
+
+ await testScreenshot(t, takeScreenshot, 'Items mode with link focus.png', { element: '#container' });
+
+ await t
+ .expect(compareResults.isValid())
+ .ok(compareResults.errorMessages());
+}).before(async () => {
+ await appendElementTo('#container', 'div', 'menu');
+
+ await setAttribute('#container', 'style', 'width: 200px; height: 400px;');
+
+ return createWidget('dxMenu', {
+ displayExpr: 'name',
+ adaptivityEnabled: true,
+ items: [{
+ id: '1',
+ name: 'Items',
+ items: [{
+ id: '1-1',
+ name: 'Item 1',
+ }, {
+ id: '1-2',
+ icon: 'more',
+ }, {
+ id: '1-3',
+ name: 'Item 2',
+ icon: 'unlock',
+ url: 'https://js.devexpress.com/',
+ }, {
+ id: '1-4',
+ name: 'Item 3',
+ url: 'https://js.devexpress.com/',
+ }],
+ },
+ {
+ id: '2',
+ name: 'Items',
+ },
+ {
+ id: '3',
+ name: 'Items',
+ },
+ {
+ id: '4',
+ name: 'Items',
+ },
+ ],
+ }, '#menu');
+});
diff --git a/testing/tests/DevExpress.ui.widgets/menu.tests.js b/testing/tests/DevExpress.ui.widgets/menu.tests.js
index b0831d484287..53897d18dcdf 100644
--- a/testing/tests/DevExpress.ui.widgets/menu.tests.js
+++ b/testing/tests/DevExpress.ui.widgets/menu.tests.js
@@ -54,6 +54,7 @@ const DX_TREEVIEW_ITEM_CLASS = DX_TREEVIEW_CLASS + '-item';
const DX_STATE_FOCUSED_CLASS = 'dx-state-focused';
const DX_STATE_ACTIVE_CLASS = 'dx-state-active';
+const ITEM_URL_CLASS = 'dx-item-url';
const CLICKTIMEOUT = 51;
const ANIMATION_TIMEOUT = 100;
@@ -2497,7 +2498,7 @@ QUnit.module('adaptivity: behavior', {
{
text: 'item2',
items: [
- { text: 'item2-1' },
+ { text: 'item2-1', url: 'http://some_url_item_2-1', linkAttr: { target: '_blank' } },
{ text: 'item2-2' }
]
}];
@@ -2508,6 +2509,80 @@ QUnit.module('adaptivity: behavior', {
fx.off = false;
}
}, () => {
+ QUnit.test('link attributes should be set correctly (T1181342)', function(assert) {
+ new Menu(this.$element, {
+ items: this.items,
+ adaptivityEnabled: true
+ });
+
+ const $item = this.$element.find(`.${DX_TREEVIEW_ITEM_CLASS}`).eq(1);
+
+ $($item).trigger('dxclick');
+
+ const itemWithAttributes = $(`.${ITEM_URL_CLASS}`)[0];
+
+ assert.strictEqual(itemWithAttributes.getAttribute('href'), 'http://some_url_item_2-1');
+ assert.strictEqual(itemWithAttributes.getAttribute('target'), '_blank');
+ });
+
+ QUnit.test('link should be clicked programmatically if item.url is set', function(assert) {
+ const clickSpy = sinon.spy();
+
+ new Menu(this.$element, {
+ items: this.items,
+ adaptivityEnabled: true
+ });
+
+ const parentTreeviewItem = $(`.${DX_TREEVIEW_ITEM_CLASS}`).eq(1);
+
+ parentTreeviewItem.trigger('dxclick');
+
+ const treeviewItem = $(`.${DX_TREEVIEW_ITEM_CLASS}`).eq(2);
+ const urlItem = $(`.${ITEM_URL_CLASS}`)[0];
+ urlItem.click = clickSpy;
+
+ treeviewItem.trigger('dxclick');
+
+ assert.ok(clickSpy.calledOnce);
+ });
+
+ QUnit.test('link should be clicked programmatically with enter key if item.url is set', function(assert) {
+ if(!isDeviceDesktop(assert)) {
+ assert.ok(true);
+ return;
+ }
+
+ const clickSpy = sinon.spy();
+
+ new Menu(this.$element, {
+ items: [
+ { text: 'item1' },
+ {
+ text: 'item2', url: 'http://url2',
+ items: [
+ { text: 'item2-1' },
+ { text: 'item2-2' }
+ ]
+ }],
+ adaptivityEnabled: true
+ });
+
+ const $hamburgerButton = $(`.${DX_ADAPTIVE_HAMBURGER_BUTTON_CLASS}`);
+ const $treeview = $(`.${ DX_TREEVIEW_CLASS}`);
+ const keyboard = keyboardMock($treeview);
+
+ $hamburgerButton.trigger('dxclick');
+ $treeview.trigger('focusin');
+
+ const urlItem = $treeview.find(`.${ITEM_URL_CLASS}`)[0];
+ urlItem.click = clickSpy;
+
+ keyboard.press('down')
+ .press('enter');
+
+ assert.ok(clickSpy.calledOnce);
+ });
+
QUnit.test('Adaptive menu should be shown when hamburger button clicked', function(assert) {
new Menu(this.$element, {
items: this.items,
diff --git a/testing/tests/DevExpress.ui.widgets/menuBase.tests.js b/testing/tests/DevExpress.ui.widgets/menuBase.tests.js
index 35eb57c21316..2214d150394d 100644
--- a/testing/tests/DevExpress.ui.widgets/menuBase.tests.js
+++ b/testing/tests/DevExpress.ui.widgets/menuBase.tests.js
@@ -47,7 +47,7 @@ const DX_ITEM_HAS_TEXT = DX_MENU_ITEM_CLASS + '-has-text';
const DX_ITEM_HAS_ICON = DX_MENU_ITEM_CLASS + '-has-icon';
const DX_ITEM_HAS_SUBMENU = DX_MENU_ITEM_CLASS + '-has-submenu';
-const DX_ITEM_URL_CLASS = 'dx-item-url';
+const ITEM_URL_CLASS = 'dx-item-url';
const DX_MENU_ITEM_TEXT_URL_CLASS = `${DX_MENU_ITEM_TEXT_CLASS}-with-url`;
const DX_ICON_WITH_URL_CLASS = `${DX_ICON_CLASS}-with-url`;
@@ -375,7 +375,7 @@ QUnit.module('Menu rendering', () => {
});
const content = menuBase.element.find(`.${DX_MENU_ITEM_CONTENT_CLASS}`).children();
- assert.ok(content.hasClass(DX_ITEM_URL_CLASS));
+ assert.ok(content.hasClass(ITEM_URL_CLASS));
assert.ok(content.children().hasClass(DX_MENU_ITEM_TEXT_URL_CLASS));
});
@@ -384,7 +384,7 @@ QUnit.module('Menu rendering', () => {
items: [{ icon: 'save', url: '/some_url' }]
});
- const icon = menuBase.element.find(`.${DX_ITEM_URL_CLASS}`).children();
+ const icon = menuBase.element.find(`.${ITEM_URL_CLASS}`).children();
assert.ok(icon.hasClass(DX_ICON_WITH_URL_CLASS));
});
@@ -491,7 +491,7 @@ QUnit.module('Menu rendering', () => {
});
const $menuItemLink = menuBase.element
- .find(`.${DX_ITEM_URL_CLASS}`)
+ .find(`.${ITEM_URL_CLASS}`)
.get(0);
$menuItemLink.click = clickSpy;
@@ -512,7 +512,7 @@ QUnit.module('Menu rendering', () => {
});
const $menuItemLink = menuBase.element
- .find(`.${DX_ITEM_URL_CLASS}`)
+ .find(`.${ITEM_URL_CLASS}`)
.get(0);
$menuItemLink.click = clickSpy;
@@ -1127,7 +1127,7 @@ QUnit.module('Keyboard navigation', () => {
});
const menuItem = menuBase.element
- .find(`.${DX_ITEM_URL_CLASS}`)
+ .find(`.${ITEM_URL_CLASS}`)
.get(0);
menuItem.click = clickSpy;