How can I clear a Codemirror editor field from Cypress - javascript

I already tried something like this from another SO answer How to type using cypress .type() inside the codemirror editor?
If it helps this is the site I am working on Cypress with https://testing-playground.com/
// CodeMirror's editor doesn't let us clear it from the
// textarea, but we can read the Window object and then
// invoke `setValue` on the editor global
cy.window().then(win => {
win.editor.setValue("")
})
The issue I am running into is when I try to implement this I am getting undefined for the editor. I tried digging into the Window object more and couldn't find anything resembling the Codemirror editor. Running .clear({force: true}) on any of the other Codemirror elements yields no results, just .type({force: true}) on the textfield adding the new content with the old.

The solution I ended up using looked something similar to code block in the question with a few changes.
I am not getting the window object from Cypress; CodeMirror editor wasn't there.
I used the idea Evan Plaice gave me related to the Editor instance being on the DOM and then searched the CodeMirror DOM hierarchy manually to find it.
The resulting code will clear a spefic editor, there are two so the [0] is necessary for that.
cy.get('.CodeMirror')
.first()
.then((editor) => {
editor[0].CodeMirror.setValue('');
});

Very unintuitive but you can update the contents by swapping in a new CodeMirror document instance
editor.swapDoc(CodeMirror.Doc([contents],[language]));
That's how I handle content updates on wc-codemirror

Related

Karate UI Framework : have to run a javascript to store chrome session to launch website [duplicate]

