How to test an infinite scroll component in Cypress - cypress

I have an dynamically loaded table based on an infinite-scroll component. I can test the loaded items as follows, but only 20 items are loaded at a time.
How can I repeat until the 500th item comes into view without repeating the code 100 times?
cy.get('div.infinite-scroll-component')
.children()
.should('have.length', 20)
.last()
.scrollIntoView()
cy.contains('Loading')
.should('be.visible')
<div class="infinite-scroll-component" style="height: auto; overflow: auto;">List:
<div style="height: 30px; border: 1px solid green; margin: 6px; padding: 8px;">Item #0</div>
<div style="height: 30px; border: 1px solid green; margin: 6px; padding: 8px;">Item #1</div>
<div style="height: 30px; border: 1px solid green; margin: 6px; padding: 8px;">Item #2</div>
<div style="height: 30px; border: 1px solid green; margin: 6px; padding: 8px;">Item #3</div>
...

To repeat an action until a certain element appears on the page, use a recursive function.
You must be careful to only take the next step after the action is complete.
In your case the "Loading" indicator has appeared, and then wait for the load to complete (timing may need adjusting).
const findItem = (item, attempt = 1) => {
if (attempt === 100) throw 'Not found'
return cy.get('div.infinite-scroll-component')
.children()
.then($els => {
const found = [...$els].some(el => el.innerText === item)
if (!found) {
// trigger load with scroll
cy.get('div.infinite-scroll-component')
.children()
.last()
.scrollIntoView()
cy.contains('Loading')
.should('be.visible')
.then(() => {
cy.wait(100) // wait for loading
// OR check the list length
const expectedListLength = (attempt +1) * 20
cy.get('div.infinite-scroll-component').children()
.should('have.length', expectedListLength)
return findItem(item, ++attempt) // next step
})
}
return cy.get('div.infinite-scroll-component')
.children(`:contains(${item})`)
})
}
findItem('div - #100').should('have.length', 1) // just one item
.and('contain.text', 'div - #100') // verify it's text

Related

Svelte draggable, onleave event triggered when dragging over child elements

I have an element that I highlight when I drag a second element over it using the dragenter event, removing the highlight using the dragleave event. The highlight element has a child and when the dragged element passes over the child, the dragleave event is triggered and I lose my highlight. How do I prevent this?
REPL: https://svelte.dev/repl/8846d8b9674d42ae86a410dbb737fb79?version=3.35.0
<script>
let highlight=""
</script>
<div class="dropon {highlight}"
on:dragenter={ event => {
highlight="highlight"
console.log( "enters")
}}
on:dragleave={ event => {
highlight=""
console.log( "leaves")
}}
>
<div class="inner">
drop on me
</div>
</div>
<div class="drag" draggable={true}>drag me</div>
<style>
.dropon {
padding: 20px;
margin: 10px;
background: #fee;
}
.drag {
padding:20px;
margin: 10px;
cursor:grab;
background: #efe;
}
.inner {
background: #eef;
padding: 8px;
}
.highlight {
background: red;
}
</style>
Add css pointer-events: none; on .inner
Like this:
.inner {
pointer-events: none;
background: #eef;
padding: 8px;
}

Is it possible to determine number of children of any container using any SASS function?

Is it possible to determine number of children of any container using any SASS function?
For example, I have a container which has 3 columns:
<div class="columns columns_3">
<div class="column"></div>
<div class="column"></div>
<div class="column"></div>
</div>
For this container, I want to implement a mixin which is +columns_3
But if the container has nth number of children, mixin will be +columns_n
What you want is to know how many childs haves an element and set the right class to it.
You need Javascript to detect the number of childs, HTML and CSS.
SCSS
.element {
$width: 100%;
width: $width;
div {
height: 100px;
float: left;
border:1px solid #000;
box-sizing: border-box;
}
#for $i from 1 through 12 {
&--#{$i} div {
width: $width/$i;
}
}
}
var element = document.getElementsByClassName('element')[0];
var childs = element.childElementCount;
element.classList.add("element--"+childs);
.element {
width: 100%;
}
.element div {
height: 100px;
float: left;
border: 1px solid #000;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
.element--4 div {
width: 25%;
}
<div class="element">
<!-- childs -->
<div></div>
<div></div>
<div></div>
<div></div>
</div>
Well if you have a range, you could potentially use a for loop - depending what you need to do. For example:
$gridWidth = 100%;
#for $numItems from 1 through 12 {
.columns_#{$numItems} {
.column {
width: $gridWidth / $numItems;
}
}
}
I think you can make this :
#function number(val) { #return val };
#mixins +columns_#{number(10)} {
// Your code;
}
I'm not sure I understand what you explain.

