Hey guys,
I have a kendo menu via ASP.NET Core:
<kendo-menu name="menuNavigation">
<scrollable enabled="true" />
<items>
<menu-item text="Einstellungen">
<sub-items>
<menu-item asp-action="Index" asp-controller="Einstellungen" text="Fahneneinstellungen & Preise"></menu-item>
<menu-item asp-action="Archiv" asp-controller="@Namings.Data.Loan" text="Archivierte @Namings.Data.Loans"></menu-item>
</sub-items>
</menu-item>
</items>
</kendo-menu>
What I'm trying to achieve is to make a mouseover event over the "Einstellungen" menu item, that it opens the underlying menu (I think you call these sub menu items "options"). Then I want to navigate the mouse to the sub menu item and click on that, triggering a link and change the browsers url.
KendoMenu menu = Pages.Home.MenuNavigation;
KendoMenuItem menuItemSettings = menu.AllMenus.SingleOrDefault(x => x.MenuItemTitle == "Einstellungen");
menuItemSettings.MouseHover();
Wait.For(x => menuItemSettings.AllOptions.Count > 0, menuItemSettings, 5000); // running into a timeout, because menuItemSettings.AllOptions always 0
KendoMenuOption menuOptionSettings = menuItemSettings.AllOptions.SingleOrDefault(x => x.MenuOptionTitle == "Fahneneinstellungen & Preise");
menuOptionSettings.MouseClick();
ActiveBrowser.WaitForUrl(Pages.Settings.Url, false, 10000);
With my code I can achieve already moving the mouse to the menu item and hovering over it, but the I'm getting a timeout in the wait step. Indeed the menu item's "AllOptions" property always remain "0". Although in the testing browser the mouse is successfully hovering over the kendo menu and it actually opens the submenu, in code these submenu items are never recognized.
Am I doing something wrong? Or do you have some better solution for me to achieve this behavior?
Test Studio version 2022.2.804 and I'm using the VS 2019 extension.
1 Answer, 1 is accepted
Hello Daniel,
Thank you for sharing details about your test scenario and the encountered issue. I have a suggestion for you that might help you with that.
I assume that the sub menu elements do not exist in the DOM tree at all times. They probably only appear once you hover over with the mouse and the menu is expanded. In this case, you might need to give them some time and refresh the DOM tree that Test Studio uses to interact with elements. Try out the code snipper below right after the MouseHover() method.
System.Threading.Thread.Sleep(2000); ActiveBrowser.RefreshDomTree();
If that works, you can reduce or remove the execution delay of 2000 msec, until the test is stable.
Another option for you us to use the Find class's methods to identify the elements in the DOM tree. There are options that allow you to look for all elements under single condition. Then, you can iterate them and click the one you need.
In case the issue persists, please share the updated code from your test and the DOM tree of the application with and without the expanded menu. It would be nicer, if the application under test is publicly accessible, or if you have a demo I can work with.
I hope the above details and suggestions are helpful.
Regards,
Plamen Mitrev
Progress Telerik
Hey,
indeed the submenu items aren't visible in DOM while initial loading the page.
<nav class="m-auto">
<div class="k-menu-scroll-wrapper k-horizontal" style="width: 824px;">
<ul id="menuNavigation" name="menuNavigation" data-role="menu" class="k-widget k-reset k-menu k-menu-horizontal" aria-orientation="horizontal" tabindex="0" role="menubar">
<span class="k-link k-menu-link">Einstellungen<span class="k-menu-expand-arrow"><span class="k-menu-expand-arrow-icon k-icon k-i-arrow-s"></span></span></span>
<ul class="k-group k-menu-group k-menu-group-md" role="menu" style="display: none;" aria-hidden="true">
<li class="k-item k-menu-item k-first" role="menuitem"><a class="k-link k-menu-link" href="/fahnenlager/Einstellungen">Fahneneinstellungen & Preise</a></li>
</ul>
</li>
</ul>
</div>
</nav>
After the first hover event the DOM elements are created, as you described.
<nav class="m-auto">
<div class="k-menu-scroll-wrapper k-horizontal" style="width: 824px;">
<ul id="menuNavigation" name="menuNavigation" data-role="menu" class="k-widget k-reset k-menu k-menu-horizontal" aria-orientation="horizontal" tabindex="0" role="menubar">
<span class="k-link k-menu-link">Einstellungen<span class="k-menu-expand-arrow"><span class="k-menu-expand-arrow-icon k-icon k-i-arrow-s"></span></span></span>
<ul class="k-group k-menu-group k-menu-group-md" role="menu" style="display: none;" aria-hidden="true">
<li class="k-item k-menu-item k-first" role="menuitem"><a class="k-link k-menu-link" href="/fahnenlager/Einstellungen">Fahneneinstellungen & Preise</a></li>
</ul>
</li>
</ul>
<div class="k-animation-container" role="region" style="width: 275px; overflow: hidden; display: none; position: absolute; height: 66px; box-sizing: content-box; z-index: 10002; top: 48px; left: 690.656px;" aria-hidden="true">
<ul class="k-group k-menu-group k-menu-group-md k-popup k-reset" role="menu" style="display: none; max-height: 924px; overflow: auto; position: absolute; font-size: 16px; font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-stretch: 100%; font-style: normal; font-weight: 400; line-height: 24px; transform: translateY(-66px);" data-role="popup" data-group="1662550216400" aria-hidden="true">
<li class="k-item k-menu-item k-first" role="menuitem"><a class="k-link k-menu-link" href="/fahnenlager/Einstellungen">Fahneneinstellungen & Preise</a></li>
</ul>
</div>
</div>
</nav>
But unfortunately the sleep did'nt help to fill the "AllOptions" property, it's still empty. And yes, I can search the submenu item's manually through the DOM and I will find them by checking the anchor-element's inner text value,
but since the KendoMenuItem class contains the "AllOptions" property I tried to use it in some way. Now if the property is always empty (IList<KendoMenuOption> has 0 counts), how's actually the purpose of the property?
Hi Daniel, thank for trying the suggestion. I have an update on the case that I tested against the demo page here.
The sleep is indeed necessary, because of the dynamic behavior of the page and KendoMenu component. On top of that in this case you need to refresh the "menuItemSettings" object, because it is different after the MouseHover action. I update your code snippet to match the menu from the demo, but the flow should be the same for your application and its component. Check out the code snippet below and let me know if you have any follow up questions or concerns.
ActiveBrowser.RefreshDomTree(); Telerik.TestingFramework.Controls.KendoUI.KendoMenu menu = Pages.DemoForCoreFeaturesIn.MenuUnorderedList; Telerik.TestingFramework.Controls.KendoUI.KendoMenuItem menuItemSettings = menu.AllMenus.SingleOrDefault(x => x.MenuItemTitle == "Products"); menuItemSettings.MouseHover(); System.Threading.Thread.Sleep(2000); menuItemSettings.Refresh(); Wait.For(x => menuItemSettings.AllOptions.Count > 0, menuItemSettings, 5000); KendoMenuOption menuOptionSettings = menuItemSettings.AllOptions.SingleOrDefault(x => x.MenuOptionTitle == "Decor"); menuOptionSettings.MouseClick();
Best regards,
Plamen
Hi Plamen,
I could run your test successfully on the demo page aswell. But not on mine.
Therefore I checked the kendo menu html of both and here we can see, that the menu on the demo page has a different html structure then mine! Hmm, seem's that the different structure causes the problems here.
<ul class="k-widget k-reset k-header k-menu k-menu-horizontal" id="Menu">
<li class="k-item k-menu-item k-first" aria-haspopup="true" aria-expanded="false" role="menuitem" style="z-index: auto;" id="Menu_mn_active">
<span class="k-link k-menu-link"><span class="k-menu-link-text">Products</span><span class="k-menu-expand-arrow"><span class="k-menu-expand-arrow-icon k-icon k-i-arrow-s"></span></span></span>
<div class="k-animation-container" style="width: 98px; height: 114px; overflow: hidden; display: none; position: absolute; z-index: 10002; top: 32px; left: 0px;" aria-hidden="true">
<ul class="k-group k-menu-group k-reset k-menu-group-md k-popup" role="menu" style="display: none; position: absolute; font-size: 14px; font-family: Arial, Helvetica, sans-serif; font-stretch: 100%; font-style: normal; font-weight: 400; line-height: 20px; transform: translateY(-114px);" data-role="popup" aria-hidden="true">
<li class="k-item k-menu-item" role="menuitem">
<span class="k-link k-menu-link"><span class="k-menu-link-text">Decor</span><span class="k-menu-expand-arrow"><span class="k-menu-expand-arrow-icon k-icon k-i-arrow-e"></span></span></span>
<div class="k-animation-container" role="region">
<ul class="k-group k-menu-group k-reset k-menu-group-md k-popup" role="menu">
<li class="k-item k-menu-item k-first" role="menuitem"><span class="k-link k-menu-link"><span class="k-menu-link-text">Bed Linen</span></span></li>
<li class="k-item k-menu-item" role="menuitem"><span class="k-link k-menu-link"><span class="k-menu-link-text">Throws</span></span></li>
<li class="k-item k-menu-item" role="menuitem"><span class="k-link k-menu-link"><span class="k-menu-link-text">Curtains & Blinds</span></span></li>
<li class="k-item k-menu-item" role="menuitem"><span class="k-link k-menu-link"><span class="k-menu-link-text">Rugs</span></span></li>
<li class="k-item k-menu-item k-last" role="menuitem"><span class="k-link k-menu-link"><span class="k-menu-link-text">Carpets</span></span></li>
</ul>
</div>
</li>
</ul>
</div>
</li>
</ul>
As you can see in the highlighted markup, the "k-animation-container" is inside the <ul> element. On the opposite my menu is rendered inside a <div> surrounding everything and the <ul> is separated from the "k-animation-container". Just compare my rendered html code in the first comment and the upper from demo page. I'm using Kendo UI version 2022.2.510, so pretty up to date.
Maybe the tag helper syntax renders the menu in a different way. I will rewrite my menu in default html helper syntax and I'll give you notice.
Yes, the kendo menu will be rendered differently whether you choose the tag helper or the html helper syntax in .NET Core.
<kendo-menu name="menuNavigation">
<scrollable enabled="true" />
<items>
<menu-item text="Bedienung">
<sub-items>
<menu-item text="Bedienungshilfe"></menu-item>
<menu-item text="Benutzerhandbuch"></menu-item>
</sub-items>
</menu-item>
</items>
</kendo-menu>
@(Html.Kendo().Menu()
.Name("menuNavigation2")
.Items(items =>
{
items.Add()
.Text("Bedienung")
.Items(children =>
{
children.Add().Text("Bedienungshilfe");
children.Add().Text("Benutzerhandbuch");
});
})
)
Output:
// Tag helper syntax
<div class="k-menu-scroll-wrapper k-horizontal">
<ul id="menuNavigation" name="menuNavigation" data-role="menu" class="k-widget k-reset k-menu k-menu-horizontal" tabindex="0" role="menubar">
<li aria-haspopup="true" aria-expanded="false" class="k-item k-menu-item k-first k-last" role="menuitem" data-groupparent="1662718092685"><span class="k-link k-menu-link">Bedienung<span class="k-menu-expand-arrow"><span class="k-menu-expand-arrow-icon k-icon k-i-arrow-s"></span></span></span>
</li>
</ul>
<span class="k-button k-button-md k-rounded-md k-button-solid k-button-solid-base k-icon-button k-menu-scroll-button k-scroll-left" unselectable="on"><span class="k-button-icon k-icon k-i-arrow-60-left"></span></span><span class="k-button k-button-md k-rounded-md k-button-solid k-button-solid-base k-icon-button k-menu-scroll-button k-scroll-right" unselectable="on"><span class="k-button-icon k-icon k-i-arrow-60-right"></span></span>
<div class="k-animation-container" role="region">
<ul class="k-group k-menu-group k-menu-group-md k-popup k-reset" role="menu">
<li class="k-item k-menu-item k-first" role="menuitem"><a class="k-link k-menu-link" href="/fruehehilfen/Home/Bedienungshilfe">Bedienungshilfe</a></li>
<li class="k-item k-menu-item k-last" role="menuitem"><a class="k-link k-menu-link" href="/fruehehilfen/Home/Benutzerhandbuch">Benutzerhandbuch</a></li>
</ul>
</div>
</div>
// Html helper syntax
<ul class="k-widget k-reset k-header k-menu k-menu-horizontal" id="menuNavigation2" data-role="menu" tabindex="0" role="menubar">
<li class="k-item k-menu-item k-first k-last" aria-haspopup="true" aria-expanded="false" role="menuitem">
<span class="k-link k-menu-link"><span class="k-menu-link-text">Bedienung</span><span class="k-menu-expand-arrow"><span class="k-menu-expand-arrow-icon k-icon k-i-arrow-s"></span></span></span>
<div class="k-animation-container" role="region">
<ul class="k-group k-menu-group k-reset k-menu-group-md k-popup" role="menu">
<li class="k-item k-menu-item k-first" role="menuitem"><span class="k-link k-menu-link"><span class="k-menu-link-text">Bedienungshilfe</span></span></li>
<li class="k-item k-menu-item k-last" role="menuitem"><span class="k-link k-menu-link"><span class="k-menu-link-text">Benutzerhandbuch</span></span></li>
</ul>
</div>
</li>
</ul>
Thank you for your detailed responses and result from your investigation, Daniel. The Tag helper syntax is not actually supported by the Kendo translators from Test Studio and I created a public feature request on your behalf to investigate this further and plan it for future releases. You can vote for and follow the public item to get notifications for its progress.
We have only covered the Html helper syntax in the current version of translators. Since there is different structure of the element in the DOM tree, the options are not taken properly and will return and empty collection. This missing feature is on the Test Studio side and we will consider extending the functionality, if it is possible. In the meantime, you need to either render the Kendo Menu in Html helper syntax or use the methods in the Find class to get all options and iterate them.
I am sorry for the inconvenience and I thank you for starting this discussion. I hope that the workarounds above are something you can consider in your test automation. Of course, I remain available to continue the conversation.
Alright, thank you for creating the request. In my opinion somehow odd that tag helper syntax is rendering the same element in a different way. I thought it should be the same output with both syntax but okay.
I'll keep the tag helper syntax because it's way more user friendly and all of my elements are rendered by tag helper syntax. For the submenu items I will write a custom find expression.
The difference in rendering comes from the Kendo Menu control. Since both renderings are valid and working, we will consider to cover them both in the automation scenario within the context of our translators.
I would understand that you do not want to change the application, so the next best options is really to create custom find expressions. Let me know if you encounter any troubles there.