Work Around for drag and drop in playwright python - playwright-python

I am trying to implement a drag and drop functionality(I was able to see there is an open issue regarding this) with the currently available mouse actions but so far not able to do that. so i am looking for a work around for that, is there anyway we can implement drag and drop in playwright python. below is the code that i am trying to use.
await page.mouse.move(472, 399)
await page.mouse.down()
await page.mouse.move(991, 313)
await page.mouse.up()
Thank you

I assume in your case the HTML5 drag and drop is not working.
Unfortunately at the time of writing this the current playwright python (1.10.x) won't trigger dragstart and drop events through the mouse.down, mouse.move and mouse.up API.
The following code however should work (using sync_api),
# This element should have the draggable attribute value as true
src_elem = page.query_selector('div.foo')
# This element should be the element as the drop target
dest_elem = page.query_selector('div.bar')
# Create a data transfer JSHandle instance
data_transfer = page.evaluate_handle('() => new DataTransfer()')
src_elem.dispatch_event('dragstart', { 'dataTransfer': data_transfer })
dest_elem.dispatch_event('drop', { 'dataTransfer': data_transfer })
# Now check whether the dropped effect is achieved
dest_elem.wait_for_selector('ENTER SELECTOR AFTER DROP EFFECT')

Related

Flaky snapshots with Percy and Cypress when animating

I’m adding a couple of animations to an app that has Percy taking snapshots in the cypress tests.
I’m trying to figure out a way to wait for the animations to finish before taking the snapshot.
I’m aware that cypress already does that by default according to the docs. But it seems that it only waits until the element is safe for an ACTION, but not regular assertions.
Let’s use my logo animation for example. It slides from the left to center. The flaky tests capture the snapshot anywhere in its path.
Now, just for a test, I asked cypress to click the logo and then Percy works alright, the snapshot is only taken at the end of the animation.
For this case it’s ok, since my logo does not have an action related to it. But what if clicking it had a redirect, for example?
How can I tell cypress to wait without using an action?
Can you assert the slide has finished before the snapshot?
It would involve a element.getBoundingClientRect() and manually checking the position.
it('waits for logo to slide to center',
{viewportWidth: 1000}, // ensure fixed, appropriate viewport for the test
() => {
cy.get('#myLogo')
.should($logo => { // using should will retry until animation finishes
const left = $logo[0].getBoundingClientRect().left
expect(left).to.eq(450)
})
// snapshot now
}
)
I'm doing this with a drag and drop scenario, but finding the numbers have rounding errors.
I've added chai-almost to sort it out.
const chaiAlmost = require('chai-almost')
chai.use(chaiAlmost(1)) // allowed amount of variance in equality is 1
...
expect(left).to.almost.eq(450)
Simplest way is to add a hard cy.wait(animation-time-in-ms) before the snapshot.
It won't make the difference to the test runtime since you need the animation to finish before the test can complete.

Access multiple renderers with spectron

I'm working on an Electron application. The main process opens a first renderer (browserWindow). When the user click on a button, this renderer sends an IPC message to the main process. When this message is received, the main process opens a second, different, renderer. Those two renderers live concurently. The application works fine.
Then, using Spectron to test this app, how to access both renderers ? The problem is app.rendererProcess always returns the first renderer.
This is the same problem with app.client which always contains the WebdriverIO browser object of the first renderer and never the second.
Is there a way to list all the process of a Spectron application in a test? Is it possible to access the browser object of the second renderer ?
With AVA:
test.(async t => {
// the application is open before the test
// at this point, the first renderer is open
// click on the button to open the second renderer
await t.context.app.client.click('#bt_openSecondRenderer');
// wait for the second renderer to open
// error: this element doesn't exist
await t.context.app.client.click('elt_of_the_scnd_renderer');
});
I'm using AVA but I don't think it is the problem. So if anyone know how to make this works with Mocha or anything else, it would be very helpfull.
Thanks !
Following the philosophy given by Tim answer, instead of using BrowserWindow, we can use WebDriverIO to focus the desired window:
test.(async t => {
// here, t.context.app.client handles the first window
await t.context.app.client.windowByIndex(1).then(() => {
// here, t.context.app.client handles the second window
});
});
Like a user, Specton can only interact with the focused window. This should work but I haven't tested it:
// The docs say that app.electron gives you access to all the Electron APIs
// This should get you a list of BrowserWindows
const windows = await t.context.app.electron.BrowserWindow.getAllWindows();
// Focus the window you want to interact with
windows[1].focus();
// Do your clicking
await t.context.app.client.click('elt_of_the_scnd_renderer');
it('Switch window', async () => {
await app.client.waitUntilWindowLoaded(100000)
.windowByIndex(0);
.windowByIndex(1);
})

drag and drop using selenium ruby capybara

I am trying to drag an element and drop to another element on the page. My code runs without any errors. But the drag actually doesn't happen.
It's able to find both the elements. I tried all the options listed below:
driver.browser.action.drag_and_drop(fromobject.native,
toobject.native).perform
fromobject.drag_to toobject
driver.browser.action.move_to(toobject.native).release.perform
fromobject.drag_and_drop_on toobject
If from_element.drag_to to_element doesn't work for you, then it's probably not going to be possible to do it directly with capybara/selenium. The reason for this is that drag and drop support in drivers is highly dependent on what events your code is looking for. Current versions of selenium implement it as the events mouse down, mouse move, mouse up whereas your code may be looking for drag start, drag, drag end events, etc. Because of this, to make it work you'll need to create synthetic events using execute_script to trigger the behavior you want. If you are using specific libraries someone may have already implemented this nicely for you - for instance, if you're using JQuery UI Sortable elements there is https://github.com/mattheworiordan/jquery.simulate.drag-sortable.js

