I started using cypress nowadays to learn better and deeper. I am faced with a problem that I can't handle. The problem is some kind of GUI effect working with mouse hover. While hovering my mouse on the element I can't see any information change into DOM. There are just ::before and ::after words appearing. I think I have to solve that problem with some javascript tricks. unfortunately, I am new to javascript and I don't have any idea if you help me I would be very happy. Thank you! (I want to assert in some way that grey background and plus icon is shown or not)
generically look like that
after the mouse hovers this grey background and plus icon comes
you can see elements DOM here
you can see the changes after the mouse hovers element
You can use the cypress-real-events plugin.
To install use the command:
npm i cypress-real-events
Then inside your cypress/support/e2e.{js,ts}, write:
import "cypress-real-events/support";
And in your code you can directly write:
cy.get("selector").realHover('mouse')
//Add assertions
Note: Since the above plugin uses Chrome DevTools Protocols to simulate native events, hence this will only work with Chromium-based browsers, so no firefox.
Into cypress' test try to use the method cy.wait("time here") following hover command.
This is very simple but for visual test this is so useful.
In order to access the :before or :after of an element, we have to do a little Cypress and JavaScript magic. This is answer is mostly from this link.
cy.get('.myClass')
.then($els => {
// get Window reference from element
const win = $els[0].ownerDocument.defaultView
// use getComputedStyle to read the pseudo selector
const before = win.getComputedStyle($els[0], ':before')
// read the value of the `content` CSS property
const contentValue = before.getPropertyValue('content')
// The above lines are just how we tell Cypress to get the `:before` value.
// There isn't a ton to understand outside of really diving into how elements and windows work together
expect(content).to.equal('foo');
})
So, using that same example, we can check for any CSS property on the element. For example, font-size:
cy.get('.myClass')
.then($els => {
const win = $els[0].ownerDocument.defaultView
const before = win.getComputedStyle($els[0], ':before')
const fontSize = before.getPropertyValue('font-size') // instead of `'font-size'`, you can substitute any CSS property
expect(fontSize).to.equal('20');
})
This can also be applied to :after, changing out ($els[0], ':before') with ($els[0], ':after').
Looking at your screenshots, I think you have a gray overlay element covering the original incident element.
The only code I can suggest is from the limited information is
cy.get('#IN-578')
.trigger('mouseover')
.should('not.be.visible')
The overlay has opacity 50%, so you can still see the incident details but from Cypress point of view the incident is covered so it will not be "visible".
If you don't have any luck with 'mouseover', try .realHover() from cypress-real-events.
After the above code, you should look for the overlay element in DOM and the + icon in the middle, select that icon and click it to take the action.
Related
There seems to be a bug when using this these 2 libraries together and trying to use CSS Pseudo-elements.
I have created a demo here: http://tappetyclick.com/fontawesomebug/. The text in the anchor which has the pseudo-element disappears and I only see the icon
If I remove the cookie consent plugin code then everything seems to work as expected see http://tappetyclick.com/fontawesomebug/test.htm
Has anyone else seen this issue or know what might be causing it.
I could be massively wrong, this is just a guess.
I think this is happening because cookie consent defines the aria-labelledby attr as cookieconsent:desc but the : is the pseudo element selector, therefor it is trying to find a :desc pseudo selector (which clearly doesn't exist).
You MIGHT be able to stop this error by defining it in jQuery
jQuery.extend(jQuery.expr[':'], {
// add the :desc pseudo-selector to jQuery
desc: function (el, index, selector) {
// stub for now
return false;
}
});
or what ever selector library you may be using.
Thats my best guess at least
I have a slide in menu using vanilla javascript for use on phones, but so far all my tests have resulted in the mobile browsers ignoring the first tap (have tried both touchstart & click as events). Starting with the second tap it works beautifully with each and every subsequent tap.
As opening & closing the menu is the only javascript function on the pages, I don't want to load a huge library, I want to keep it simple and small. My code is below:
var b = document.getElementById('menubtn');
b.addEventListener('touchstart', function (e) {
var n = document.getElementById('nav');
var ns = n.style.left;
if (ns == "-600px") {
n.style.left = "0px";
} else {
n.style.left = "-600px";
}
e.preventDefault();
});
Any ways to easily eliminate this need for double clicking the first time?
In the fwiw dept, it is a responsive design, with the nav menu in a column on big screens and a slide in on phones.
Edit: Solved the issue
Following through on Matt Styles comment, I tried using classList.toggle and it solved the issue. The final version is below:
var b = document.getElementById('menubtn');
var n = document.getElementById('nav');
b.addEventListener('touchstart', function () {
n.classList.toggle('shwmenu');
setTimeout(function () {
b.classList.toggle('shwmenu');
}, 500);
});
I added the delayed menubtn code to toggle the icon between closed and open states.
The behaviour you describe could be caused by the following:
In your JS you try to implement some kind of On-Off toggle for your nav element, differentiated on the left CSS property value, with -600 representing the off value and 0 representing the on value.
As you said, toggling between those states seems to work fine, but what happens when your element is NOT initialized on exactly -600? Then on your first tap you will always run into your else clause and set it to -600 first, showing effectively no visual effect on your first tap, just as you describe.
For an instant test, just swap the if-else clause around to turn it on when style.left is not -600 and then maybe work up towards a more dynamic differentiation between your states ;)
I think this is because element.style.left is empty even if you have set left property in your stylesheet. You can use element.offsetLeft instead. Please see here to how it works.
HTMLElement.style - MDN
The style property is not useful for learning about the element's style in general, since it represents only the CSS declarations set in the element's inline style attribute, not those that come from style rules elsewhere, such as style rules in the <head> section, or external style sheets. To get the values of all CSS properties for an element you should use window.getComputedStyle() instead.
I'm writing a program that will use a CodeMirror instance and have a little element that pops up that you can, among other things, type text in. That text typing area is supposed to be one line high. I'm going to be doing a lot of the same stuff with that text typing area that I'm doing with the main CodeMirror instance, so I want to just use another instance of CodeMirror, but everything I've tried so far ends up too tall.
How do I make a CodeMirror instance that is just one line high and is horizontally scrollable? I'd like no line numbers, no gutters, etc., just the area for the text to be entered.
I tried several things including the code here (which I tried in whole and in parts): codemirror for just one-line-textfield?. The example prevents a user from typing more than one line of code in a code mirror instance, but it doesn't make it just one line high. There's other CodeMirror stuff there, though I'm not sure what all is there or how to get rid of it.
Edit:
re: #rfornal's request, here was the code and explanation I'm referring to (by Tigran Saluev):
Well, there is a way to make a single-line editor using rich capabilities of CodeMirror. First, you'll have to add a full-featured CodeMirror object (use a textarea).
Assume you've got var cm = CodeMirror(...). (Use value: ""). Then do
cm.setSize(200, cm.defaultTextHeight() + 2 * 4);
// 200 is the preferable width of text field in pixels,
// 4 is default CM padding (which depends on the theme you're using)
// now disallow adding newlines in the following simple way
cm.on("beforeChange", function(instance, change) {
var newtext = change.text.join("").replace(/\n/g, ""); // remove ALL \n !
change.update(change.from, change.to, [newtext]);
return true;
});
// and then hide ugly horizontal scrollbar
cm.on("change", function(instance, change) {
$(".CodeMirror-hscrollbar").css('display', 'none');
// (!) this code is using jQuery and the selector is quite imperfect if
// you're using more than one CodeMirror on your page. you're free to
// change it appealing to your page structure.
});
// the following line fixes a bug I've encountered in CodeMirror 3.1
$(".CodeMirror-scroll").css('overflow', 'hidden');
// jQuery again! be careful with selector or move this to .css file
This works just fine for me.
Everything I've tried so far still ends up taller than one line. There's probably a way to do this, I'm just not understanding how.
As per usual, this was user error. I had assumed that CodeMirror's styles would overwrite any styles that I had created for the container, but they didn't. My styles infected the CodeMirror instance and caused the weirdness.
Specifically:
- Setting position: relative somewhere where it shouldn't be (I'm not sure where)
- Setting display: inline-block somewhere where it shouldn't be (again, not sure what it specifically affected)
My apologies and I hope this helps someone else in the future.
When I am updating links with JavaScript
$('#link_id').attr('href', some_new_url)
the color theme for visited/non-visited links persists, regardless of the status of the new url address.
Is there a way to change link address forcing browser to re-check its visited status?
Further notes:
I am (on OSX 10.8) experiencing this problem in Chrome (32) and Safari (6.1). In Firefox (26) the links status gets updated automatically, as desired.
The example above is in jQuery, but the problem is the same way with with vanilla JavaScript, i.e. document.getElementById and setAttribute.
(I would prefer to avoid deleting and adding <a></a>, if possible.)
EDIT:
Minimal (non-)working example (by Joeytje50): http://jsfiddle.net/3pdVW/
Definitive answer
What you could do to fix this, is simply forcing the browser to recalculate the styles by completely removing the href attribute, and then re-adding it back again immediately afterwards. That will make the browser first calculate the styles, since the <a> is no longer a link without the href, and then you add the href you want to give it. The code would then be:
$('#link_id').removeAttr('href').prop('href', some_new_url);
Demo
PS: in this case, using .attr('href', some_new_url); would probably work equally fine.
Previous attempts
What I'm thinking is that this is a rendering glitch. It doesn't recalculate the styles when the :visited state changes because of the script. This minimal example of your problem shows this well. What you could try is either of the following:
Using the element's properties
What the problem might be is that you're changing the attribute, which in turn changes the href property. If you directly change the href property it might work. You can do this via jQuery.prop, which would use the following code to change the link:
$('#link_id').prop('href', some_new_url);
Demo. I don't really have very high hopes about this one, but it's worth trying. What I do suspect will work much better is:
Forcing to recalculate the styles
If you want to force a recalculation of the styles, you can simply change a class on the highest element you want updated. Since you're updating the <a> element alone, you'd need something like this:
$('#link_id').prop('href', some_new_url).toggleClass('webkit-force-recalculate');
Demo
I think that is quite likely to do the trick.
If neither of these approaches work for you, you could of course use maximgladkov's solution.
You can change it like this:
$('#link_id').replaceWith($('' + $('#link_id').text() + ''));
It should do the trick. Tested: http://jsfiddle.net/maximgladkov/L3LMd/
Frequently experience similar issues, e.g. when setting size of elements with border, there are stray borders left etc.
Though this is not directly the same, I have found that hiding the element does the trick. Have not had any trouble with it.
Simple fiddle
$("#change_link").on("click", function(e) {
$("#anchor1").hide();
$("#anchor1").attr('href', $("#url").val());
$("#anchor1").show();
});
This should force a redraw of the element.
I think what you might be looking for is the following CSS code:
a:link {
text-decoration: none;
color: #00F;
}
a:visited {
color: #00F;
}
I have an IMG element c. The following works to change its cursor (in Chrome):
c.style.cursor='-webkit-zoom-out';
But if I try to add compatibility for other browsers, as in the following, it breaks:
c.style.cursor='-webkit-zoom-out, -moz-zoom-out';
(And I haven't even gotten to trying to link a .cur for IE-compatibility....) What's the correct syntax to add multiple values to a style element?
You have to add them separately:
c.style.cursor = '-webkit-zoom-out';
c.style.cursor = '-moz-zoom-out';
Unfortunately zoom-in and zoom-out are not supported by Internet Explorer yet. See the MDN Cursor: Browser compatibility.
Demo
Try before buy
Alternatively you can create a CSS class that sets the correct styles and add or remove this class using JavaScript if you need to toggle it.