I'm using the latest version of Selenium and the chromedriver to test a ZK application.
During the test, I'd like to dump the DOM (or part of it) to help me find the elements I need (and probably help people who have to maintain the test).
The method WebDriver.getPageSource() looked promising but it only returns the HTML as it was sent by the server, not the result after running all the JavaScript code.
The JavaScript code is run; I can find elements by ID that I can't see in the output of getPageSource(). So I tried WebElement.getText() but that is only the text of the elements, not the elements themselves or their attributes.
Is it possible at all to get the DOM or do I have to do keyhole surgery here?
I have the same question really but the only way I've found to do it is ExecuteScript:
/// <summary>
/// Gets the parentElement/Node of a particular element
/// </summary>
/// <param name="driver"></param>
/// <param name="element"></param>
/// <returns></returns>
public static IWebElement GetElementParent(IWebDriver driver,IWebElement element)
{
return (IWebElement) ((IJavaScriptExecutor)driver).ExecuteScript("return arguments[0].parentNode", element);
}
why the By doesnt support By.DOM with a function I don't really know...I suspect its due to the need for a webdriver for multiple browsers etc
Related
How do I show a list of items created using a SmartForm in Ektron Version: 9.00 SP3(Build 9.0.0.249)?
I created a SmartForm where users can put in details of job positions available. Now I want to display those positions in a list i.e. jobs available. Then when they click on a link it takes them to the details of that job.
I have zero experience with Ektron so I hope this isn't a silly question and I need stuff broken down to pretty basic levels.
EDIT: You can find this and more in-depth information on using strongly typed objects with Ektron Smart Forms at Thomas Higginbotham's blog.
POST:
The example I'm creating below is for output of images in a list, as though I were going to make a gallery. Keep in mind that there are other things I would do when actually creating a gallery, so this is by no means completed code in that regard. It is, however, a very good and simple illustration for how to retrieve and handle content from Ektron in the most .NET way possible (without a lot more separation of concerns).
First, I have some recommended reading for you. Ken McAndrew (long-time Ektron dev and now Sitecore dev) put together a nice set of posts about a class you can use to obtain Ektron's Smart Form content as .NET objects, making them much easier to work with. I recommend using Ken's version of the class (link within the blog post).
There's also a hangout featuring Bill Cava, original author of the method, Ken, and myself talking about this approach, which might help.
I looked and I think the original webinar has been taken down.
Regardless, once you have the Content Types code in place, it's relatively simple. You want to:
Create .NET models for your Smart Forms
Get the items
Map them to a ViewModel (optional)
Databind them to a ListView or Repeater control
Creating .NET Models for Smart Forms
To start this, I've created a rather simple Smart Form for a Press Photo. It contains three fields:
Name
Description (Caption)
Image (stored as a URL string for simplicity, not as an <img /> tag)
Next, click the "XSD" button in the SmartForm Data Design View (where you add/manage the fields) and copy all the XSD code. (You'll see the XSD button in the screenshot below, immediately above the modal.)
Save that to a file. I created a folder at C:\ContentTypes and added the file as PressPhoto.xsd there.
You'll want to run a file called XSD.exe (provided and documented by Microsoft as part of most Visual Studio installations). This will use the XSD and generate a C# class file for you - one that's friendly for deserializing the Smart Form XML into a .NET object.
Here's where to find it (as included with Visual Studio 2015):
However, running it from the command line is something I find painful since I always forget the rather lengthy path for it. So I created a Batch file to do most of the dirty work for me. I wrote it to accept three parameters, in order:
The path to the XSD file
The output path where I'd like to store the generated class file
The namespace I want for the generated class (tip: I always set the Namespace to include the name of the Smart Form - this prevents conflicts if you're generating classes for multiple Smart Forms)
Here's the code and a screenshot of the command to execute it.
#ECHO OFF
SET xsdExePath="C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools\xsd.exe"
SET xsdFilePath="%~f1"
SET outFolderPath="%~f2"
SET ns=%3
%xsdExePath% /c %xsdFilePath% /o:%outFilePath% /l:CS /n:%ns%
This generates a file named PressPhoto.cs within my C:\ContentTypes\ directory.
Going into my Ektron project, I'm going to add Ken's SmartForm class (referenced in his blog above) and my new PressPhoto class within a directory in my App_Code folder. Like so (folder structure beneath App_Code/CSCode is up to you, but keep it organized for your own sanity):
Add a class for each Smart Form you want to pull via API (for me, that's all Smart Forms).
I know this is seemingly a lot of prep, and compared to some other, more modern systems, it is. But this will help you immensely once you're in the habit.
Get the Items (and Map to a ViewModel)
Now that you've basically created your own APIs for getting the items (the alternative is XML Transforms, btw), you're ready to use them.
I prefer to create my own "Manager" class as well as ViewModel. If you'd prefer a different approach, then this will at least give you the sample code to move in your own direction.
I'm putting comments about the code in-line so you can read them in context.
View Model - very basic
namespace MyProject.ViewModels
{
/// <summary>
/// Provides the fields necessary to display a PressPhoto Smart Form to the site.
/// </summary>
public class PressPhotoViewModel
{
public string Title { get; set; }
public string Description { get; set; }
public string ImageUrl { get; set; }
public string ContentUrl { get; set; }
public long ContentId { get; set; }
public PressPhotoViewModel()
{
}
}
}
And the "Manager" class so I put as little code into the code-behinds as possible. A nice, centralized location for all my PressPhoto logic.
using Ektron.Cms;
using Ektron.Cms.Content;
using Ektron.Cms.Common;
using Ektron.Cms.Framework.Custom;
using MyProject.SmartForms.PressPhoto;
using MyProject.ViewModels;
using System.Collections.Generic;
using System.Linq;
namespace MyProject.Managers
{
/// <summary>
/// Provides CRUD operations for managing PressPhoto objects within the CMS.
/// </summary>
public class PressPhotoManager
{
/*
* "root" is the default root element of the Smart Form XML.
*
* If you've changed this, your code will be different. Most people don't,
* so I'm going with the lowest-common-denominator example.
*
* I normally set the "root" to something else, and thus give it a more
* meaningful class name. I also tend to load this manager via something more
* similar to a singleton, but for simplicity's sake...
*/
private SmartFormManager<root> pressPhotoManager = new SmartFormManager<root>();
public PressPhotoManager()
{
// Nothing needs done here for this example.
}
/*
* Usually, I'm not interested in writing information back to the DB, so
* I'm only going to include samples for GetItem and GetList (by folder) here.
*/
/// <summary>
/// Retrieves a PressPhoto item by its Ektron Content ID
/// </summary>
/// <param name="ContentId">Ektron Smart Form Content Id</param>
/// <returns>Press Photo ViewModel for display</returns>
public PressPhotoViewModel GetItem(long ContentId)
{
/*
* Get items - this returns an object that is the amalgamation of the standard
* Ektron ContentData object and the deserialized Smart Form information.
*
* The format is:
* * systemObject.Content = standard ContentData fields
* * systemOjbect.SmartForm = Smart Form fields
*
* For some reason, the returned object in the custom class inherits from ContentData.
* This inheritance is probably not necessary and is also likely confusing. So only try
* to use the fields within the containers listed above.
*/
var systemObject = pressPhotoManager.GetItem(ContentId, false);
if (systemObject == null) return null;
/*
* I often want to map both Smart Form and ContentData fields to my output. This is where
* a ViewModel comes in handy - it normalizes the data to be rendered. So then I'm not
* dealing with object.Content.* and object.SmartForm.* during rendering.
*
* Another note: You might consider putting this mapping into a constructor in
* the ViewModel in order to avoid the repetition you'll find in the GetList method
* below.
*/
return new PressPhotoViewModel()
{
ContentId = systemObject.Content.Id,
ContentUrl = systemObject.Content.Quicklink,
Title = systemObject.SmartForm.Name,
Description = systemObject.SmartForm.Caption,
ImageUrl = systemObject.SmartForm.Photo
};
}
/// <summary>
/// Retrieves a list of PressPhoto by the containing Ektron Folder Id (non-recursive)
/// </summary>
/// <param name="FolderId">Ektron Folder Id</param>
/// <returns>Enumerable of Press Photo ViewModel for display</returns>
public IEnumerable<PressPhotoViewModel> GetList(long FolderId)
{
/*
* There are several "Criteria" objects. This is the simplist, but they also exist
* for retrieving items from a Collection, from Taxonomy, or given a certain
* Metadata property value.
*/
var criteria = new ContentCriteria();
// Filter tells the API which folder to retrieve content from.
criteria.AddFilter(ContentProperty.FolderId, CriteriaFilterOperator.EqualTo, FolderId);
// Don't check sub-folders.
criteria.FolderRecursive = false;
/*
* Retrieve only 12. The default is 50. Get in the habit of setting this so you
* don't grab 50 when you only need one.
*/
criteria.PagingInfo = new PagingInfo(12);
// Only return metadata when you need it, for performance. Default here is false.
criteria.ReturnMetadata = false;
// Ordering FTW! Hopefully self-explanatory.
criteria.OrderByField = ContentProperty.Title;
criteria.OrderByDirection = EkEnumeration.OrderByDirection.Ascending;
// Same as above...
var systemObjectList = pressPhotoManager.GetList(criteria);
if (systemObjectList == null || !systemObjectList.Any()) return null;
return systemObjectList.Select(p => new PressPhotoViewModel()
{
ContentId = p.Content.Id,
ContentUrl = p.Content.Quicklink,
Title = p.SmartForm.Name,
Description = p.SmartForm.Caption,
ImageUrl = p.SmartForm.Photo
});
}
}
}
Databinding to a List Control
For simplicity, I'm going to put this code into a .NET User Control.
Markup:
<%# Control Language="C#" AutoEventWireup="true" CodeFile="Gallery.ascx.cs" Inherits="Components_Controls_Gallery" %>
<asp:ListView ID="uxPhotoGallery" runat="server" ItemPlaceholderID="itemPlaceholder">
<LayoutTemplate>
<ul>
<asp:PlaceHolder ID="itemPlaceholder" runat="server" />
</ul>
</LayoutTemplate>
<ItemTemplate>
<li>
<%--
I'm mixing up two different ways of referencing the incoming data. One is by casting
the DataItem to the incoming type, which gives you intellisense access to the properties.
The other is more of a dictionary approach in which you have to type out the property name
as a string.
I really like the casting approach, but it's mega-wordy.
--%>
<a href="<%#((MyProject.ViewModels.PressPhotoViewModel)Container.DataItem).ImageUrl %>">
<img src="<%#((MyProject.ViewModels.PressPhotoViewModel)Container.DataItem).ImageUrl %>" alt="<%#Eval("Description") %>" />
<div><%#Eval("Description") %></div>
</a>
</li>
</ItemTemplate>
</asp:ListView>
Code:
using MyProject.Managers;
using System;
using System.Linq;
public partial class Components_Controls_Gallery : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
var pressPhotoManager = new PressPhotoManager();
// Whichever folder Id...
var photos = pressPhotoManager.GetList(75);
if (photos != null && photos.Any())
{
uxPhotoGallery.DataSource = photos;
uxPhotoGallery.DataBind();
}
}
}
And... that should do it. The best way I know how, in any case. There are certainly ways that require less code and prep, but this is by far my preferred as it keeps me working as much as possible with real .NET objects. Though you could use LinqToXML or other techniques, I prefer to not use them as it requires you to develop a lot of your own knowledge of the XML and never reads as well as this, imo.
Happy coding.
For the following comment block, doxygen is not adding a remarks tag to the outputted xml. Is this the correct use of the xml remarks tag in the comments block? It appears to be supported in doxygen : http://www.doxygen.nl/manual/xmlcmds.html
Comment Block:
/// <summary>
/// Returns an AchievementsResult object containing the first page of achievements
/// for a player of the specified title.
/// </summary>
/// <param name="titleId">The title ID.</param>
/// <param name="type">The achievement type to retrieve.</param>
/// <param name="orderby">Controls how the list of achievements is ordered.</param>
/// <param name="skipItems">The number of achievements to skip.</param>
/// <param name="maxItems">The maximum number of achievements the result can contain. Pass 0 to attempt
/// to retrieve all items.</param>
/// <returns>An AchievementsResult object that contains a list of Achievement objects.</returns>
/// <remarks>
/// Returns an IAsyncOperation<TResult> object that represents the state of the asynchronous operation.
/// Completion of the asynchronous operation is signaled by using a handler that is passed to the
/// IAsyncOperation<TResult>.Completed property. When the asynchronous operation is complete, the result of the
/// operation can be retrieved by using the IAsyncOperation<TResult>.GetResults method.
///
/// See AchievementsResult::GetNextAsync to page in the next set of results.
///
/// This method calls V2 GET /users/xuid({xuid})/achievements.
/// </remarks>
Doxygen XML :
...
</simplesect>
</para>
<para>Returns an IAsyncOperation<TResult> object that represents the state of the asynchronous operation. Completion of the asynchronous operation is signaled by using a handler that is passed to the IAsyncOperation<TResult>.Completed property. When the asynchronous operation is complete, the result of the operation can be retrieved by using the IAsyncOperation<TResult>.GetResults method.</para>
<para>See <ref refid="class_d3337fa7a" kindref="member">AchievementsResult::GetNextAsync</ref> to page in the next set of results.</para>
<para>This method calls V2 GET /users/xuid({xuid})/achievements.</para>
</detaileddescription>
Doxygen's XML output follows a different schema than the C# XML input (which doesn't even have a proper schema defined). So <remarks>...</remarks> in the input ends up as a set of paragraphs within the <detaileddescription>...</detaileddescription> container in the output.
React Developer Tools give a lot of power to inspect the React component tree, and look at props, event handlers, etc. However, what I'd really like to do is to be able to inspect those data structures in the browser console.
In chrome I can play with the currently selected DOM element in the console using $0. Is there a way to extract React component info from $0, or is it possible to do something similar with the React Dev Tools?
Using React Developer Tools you can use $r to get a reference to the selected React Component.
The following screenshot shows you that I use React Developer Tools to select a component (Explorer) which has a state-object callednodeList. In the console I can now simply write $r.state.nodeList to reference this object in the state. Same works with the props (eg.: $r.props.path)
An answer to your question can be found here in a similar question I asked:
React - getting a component from a DOM element for debugging
I'm providing an answer here because I don't have the necessary reputation points in order to mark as duplicate or to comment above.
Basically, this is possible if you are using the development build of react because you can leverage the TestUtils to accomplish your goal.
You need to do only two things:
Statically store the root level component you got from React.render().
Create a global debug helper function that you can use in the console with $0 that accesses your static component.
So the code in the console might look something like:
> getComponent($0).props
The implementation of getComponent can use React.addons.TestUtils.findAllInRenderedTree to search for match by calling getDOMNode on all the found components and matching against the passed in element.
Open console (Firefox,Chrome) and locate any reactjs rendered DOM element or alternatively execute js script to locate it:
document.getElementById('ROOT')
Then check for element properties in object property viewer for attributes with name beginning like '__reactInternalInstace$....' expand _DebugOwner and see stateNode.
The found stateNode will contain (if it has) 'state' and 'props' attributes which is used heavily in reactjs app.
Though the accepted answer works, and is a great method, in 2020 you can now do a lot of inspection without using the $r method. The Components tab of React DevTools will show you props and detailed state when you select the relevant component (make sure you're on the right level), as well as let you do other things like suspend it or inspect the matching DOM element (little icons in the top right).
Assign the state or prop object to the window object:
window.title = this.state.title
And then from the dev tools console you can try different methods on the exposed object such as:
window.title.length
8
You can attach a reference to the window object like
import { useSelector } from "react-redux";
function App() {
// Development only
window.store = useSelector((state) => state);
return (
<div className="App">
</div>
);
}
export default App;
Then access it from the console
store
{states: {…}}
states:
someProperty: false
[[Prototype]]: Object
[[Prototype]]: Object
[Console][1]
[1]: https://i.stack.imgur.com/A4agJ.png
I have to pass value dynamically to applet so that it can pick correct xml from resource based on the value selected from the dropdown .
<applet code="com.vaannila.utility.dynamicTreeApplet.class" archive="./appletjars/dynamictree.jar, ./appletjars/prefuse.jar" width ="1000" height="500" >
</applet>
How can i do that .
You can handle this by writing a public method in your applet
let's assume
void setXmlName(String xmlName);
you can access this method from java script .. for example this java script method
function updateXmlName(value){
/* Get an object of the applet .. make sure the at 'id' attribute has the 'myappletid' value. */
var myApplet = documents.applets["myappletid"];
myApplet.setXmlName(value);
}
update your dropbox HTML
<select id="optionList" onchange="updateXmlName(document.getElementById('optionList').value);>
I hope this could help you.
If you choose a value from dropdown and then send it to the page with applet then used simple <param> tag (as described here). If you want to do it dynamically, then you can invoke java methods via javascript as described here.
In an MVC2 view, I can't get tags to work at all. They show up as broken pictures. The tag (created by an Html.ImageFor() extension method that I wrote) is a perfectly valid tag, such as this, which I copied from the page source in IE:
<img alt="Picture Display" src="~/Content/Pictures/IMGP0164 (resized).JPG" />
Note that if I don't use the helper method, and just type an tag, with a correct src URL, that ends up broken as well. If I use an tag instead, with the same src URL, that works fine, and the picture shows up as expected.
So for some reason, righteous tags simply aren't working for me from an MVC2 view. I'm very new to MVC2, but not new to ASP.NET or Html. Is there something about tags, when used in an MVC2 view, that I simply haven't found out about yet?
Thanks in advance for a clue!
Your Html.ImageFor() is broken, because src="~/Content/Pictures/IMGP0164 (resized).JPG" is not a valid URI.
The tilde must be replaced with the virtual path of the site. To do that, you use Url.Content. Since you haven't shown the source for your broken method, I can't fix it, but in plain markup you would write:
<img alt="Picture Display" src="<%= Url.Content("~/Content/Pictures/IMGP0164 (resized).JPG")" />
You can use the same idea inside your helper.
Here's the requested helper method:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Web;
using System.Web.Mvc;
using PictureThis.Models;
namespace System.Web.Mvc.Html
{
public static class ExtensionMethods
{
// HtmlHelper Extensions
/// <summary>
/// Builds an Html image element.
/// </summary>
/// <param name="helper">Required target param</param>
/// <param name="src">Source URL attribute</param>
/// <param name="alt">Alt text attribute</param>
/// <returns></returns>
public static MvcHtmlString ImageFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, string alt)
{
TagBuilder tb = new TagBuilder("img");
Delegate GetSource = expression.Compile();
string source = GetSource.DynamicInvoke(html.ViewData.Model).ToString();
tb.Attributes.Add("src", source);
tb.Attributes.Add("alt", alt);
return MvcHtmlString.Create(tb.ToString(TagRenderMode.SelfClosing));
}
}
}