Building XPATHs for React apps
Recently at Postman we decided to build “In-app Lessons” to provide our users with an unique on-boarding experience. The objective of the lessons is to skill up our users on different features inside Postman.
One of the major part of building this on-boarding system was to have the capability to reference parts of UI so that we can attach popovers while running a lesson.
But the problem here is that these lessons exists separately on a service and Postman app just fetches the required lesson and run it. So we needed to create a way that this service can reliably use to create lesson steps (popovers that are attached to an UI element).
We couldn’t use traditional query selectors or xpaths because they are tightly coupled with the DOM and the way how components are structured. Also there is always this risk that some attributes or elements could be removed during refactoring or implementing new features.
After some brainstorming and POCs we built our own flavour of XPATHS by leveraging React and its context API.
The idea here is to wrap all the components that you want to make referenceable with XPATH Component. What this enabled us to do is create a skeleton structure of our entire app which can be referenced and also allowed developers enough flexibility to build new features without worrying about removing or changing these XPATHs.
<XPATH identifier='app'> //...
<XPATH identifier='sidebar'>
//... </XPATH>
<XPATH identifier='main'>
//... <XPATH identifier='requestSection'>
//... </XPATH>
</XPATH>
</XPATH>
So from above you can see that now we have 4 sections that we can reference and also now developers can add/remove any code that they want without touching these XPATHS. Lets say a lesson step needs to show popover on “requestSection”. The way to reference it is app/main/requestSection.
We used context from React to provide parent’s path to its children. The XPATH components down in the React tree just compose on top of the paths provided by the parent and then again pass down this composed path. Now whenever an XPATH component is mounted, it registers the DOM node it is wrapping against its final path. Below I have added a codesandbox which shows a trimmed down version of the XPATH that we implemented inside Postman.
Along with this, for more seamless orchestration of lessons, XPATH component inside Postman app emit registered and unregistered events so that the on-boarding system knows that the XPATH is ready and can be used for attaching Popovers. Also rather than just mounting and unmounting, developers can control when they actually want to make this XPATH register/unregister by passing a prop. A use case for this was that inside our app there were certain sections of UI which are always mounted but are made hidden using CSS and we don’t want it to be made available for reference until it is actually visible on the UI.
Future ahead…
With these XPATH now we have the capability to create on-boardings for ideally anything inside the Postman app. This also enables our developers to very easily make new features on-boarding ready by just adding XPATH around their components. In future we want to build more flexibility around using these xpaths like we have in traditional query selectors or xpath.