Possible navigation issue in React Native/Redux app

During navigation in big React Native app with using Redux all visited scenes (scenes from navigation stack) are staying mounted. All these scenes receive props and get rendered in the order they were visited when any action is dispatched from last scene component. It causes freezes and visible delays between dispatching and last scene rendering.
For navigation I am using react-native-router-flux but same issue happens with original React Native Navigator too.
Video Possible navigation issues in React Native/Redux app
Code react-redux-navigation-test
Would be nice to know how to prevent passing props to not focused components from the navigation chain.
At the moment I am checking in shouldComponentUpdate of each component if this one is focused(visible) and return false in opposite case.
Is there any better solution?
I recommend that you calculate the scene distance between the current scene and scene being rendered using the navigation index in the scene and header rendering methods. If the distance > 1 return null.
This should prevent rendering the entire navigation history. It doesn't make any sense to me that this kind of behaviour is not available out of the box, but there it is.
I have not used the react-native-router-flux, however I do have experience with a fairly large React Native and Redux app. I have noticed that sometimes if the data you are working with gets large enough it can cause noticeable delays, but those are mostly limited to working in development. When the app is built it is usually noticeably faster. It seems as though Redux does things a little differently in development and production modes.
Regarding scenes in the navigation stack still being mounted, that is by design. Even when you navigator.push to another screen those previous screens remain mounted until they are either popped off the currentRouteStack or replaced from the currentRouteStack.
Also, it's probably worth noting that your simulator is in Slow Animations mode. Not sure if you did that for the video sake or not, but the navigation slowness is in part due to that. Just a heads up in case that wasn't on purpose.
I would check how the app seems to function after you've built it and it's not in development mode before troubleshooting the performance issues much further. May not be an issue for the final app product.
I'm going to go out on a limb here but are you using one of the below methods to prevent re-rendering?
PureComponents (added in React 15.3 I think)
Manually with shallow compare props and state with shouldComponentUpdate method.
By default React will re-render all components upon update unless you correctly handle the shouldComponentUpdate.
I'm doing something similar and not having these issues at all
We solved it by simply wrapping all screens in a component.
We have one ScreenView component that wraps the whole screen, and we pass it a parameter "restrictRerendersToRoutes".
This screen is connected to the state, and we update the currentScrene in our state and expose it to this screen view.
Then we simply restrict rerenders when the screen is in the background with this shouldComponentUpdate implementation:
shouldComponentUpdate(nextProps) {
if (!_.empty(this.props.restrictRerendersToRoutes)) {
return !!this.props.restrictRerendersToRoutes
.find((routeKey) => routeKey === nextProps.currentScene.name);
}
return true;
}
The problem is indeed that the whole navigation stack is connected to the store( because components are not unmounted unless you use resetto or resetnavigation )
For what it's worth here is what I do right now.
I have been working with a slightly modified react redux implementation that skips updates for scenes that are not in view ( see below )
To use it you need to:
Store the route for one component tree in context
We created a wrapper for this
const CurrentRoute = React.createClass({
childContextTypes : { currentRoute: PropTypes.object },
getChildContext() {
return { currentRoute: this.props.route }
},
render() { return this.props.children; }
})
And use it in render scene
<CurrentRoute route={route}><CurrentScene navigate={navigate} route={route} index={index} /></CurrentRoute>
Then you can access the route a component has been rendered into.
Store the navigation stack in a singleton
We use this code in configure scene
let routeStack = [];
export const updateRouteStack = stack => routeStack = stack;
Then you can use this slightly modified react-redux connect function, it will skip updates if component is rendered in another component tree then the currently displayed one
( or a similar implementation )
https://github.com/reactjs/react-redux/compare/master...ganmor:master
It might be possible to package this but I haven't had the time to look into it. If anyone feels like doing it..
Hope that helps

st_widget_get_theme_node errors on drag

I'm trying to implement a drag and drop system in the extension I'm developing but I'm running into a problem.
As far as I can tell, dnd is implemented by making a draggable object like this
let draggable = DND.makeDraggable(this.actor)
where this.actor is the Clutter actor I want to drag and drop, and then implementing the necessary callbacks. However, when I do this, Gnome Shell immediately crashes when I start to drag and leaves output on stderr like this
(gnome-shell:15279): St-ERROR **: st_widget_get_theme_node called on the widget [0x2b3c000 StBoxLayout.window-list-item-box:focused ("extension.js (~/Source/js/Botto...gmail.com) - GVIM")] which is not in the stage.
However, using the Looking Glass to call the get_theme_node method on that specific widget does work perfectly!
Do I have to explicitly add actors to the stage? And how could get_theme_node fail somewhere deep inside the belly of Gnome Shell, but not from the Looking Glass?
It is also necessary to implement a getDragActor and getDragActorSource method on the delegate of the actor you're trying to drag.
Here is a simple implementation that just drags around a clone of the actor.
getDragActor: function() {
return new Clutter.Clone({source: this.actor,
reactive: false,
width: this.actor.get_width(),
height: this.actor.get_height()});
},
getDragActorSource: function() {
return this.actor;
}

Resources