Firstly, Karate UI automation is really awesome tool. I am kind of enjoying it while writing the UI tests using Karate. I ran into a situation where in, i was trying to fetch the shadowRoot elements. I read few similar posts related to javascript executor with karate and learnt that it is already answered. it is recommended to use driver.eval. But in Karate 0.9.5 there is no eval, it has script() or scriptAll(). I have gone through documentation couple of times to figure out how i can fetch element inside an element but no luck.
Using traditional selenium+java, we can fetch shadowRoot like this way:
something like shadowRoot which sits inside a parent element like div or body.
//downloads-manager is the tagname and under that downloads-manager, a shadowRoot element exists
The HTML looks like this. it is from chrome://downloads.
<downloads-manager>
#shadow-root(open)
</download-manager>
WebElement downloadManager =driver.findElement(By.tagName("downloads-manager");
WebElement shadowRoot= (WebElement)((JavaScriptExecutor)driver)
.executeScript("return arguments[0].shadowRoot",downloadManager);
So i tried the following in Karate UI
script("downloads-manager","return _.shadowRoot"); //js injection error
script('downloads-manager', "function(e){ return e.shadowRoot;}"); // same injection error as mentioned above.
def shadowRoot = locate("downloads-manager").script("function(e){return e.shadowRoot};"); //returns an empty string.
I bet there is a way to get this shadowRoot element using Karate UI but i am kind of running out of options and not able to figure out this.
Can someone please look into this & help me?
-San
Can you switch to XPath and see if that helps:
* def temp = script('//downloads-manager', '_.innerHTML')
Else please submit a sample in this format so we can debug: https://github.com/intuit/karate/tree/develop/examples/ui-test
EDIT: after you posted the link to that hangouts example in the comments, I figured out the JS that would work:
* driver 'http://html5-demos.appspot.com/hangouts'
* waitFor('#hangouts')
* def heading = script('hangout-module', "_.shadowRoot.querySelector('h1').textContent")
* match heading == 'Paul Irish'
It took some trial and error and fiddling with the DevTools console to figure this out. So the good news is that it is possible, you can use any JS you need, and you do need to know which HTML element to call .shadowRoot on.
EDIT: for other examples of JS in Karate: https://stackoverflow.com/a/60800181/143475

PowerBi-Javascript: How do I find out the visualName value for setting a slicer?

I'm attempting to use Microsoft's PowerBi-Javascript library to embed a report in a webpage. I want to apply a slicer on load, that depends on the actual page I'm on (so can't be done by defaults on the report).
The library wiki gives a way to do this by setting slicers in the config passed to the embed function. The slicer object looks something like this (from the documentation https://github.com/Microsoft/PowerBI-JavaScript/wiki/Slicers):
interface ISlicer {
// Selects a slicer to change.
selector: SlicerSelector;
// A new state of the slicer
state: ISlicerState;
}
interface ISlicerSelector {
$schema: string;
visualName: string;
}
I'm happy with setting up the state using the filtering examples given, but I'm having problems finding the visualName for the selector - I can't see it in the interface (on viewing or editing), and I've tried using the names/headers etc I can see, none of which work.
How do I find out and/or set what this visualName is?
I've not found a way in the UI to see this. Hopefully there is a better way than the below, but this does work.
However, it is possible to find out using the api, or using this library if you're able to mess around running some code locally.
In my case, I found out by (while developing locally) finding the page and then the visuals that were displaying once the report had rendered, logging the data to the console, and identifying which visual was the one I wanted.
Something like:
report.on('rendered', () => {
report.getPages().then(pages => {
pages[0].getVisuals().then(visuals => console.log(visuals))
});
});
Where in this case I only cared about the first page.
This then logged some data to the console about each visual, including co-ordinate values and visualName, so I was able to identify the one I was interested in and see its visualName property.
Confusingly, the visualName property looks more like an id (although not a guid).
You can set the Visual Title (not the Slicer Title) on the slicer under General > Title > Text.
Screenshot
Then, you can find the slicer using the visual.title property.
For example,
report.on('rendered', () => {
report.getPages().then(pages => {
pages[0].getVisuals().then(visuals => console.log(
visuals.find(visual => visual.title === "MySlicer")
);
});
});

CKEditor5 Get Plain Text

I know how to get data using CKEditor5 API as it's mentioned in documentation and on another SO post.
However, how could I get the Plain Text? I tried following but it returns nothing.
alert($(editorObj.element).val());
Interesting Note: Even following code returns nothing if TextArea is bind with CKEditor
alert( $("#editor").val());
But if I don't bind TextArea with CKEditor then it works fine.
Any solution or feedback would be highly appreciated.
CKEditor 5 does not expose such a method but you can use one of the utils of the #ckeditor/ckeditor5-clipboard package – viewToPlainText().
It's used by the clipboard feature to set the text/plain flavour in the clipboard when the user copies some content from the editor.
To use it you'll need to use CKEditor 5 from source (because this function is not exposed publicly). You can read about that in the CKEditor 5 Framework's Quick start guide.
You can use this method to stringify the entire editor's view:
import viewToPlainText from '#ckeditor/ckeditor5-clipboard/src/utils/viewtoplaintext';
import ClassicEditorBuild from '#ckeditor/ckeditor5-build-classic/src/ckeditor';
ClassicEditorBuild
.create( element )
.then( editor => {
// Will get the stringified content.
console.log( viewToPlainText( editor.editing.view.getRoot() ) );
} )
.catch( error => {
console.error( error.stack );
} )
Ok, I found a workaround:
var plainText = $(editorObj.getData()).text();
Until we get a proper solution or a method exposed by library, I hope this workaround will work.

How to deal with DOM elements?

I am learning about writing custom JavaScript for my Odoo 10 addons.
I've written the following piece of code:
odoo.define('ioio.io', function(require) {
'use strict'
const e = $('div.o_sub_menu_footer')
console.log('--testing--'.repeat(7))
console.log(e)
// the "Powered by Odoo" down the secondary menu
e.remove()
})
The code is well loaded and I can see my testing string in the console.
However when this code is being loaded before the target div, so e empty/not yet filled and thus its content is not removed.
Doing it manually from the console works.
My question is what is the right way to do that? And how to know exactly when the code gets executed?
You can
put your html code before the script tag in your file
use jQuery $(document).ready(...);
Place your script at the bottom of the <body> tag to make sure the DOM renders before trying to manipulate it.
This is an Odoo specific question, so you should use the Odoo standard way, which is via its base JS class. That class contains a ready() method which does exactly what you need.
In your case, to use that function, you need to require the class first. Then you can use ready().
Updating your code, it should look like this:
odoo.define('ioio.io', function(require) {
'use strict'
// require base class
var base = require('web_editor.base');
//use its ready method
base.ready().done(function () {
// put all the code you want to get loaded
// once the DOM is loaded within this block
const e = $('div.o_sub_menu_footer')
console.log('--testing--'.repeat(7))
console.log(e)
// the "Powered by Odoo" down the secondary menu
e.remove()
});
})
While your accepted answer leads to the same outcome, you might want to update it to this one since this is the Odoo way. It's generally advised to work within the Odoo framework as much as possible and customise only if really needed. (Though it can be tough to learn what features Odoo already provides because of its poor documentation.)

Event handling in Dojo

Taking Jeff Atwood's advice, I decided to use a JavaScript library for the very basic to-do list application I'm writing. I picked the Dojo toolkit, version 1.1.1. At first, all was fine: the drag-and-drop code I wrote worked first time, you can drag tasks on-screen to change their order of precedence, and each drag-and-drop operation calls an event handler that sends an AJAX call to the server to let it know that order has been changed.
Then I went to add in the email tracking functionality. Standard stuff: new incoming emails have a unique ID number attached to their subject line, all subsequent emails about that problem can be tracked by simply leaving that ID number in the subject when you reply. So, we have a list of open tasks, each with their own ID number, and each of those tasks has a time-ordered list of associated emails. I wanted the text of those emails to be available to the user as they were looking at their list of tasks, so I made each task box a Dijit "Tree" control - top level contains the task description, branches contain email dates, and a single "leaf" off of each of those branches contains the email text.
First problem: I wanted the tree view to be fully-collapsed by default. After searching Google quite extensively, I found a number of solutions, all of which seemed to be valid for previous versions of Dojo but not the one I was using. I eventually figured out that the best solution would seem to be to have a event handler called when the Tree control had loaded that simply collapsed each branch/leaf. Unfortunately, even though the Tree control had been instantiated and its "startup" event handler called, the branches and leaves still hadn't loaded (the data was still being loaded via an AJAX call). So, I modified the system so that all email text and Tree structure is added server-side. This means the whole fully-populated Tree control is available when its startup event handler is called.
So, the startup event handler fully collapses the tree. Next, I couldn't find a "proper" way to have nice formatted text for the email leaves. I can put the email text in the leaf just fine, but any HTML gets escaped out and shows up in the web page. Cue more rummaging around Dojo's documentation (tends to be out of date, with code and examples for pre-1.0 versions) and Google. I eventually came up with the solution of getting JavaScript to go and read the SPAN element that's inside each leaf node and un-escape the escaped HTML code in it's innerHTML. I figured I'd put code to do this in with the fully-collapse-the-tree code, in the Tree control's startup event handler.
However... it turns out that the SPAN element isn't actually created until the user clicks on the expando (the little "+" symbol in a tree view you click to expand a node). Okay, fair enough - I'll add the re-formatting code to the onExpand() event handler, or whatever it's called. Which doesn't seem to exist. I've searched to documentation, I've searched Google... I'm quite possibly mis-understanding Dojo's "publish/subscribe" event handling system, but I think that mainly because there doesn't seem to be any comprehensive documentation for it anywhere (like, where do I find out what events I can subscribe to?).
So, in the end, the best solution I can come up with is to add an onClick event handler (not a "Dojo" event, but a plain JavaScript event that Dojo knows nothing about) to the expando node of each Tree branch that re-formats the HTML inside the SPAN element of each leaf. Except... when that is called, the SPAN element still doesn't exist (sometimes - other times it's been cached, just to further confuse you). Therefore, I have the event handler set up a timer that periodically calls a function that checks to see if the relevant SPAN element has turned up yet before then re-formatting it.
// An event handler called whenever a "email title" tree node is expanded.
function formatTreeNode(nodeID) {
if (dijit.byId(nodeID).getChildren().length != 0) {
clearInterval(nodeUpdateIntervalID);
messageBody = dijit.byId(nodeID).getChildren()[0].labelNode.innerHTML
if (messageBody.indexOf("<b>Message text:</b>") == -1) {
messageBody = messageBody.replace(/>/g, ">");
messageBody = messageBody.replace(/</g, "<");
messageBody = messageBody.replace(/&/g, "&");
dijit.byId(nodeID).getChildren()[0].labelNode.innerHTML = "<b>Message text:</b><div style=\"font-family:courier\">"+messageBody+"</div>";
}
}
}
// An event handler called when a tree node has been set up - we changed the default fully-expanded to fully-collapsed.
function setupTree(theTree) {
dijit.byId("tree-"+theTree).rootNode.collapse();
messageNode = dijit.byId("tree-"+theTree).rootNode.getChildren();
for (pl = 0; pl < messageNode.length; pl++) {
messageNode[pl].collapse();
messageNode[pl].expandoNode.onclick = eval("nodeUpdateIntervalID = setInterval(\"formatTreeNode('"+messageNode[pl].id+"')\",200); formatTreeNode('"+messageNode[pl].id+"');");
}
}
The above has the feel of a truly horrible hack, and I feel sure I must have taken a wrong turn somewhere early on in my thought process. Can someone please tell me:
The correct way to go about putting nicely-formatted text inside a Dojo/Dijit Tree control.
The correct way to handle Dojo events, like where I can figure out what events are available for me to subscribe to.
A better JavaScript library to use (can I do what I want to with JQuery and avoid the all-around-the-houses approach seen above?).
PS: If you're naming a software project, give thought to its name's uniqueness in Google - I'm sure searching for "Dojo" documentation in Google would be easier without all the martial arts results getting in the way.
PPS: Firefox spellchecker knows how to spell "Atwood", correcting me when I put two 'T's instead of one. Is Jeff just that famous now?
I assume that you followed the dijit.Tree and dojo.data in Dojo 1.1 tutorial which directed you to pass the data to the tree control using a data store. That had me banging my head of a brick wall for a while.
Its not really a great approach and the alternative is not really well documented. You need to create a use model instead. I have included an example below of a tree model that I created for displaying the structure of an LDAP directory.
You will find the default implementation of the model in your dojo distribution at ./dijit/_tree/model.js. The comments should help you understand the functions supported by the model.
The IDirectoryService class the code below are stubs for server-side Java POJOs generated by Direct Web Remoting (DWR). I highly recommend DWR if you going to be doing a lot of client-server interaction.
dojo.declare("LDAPDirectoryTreeModel", [ dijit.tree.model ], {
getRoot : function(onItem) {
IDirectoryService.getRoots( function(roots) {
onItem(roots[0])
});
},
mayHaveChildren : function(item) {
return true;
},
getChildren : function(parentItem, onComplete) {
IDirectoryService.getChildrenImpl(parentItem, onComplete);
},
getIdentity : function(item) {
return item.dn;
},
getLabel : function(item) {
return item.rdn;
}
});
And here is an extract from the my JSP page where I created the model and used it to populate the tree control.
<div
dojoType="LDAPDirectoryTreeModel"
jsid="treeModel"
id="treeModel">
</div>
<div
jsid="tree"
id="tree"
dojoType="dijit.Tree" model="treeModel"
labelAttr="name"
label="${directory.host}:${directory.port}">
</div>

Categories

Resources