kendo sortable with kendo observable array

i am using kendo sortable data source is kendo observable array,
when we sorting the divs we are updating the array object in change event,
but array is updating properly but ui is not updating.
can u please help me.
<!DOCTYPE html>
<html>
<head>
<title></title>
<link href="http://cdn.kendostatic.com/2014.1.528/styles/kendo.common.min.css" rel="stylesheet" />
<link href="http://cdn.kendostatic.com/2014.1.528/styles/kendo.default.min.css" rel="stylesheet" />
<link href="http://cdn.kendostatic.com/2014.1.528/styles/kendo.dataviz.min.css" rel="stylesheet" />
<link href="http://cdn.kendostatic.com/2014.1.528/styles/kendo.dataviz.default.min.css" rel="stylesheet" />
<script src="http://cdn.kendostatic.com/2014.1.528/js/jquery.min.js"></script>
<script src="http://cdn.kendostatic.com/2014.1.528/js/kendo.all.min.js"></script>
</head>
<body>
<div id="example">
<div id="playlist">
<ul id="sortable-basic" data-bind="source:items" data-template="template">
</ul>
</div>
<script type="text/x-kendo-tmpl" id="template">
<li class="sortable">#:value#<span>#:time#</span></li>
</script>
<script>
var data;
$(document).ready(function () {
data = kendo.observable({
items: new kendo.data.ObservableArray([
{ value: 'Papercut', time: '3:12' },
{ value: 'One Step Closer ', time: '4:10' },
{ value: 'With You ', time: '5:00' },
{ value: 'Points of Authority ', time: '2:59' }]
)
});
kendo.bind($('#playlist'), data);
$("#sortable-basic").kendoSortable({
change: function (e) {
var daa = data.items.splice(e.oldIndex, 1);
data.items.splice(e.newIndex, 0, daa[0]);
}
});
});
</script>
<style>
#example
{
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
#playlist
{
margin: 30px auto;
width: 300px;
background-color: #f3f5f7;
border-radius: 4px;
border: 1px solid rgba(0,0,0,.1);
}
#playlist-title
{
height: 80px;
border-radius: 4px 4px 0 0;
border-bottom: 1px solid rgba(0,0,0,.1);
}
#playlist-title span
{
display: none;
}
#sortable-basic
{
padding: 0;
margin: 0;
}
li.sortable
{
list-style-type: none;
padding: 6px 8px;
margin: 0;
color: #666;
font-size: 1.2em;
}
li.sortable:last-child
{
border-bottom: 0;
border-radius: 0 0 4px 4px;
}
li.sortable span
{
display: block;
float: right;
color: #666;
}
li.sortable:hover
{
background-color: #dceffd;
}
li.hint
{
display: block;
width: 200px;
background-color: #52aef7;
color: #fff;
}
li.hint:after
{
content: "";
display: block;
width: 0;
height: 0;
border-top: 6px solid transparent;
border-bottom: 6px solid transparent;
border-left: 6px solid #52aef7;
position: absolute;
left: 216px;
top: 8px;
}
li.hint:last-child
{
border-radius: 4px;
}
li.hint span
{
color: #fff;
}
li.placeholder
{
background-color: #dceffd;
color: #52aef7;
text-align: right;
}
</style>
</div>
</body>
</html>
I think I found your problem. It seems to be the change function, just remove it and you can sort your list.
I've not used kendoSortable but I would assume that it is already maintaining the array sort because you have bound the array to the kendoSortable. That's the purpose of binding, it keeps the data and elements in sync for you. What you're doing in the change event is simply undoing the work that the binding just did, that is, sort the elements AND the bound array.
As per telerik,
https://www.telerik.com/forums/sortable-and-moving-items-in-observable-arrays
You have to do this manually and attaching sortable to an array doesn't do anything automatically. So what you are doing is correct, however even though your changes reflect correctly in observable array it doesn't on screen.
So we have to trigger clear and change event, to sync UI with the array. There may be a better way invoke sync without having to clear out array but this was a hack that worked for me.
Here is a sample code where we clear the array and then re-insert which fixes the issue.
$("#sortable-basic").kendoSortable({
change: function (e) {
var daa = data.items.splice(e.oldIndex, 1);
data.items.splice(e.newIndex, 0, daa[0]);
var copiedArray = data.items.splice(0, data.items.length);
$.each(copiedArray,
function (index, item) {
data.items.push(item);
});
}
});

Bootstrap Nod Validation Plugin And Iframs

I'm using bootstrap-wysihtml5 editor on my form which creates iframe element.
<iframe class="wysihtml5-sandbox" width="0" height="0" frameborder="0" security="restricted" allowtransparency="true" marginwidth="0" marginheight="0" name="for_nod" src="#" style="display: inline-block; background-color: rgb(255, 255, 255); border-collapse: separate; border-color: rgb(204, 204, 204); border-style: solid; border-width: 1px; clear: none; float: none; margin: 0px 0px 10px; outline: 0px none rgb(0, 0, 0); outline-offset: 0px; padding: 4px 6px; position: static; top: auto; left: auto; right: auto; bottom: auto; z-index: auto; vertical-align: middle; text-align: start; -moz-box-sizing: content-box; box-shadow: 0px 1px 1px 0px rgba(0, 0, 0, 0.075) inset; border-radius: 4px 4px 4px 4px; width: 750px; height: 300px;">
<html>
<head>
<meta charset="UTF-8">
<link href="/js/plug-ins/bootstrap-wysihtml5/rtl/rtl-editor.css" rel="stylesheet">
<style type="text/css">
</head>
<body class="wysihtml5-editor" contenteditable="true" spellcheck="true" style="background-color: rgb(255, 255, 255); color: rgb(85, 85, 85); cursor: text; font-family: "Helvetica Neue",Helvetica,Arial,sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: 400; line-height: 20px; letter-spacing: normal; text-align: start; text-decoration: none; text-indent: 0px; text-rendering: optimizelegibility; word-break: normal; word-wrap: break-word; word-spacing: 0px;">
simple text
<br>
</body>
</html>
</iframe>
I need to validate that body element inside the iframe isn't empty using Nod validation plugin.
the problem is that Nod validation plugin accepts jquery selectors TEXT for setting validation rules for elements , NOT objects - I can get the iframe object using $("iframe").content().find("body") but the validation logic will not work.
I have tried to set submit button onclick event handler to handle the validation of the iframe manually , the problem was that if the rules used by Nod passes ,then the custom validation function will have no effect if it returned true or false values.
anyway to get around this issue?
I have been solved my issue by creating non-displayed textarea element and then using custom events feature in order to listen to change event of iframe body , and minplulated the hidden textarea content to be the same.
nod rules has been applied to the hidden textarea.
I am not sure if this is the perfect solution but I had no choice :) for the moment.
the custom contentchange event code
/*
* custom-change-event
*
* This custom event is used for those elements
* that has no support for default change event
* like : body , div ,span, ....
*
*
*/
var interval;
jQuery.fn.contentchange = function (fn) {
return this.on('contentchange', fn);
};
jQuery.event.special.contentchange = {
setup: function (data, namespaces, eventHandle) {
var self = this,
$this = $(this),
$originalContent = $this.text();
interval = setInterval(function () {
if ($originalContent != $this.text()) {
$originalContent = $this.text();
jQuery.event.special.contentchange.handler.call(self);
}
}, 500);
},
teardown: function (namespaces) {
clearInterval(interval);
},
handler: function (event) {
$(this).trigger('contentchange');
}
};

Jquery cycle plugin with number and text paging

I have the basic functionality of the jquery cycle plugin working. I have set up a test page at here but was wondering what would I need to change in order for the paging to resemble this page
This is how I am calling the paging function, but I do not see anything in the plugin itself that would allow me to enclose the pager links in a
$(document).ready(function()
{
$('.promogallery').before('<div id="promonav">').cycle({
fx: 'fade', // choose your transition type, ex: fade, scrollUp, shuffle, etc...
timeout: 3000,
pager: '#promonav',
before: function()
{
}
});
});
Here is the relevant CSS:
/* promonav styling */
#promonav
{
margin: 5px 0;
text-align: left;
position: absolute;
top: -21px;
}
#promonav a, #promonavcyle strong
{
margin: 0 5px;
padding: 3px 5px;
border: 1px solid #ccc;
background: transparent;
text-decoration: none;
color: #a60000;
}
#promonav a.activeSlide
{
background: #ddd;
}
#promonav a:focus
{
outline: none;
}
/* #output { text-align: left; } */
Try the following in your CSS for #promonav a, #promonavcyle strong
border-style:dotted;

Resources