The slider in cypress invokes the changes , but the changes are not captured in the textbox - slider

The assertion to verify the selected value from the slider input fails, while the script runs, the slider position changes correctly but it doesn't take any effect on the textbox; the value in the box isn't updated.
describe('Validate the slidervalue', function() {
it('Should assert the slider value correctly', function() {
cy.visit('https://demoqa.com/slider')
cy.get('input[type="range"]').invoke('val', 65).trigger('change')
cy.get('#sliderValue').should('have.value', 65)
})
})

I haven't figured out the problem with val() but stepup() works
it('Should assert the slider value correctly', function() {
cy.visit('https://demoqa.com/slider')
cy.get('input[type="range"]')
.then($el => $el[0].stepUp(40) ) // steps = 65 - 25
.trigger('change')
cy.get('#sliderValue').should('have.value', 65) // passes
})
Or with helper function
const stepTo = ($el, target) => {
const step = $el[0].getAttribute('step') || 1
const current = $el[0].value
const diff = target - current
const steps = Math.abs(diff * step)
if (diff > 0) {
$el[0].stepUp(steps)
else {
$el[0].stepDown(steps)
}
}
it('Should assert the slider value correctly', function() {
cy.visit('https://demoqa.com/slider')
cy.get('input[type="range"]')
.then($el => stepTo($el, 65) )
.trigger('change')
cy.get('#sliderValue').should('have.value', 65) // passes
})

Related

React native - Need to change the state value to pass values to api call on each button click

In my app there is a list(FLatList) with pagination.
There are two buttons for sorting the list
Button 1 -> to remove the sorting key and load the default data from api.
Button 2 -> Each click on this button need to pass the value 'a to z' and 'z to a' to api as params
How to change the state(setSort,setSortAsc) of the value on each click and call api function?
My try -
const [getSort, setSort] = useState(false);
const [getSortAsc, setSortAsc] = useState(false);
Button 1 -> onPress () =>
const onCustomSort = () => {
setSort(false);
checkSorting();
};
Button 2 -> onPress () =>
const onNameSort = () => {
setSort(true);
setSortAsc(!getSortAsc);
checkSorting();
};
const checkSorting = () => {
console.log(TAG, 'Mrbee' + getSort + '---' + getSortAsc);
setviewProduct([]);
setLoader(true);
if (getSort) {
if (getSortAsc === true) {
setSortType('a to z');
} else {
setSortType('z to a');
}
} else {
setSortType('');
}
//api_call
dispatch(productlistAction(...,...,getSortType,),);
};
Issue is -> the state not getting change on button click so the api returns the same response.
On multiple clicks the state getting changed.
Calling of setState is not working for any states!
setviewProduct([]);
setLoader(true);
What is the mistake here. P
const [getSort, setSort] = useState(false);
const [getSortAsc, setSortAsc] = useState(false);
const [extra, setExtra] = useState(0);
Button 1 -> onPress () =>
const onCustomSort = () => {
setSort(false);
setExtra(extra+1) //add this
setTimeout(() => {
checkSorting();
}, "500")// 500 mean 0.5 sec delay, you can add your custom time
};
Button 2 -> onPress () =>
const onNameSort = () => {
setSort(true);
setSortAsc(!getSortAsc);
setExtra(extra+1) //add this
setTimeout(() => {
checkSorting();
}, "500") // 500 mean 0.5 sec delay, you can add your custom time
};
const checkSorting = () => {
console.log(TAG, 'Mrbee' + getSort + '---' + getSortAsc);
setviewProduct([]);
setLoader(true);
if (getSort) {
if (getSortAsc === true) {
setSortType('a to z')
setExtra(extra+1) //add this
} else {
setSortType('z to a');
setExtra(extra+1) //add this
}
} else {
setSortType('');
setExtra(extra+1) //add this
}
//api_call
dispatch(productlistAction(...,...,getSortType,),);
};

Testcafe: Is there a method to check for elements visible within the viewport? [duplicate]

I'm trying to implement a custom method to find out if the element is in the current view port
Below is the snippet of code that I've tried to implement but the outcome does not render the boolean result:
export const isElementInViewport = () => {
const getBoundValues = ClientFunction(() => document.querySelectorAll(".hero-getstart").item(0).getBoundingClientRect());
const windowHeight = ClientFunction(() => window.innerHeight);
const windowWidth = ClientFunction(() => window.innerWidth);
return getBoundValues.bottom > 0 && getBoundValues.right > 0 && getBoundValues.left < (windowWidth || document.documentElement.clientWidth) && getBoundValues.top < (windowHeight || document.documentElement.clientHeight);
};
The above code runs properly on the browser console, i.e when I try to store the getBoundValues in a variable A and try to run the return command, it prints the output as true or false depending on the visibility of the element in the viewport but in the script, It always gives a false:
Here's the method which triggers the above method:
export const verifyElementInView = () => {
const elementVisible = isElementInViewport();
console.log(elementVisible);
};
The output is always false.
Here's the snippet of output I receive upon trying to console.log(getBoundValues):
{ [Function: __$$clientFunction$$]
with: [Function],
[Symbol(functionBuilder)]:
ClientFunctionBuilder {
callsiteNames:
{ instantiation: 'ClientFunction',
execution: '__$$clientFunction$$' },
fn: [Function],
options: {},
compiledFnCode: '(function(){ return (function () {return document.querySelectorAll(".hero-getstart").item(0).getBoundingClientRect();});})();',
replicator:
{ transforms: [Array],
transformsMap: [Object],
serializer: [Object] } } }
What am I missing?
There's no need to create a client function for each client-side call. Instead, you can wrap the entire function into the ClientFunction call as follows:
const isElementInViewport = ClientFunction(() => {
const getBoundValues = document.querySelector("#developer-name").getBoundingClientRect();
const windowHeight = window.innerHeight;
const windowWidth = window.innerWidth;
return getBoundValues.bottom > 0 && getBoundValues.right > 0 && getBoundValues.left < (windowWidth || document.documentElement.clientWidth) && getBoundValues.top < (windowHeight || document.documentElement.clientHeight);
});
I recommend that you call your client function as follows (as described in the Executing Client Functions topic):
 
test('ClientFunctionCall', async t => {
const elementVisible = await isElementInViewport();
console.log(elementVisible)
});
 
The following example might also be useful: Complex DOM Queries

How does Puppeteer handle the click Object / DevTools Protocol Chromium/Chrome

I need to know how puppeteer handles the click object, as well as Chromium DevTools API. I've tried to research it on my own and have found myself not being able to find the actual code that handles it.
The reason why I need to know is I'm developing a wrapper that tests events in code for testing Web Pages, and was looking to see if implementing a event handling routine is beneficial instead of using puppeteers interface of events (clicks and taps an hover, as well as other events that might be needed like touch events, or scrolling)
Here is how far I've gotten:
Puppeteer API uses the Frame Logic of DevTools to contact API:
https://github.com/puppeteer/puppeteer/blob/master/lib/Page.js
/**
* #param {string} selector
* #param {!{delay?: number, button?: "left"|"right"|"middle", clickCount?: number}=} options
*/
click(selector, options = {}) {
return this.mainFrame().click(selector, options);
}
/**
* #return {!Puppeteer.Frame}
*/
/**
* #param {!Protocol.Page.Frame} framePayload`
*/
_onFrameNavigated(framePayload) {
const isMainFrame = !framePayload.parentId;
let frame = isMainFrame ? this._mainFrame : this._frames.get(framePayload.id);
assert(isMainFrame || frame, 'We either navigate top level or have old version of the navigated frame');
// Detach all child frames first.
if (frame) {
for (const child of frame.childFrames())
this._removeFramesRecursively(child);
}
if (isMainFrame) {
if (frame) {
// Update frame id to retain frame identity on cross-process navigation.
this._frames.delete(frame._id);
frame._id = framePayload.id;
} else {
// Initial main frame navigation.
frame = new Frame(this, this._client, null, framePayload.id);
}
this._frames.set(framePayload.id, frame);
this._mainFrame = frame;
}
This is as far as I have gotten because I've tried to look up the Page Protocol but I can't figure out what happens there.
Any help would be appreciated, even in research.
The main parts are happening in JSHandle here:
async click(options) {
await this._scrollIntoViewIfNeeded();
const {x, y} = await this._clickablePoint();
await this._page.mouse.click(x, y, options);
}
It scrolls until the element is in viewport (otherwise it won't click) which is happening here, then it finds the clickable coordinates on the element using DevTools API here:
async _clickablePoint() {
const [result, layoutMetrics] = await Promise.all([
this._client.send('DOM.getContentQuads', {
objectId: this._remoteObject.objectId
}).catch(debugError),
this._client.send('Page.getLayoutMetrics'),
]);
if (!result || !result.quads.length)
throw new Error('Node is either not visible or not an HTMLElement');
// Filter out quads that have too small area to click into.
const {clientWidth, clientHeight} = layoutMetrics.layoutViewport;
const quads = result.quads.map(quad => this._fromProtocolQuad(quad)).map(quad => this._intersectQuadWithViewport(quad, clientWidth, clientHeight)).filter(quad => computeQuadArea(quad) > 1);
if (!quads.length)
throw new Error('Node is either not visible or not an HTMLElement');
// Return the middle point of the first quad.
const quad = quads[0];
let x = 0;
let y = 0;
for (const point of quad) {
x += point.x;
y += point.y;
}
return {
x: x / 4,
y: y / 4
};
}
and finally it moves the mouse to the coordinate here and clicks on it here
async click(x, y, options = {}) {
const {delay = null} = options;
if (delay !== null) {
await Promise.all([
this.move(x, y),
this.down(options),
]);
await new Promise(f => setTimeout(f, delay));
await this.up(options);
} else {
await Promise.all([
this.move(x, y),
this.down(options),
this.up(options),
]);
}
}
which uses DevTools API to interact with mouse here
async down(options = {}) {
const {button = 'left', clickCount = 1} = options;
this._button = button;
await this._client.send('Input.dispatchMouseEvent', {
type: 'mousePressed',
button,
x: this._x,
y: this._y,
modifiers: this._keyboard._modifiers,
clickCount
});
}

Hide/Show the corresponding data from the chart on legend click ngx-charts

I am working with angular 6 and ngx-chart and I need on clicking the legend item, the corresponding data from the chart should show/hide
The ng-chart library does have this functionality and my client requests it.
Edit01:
I have almost everything working but I have a problem when applying axisFormat. once I remove an item from the legend it reformats the x-axis and doesn't literally put how the data comes without applying the AxisFormat. Any solution?
onSelect (event) {
let temp = JSON.parse(JSON.stringify(this.multi));
this.sourceData = JSON.parse(JSON.stringify(this.multi2));
if (this.isDataShown(event)) {
//Hide it
temp.some(pie => {
const pie2 = pie.name[0] + ',' + pie.name[1];
// console.log('pie', pie[0], event, pie2);
if (pie2 === event) {
pie.series = [];
return true;
}
});
} else {
//Show it back
console.log('Entramos en el ELSE');
const pieToAdd = this.sourceData.filter(pie => {
const pie2 = pie.name[0] + ',' + pie.name[1];
return pie2 === event;
});
temp.some(pie => {
const pie2 = pie.name[0] + ',' + pie.name[1];
if (pie2 === event) {
pie.series = pieToAdd[0].series;
return true;
}
});
}
console.log('log temp: ' + JSON.stringify(temp));
this.multi = temp;
// this.axisFormat(this.multi);
}
isDataShown = (name) => {
const selectedPie = this.multi.filter(pie => {
const pie2 = pie.name[0] + ',' + pie.name[1];
return pie2 === name && pie.series[0] !== undefined;
});
return selectedPie && selectedPie.length > 0;
}
axisFormat(val) {
const options = { day: 'numeric', month: 'short', hour: '2-digit', minute: '2-digit' };
// Esto funciona pero al hacer timeline no pone horas val.toLocaleDateString("es-ES", options);
console.log('val:', val.toLocaleDateString('es-ES', options));
return val.toLocaleDateString('es-ES', options);
}
HTML
<ngx-charts-line-chart [view]="" [scheme]="colorScheme" [results]="multi" [gradient]="gradient" [xAxis]="showXAxis" [yAxis]="showYAxis" [legend]="showLegend" legendPosition="'below'" [showXAxisLabel]="showXAxisLabel" [showYAxisLabel]="showYAxisLabel"
[xAxisLabel]="xAxisLabel" [yAxisLabel]="yAxisLabel" [autoScale]="autoScale" [timeline]="timeline" [roundDomains]="true" [animations]="animations" (select)="onSelect($event)" [xAxisTickFormatting]="axisFormat">
<ng-template #seriesTooltipTemplate let-items="model">
<p>{{items[0].name | date:'medium'}}</p>
<ul>
<li *ngFor="let item of items">
{{item.series}}: {{item.value | number}}
</li>
</ul>
</ng-template>
</ngx-charts-line-chart>
EDIT
Hello,
I have already managed to solve the problem adding an example in case it can help other people.
https://stackblitz.com/edit/click-lengd-ngx-charts
I am kinda new to Stack Overflow, but i think you should specify your answer more and show us what you already tried. Nevertheless I will try to help you.
You should give your chart a (select)="onClickFunction ($event)" in HTML. In your TS you then call the onClickFunction(event). I always start with giving it a console.log(event) to see what i get from clicking on the legend.
After clicking on the legend, you get the label of the element you clicked on. You can then search for this label in your data and remove this data out of the array you use for filling the chart.
If you provide a stackblitz or plunker wtih your code, I will gladly show you how to do it.
This is how we can achieve it for ngx-pie-chart. With the help of select event, capture it, identify the item from the data and make it zero. Next, on the next click, add the value back from the source copy. See it working here ngx-pie-chart label-filter
onSelect (event) {
let temp = JSON.parse(JSON.stringify(this.single));
if (this.isDataShown(event)) {
//Hide it
temp.some(pie => {
if (pie.name === event) {
pie.value = 0;
return true;
}
});
} else {
//Show it back
const pieToAdd = this.sourceData.filter(pie => {
return pie.name === event;
});
temp.some(pie => {
if (pie.name === event) {
pie.value = pieToAdd[0].value;
return true;
}
});
}
this.single = temp;
}
isDataShown = (name) => {
const selectedPie = this.single.filter(pie => {
return pie.name === name && pie.value !== 0;
});
return selectedPie && selectedPie.length > 0;
}

Swiper JS return to first slide

I have slider with swiper js, how it can return to first slide when we click Next Button on end of slide ?
http://idangero.us
You can set the loop parameter. For example:
var mySwiper = new Swiper ('.swiper-header', {
loop: true, //this should allow the last next button to return to the beginning
nextButton: '.swiper-button-next',
prevButton: '.swiper-button-prev',
});
i made function like this:
.swiper-next is: navigation - nextEl
var changed = false;
$(".swiper-next").on('click', function () {
if (changed === true) {
changed = false;
faqSwiper.slideTo(0);
}
if (faqSwiper.isEnd) changed = true;
})
You may use "click" event from Swiper API.
Note: setTimeout is needed to correctly determine slide index
const swiper_instance = new Swiper('.swiper-container', {
// ...
});
swiper_instance.on('click', function (swiper, event) {
const is_next_click = event.target === swiper.navigation.nextEl,
is_prev_click = event.target === swiper.navigation.prevEl,
is_end = this.isEnd,
is_beginning = this.isBeginning;
// slide to begin
if (is_next_click && is_end) {
setTimeout(() => swiper.slideTo(0))
}
// slide to end
if (is_prev_click && is_beginning) {
setTimeout(() => swiper.slideTo(swiper.slides.length))
}
});