Webdriverio can't do drag and drop for SVG tspan element - webdriver-io

I tried to do drag and drop for SVG tspan elements, but it's not working, also tried to use browser.performActions, still not working, any idea? Browser is google chrome: version 103.0.5060.53, webdriverio version is 7.20.5. Below is the code:
let x1, x2, y1, y2, from, target;
const el = await $$('tspan');
for (const e of el) {
if((await e.getText())==="input_field"){
from = e;
x1=parseInt(await from.getLocation('x'),10);
y1=parseInt(await from.getLocation('y'),10);
console.log("input",x1,y1);
}
else if((await e.getText())==="output_field"){
target = e;
x2=parseInt(await target.getLocation('x'),10);
y2=parseInt(await target.getLocation('y'),10);
console.log("output",x2,y2);
}
}
const xoffset =x2-x1;
const yoffset=y2-y1;
console.log("offset",xoffset,yoffset);
await from.dragAndDrop(target, 500);
await browser.performActions([
{
"type": "pointer",
"id": "mouse1",
"parameters": {"pointerType": "mouse"},
"actions": [
{"type": "pointerMove", "duration": 0, "x": x1, "y": y1},
{"type": "pointerDown", "button": 0},
{"type": "pause", "duration": 1000},
{"type": "pointerMove", "duration": 1000, "origin": "pointer", "x": xoffset, "y": yoffset},
{"type": "pointerUp", "button": 0}
]
},
]).then(() => browser.releaseActions());

Related

Prebid - Index video outstream configuration with multiple playerSize in bidders

I would like to create an adUnit video outstream with multiple playserSizes for Index (documentation there
At first I thought to put the playerSize at the adUnit level, but because I want to define multiple playerSizes, I decided to move it at bidder level in params > video > playerSize. Nonetheless it does not work whereas in the documentation it is written
If you are using Index’s outstream player and have placed the video object at the bidder level, you must include the Index required parameters at the bidder level``` (link above)
Here is my prebid configuration
```javascript
{
"code": slotCode,
"sizes": [[1,1],[300,250],[160,600],[300,600],[640,360]],
"bids": [
{
"bidder": "criteo",
"params": {
"networkId": networkId,
"video": {
"playerSize": [640, 480],
"skip": 0,
"playbackmethod": 1,
"placement": 1,
"mimes": [
"video/mp4"
],
"maxduration": 30,
"api": [
1,
2
],
"protocols": [
2,
3
]
}
},
"userId": {...},
"userIdAsEids": [...],
"crumbs": {...}
},
{
"bidder": "index",
"params": {
"siteId": siteId,
"size": [
640,
360
],
"video": {
"playerSize": [640, 480],
"h": 640,
"w": 360,
"protocols": [
2,
3,
5,
6
],
"minduration": 5,
"maxduration": 30,
"mimes": [
"video/mp4",
"application/javascript"
],
"playerSize": [
640,
360
]
}
},
"userId": {... },
"userIdAsEids": [...],
"crumbs": {...}
}
],
"mediaTypes": {
"video": {
"context": "outstream"
}
},
"pubstack": {...}
}
If I use this configuration, I got this error
ERROR: IX Bid Adapter: bid size is not included in ad unit sizes or player size.
Even if my playerSize for index ([640, 360]) is in the adUnit sizes.
I wonder if it is possible for an adUnit to have multiple payerSizes?

Selection Transform as Text/Title

How can I display a transform over selected points as text within a title or subtitle?
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"data": {"url": "data/stocks.csv"},
"transform": [{"filter": "datum.symbol==='GOOG'"}],
"width": 800,
"title": {
"text": "Google's stock price over time.",
"subtitle": "selected average: ???"
},
"selection": {
"interval": {
"type": "interval",
"encodings": ["x"]
}
},
"mark": "point",
"encoding": {
"x": {"field": "date", "type": "temporal"},
"y": {"field": "price", "type": "quantitative"}
}
}
A sum transformation does not lend itself to any graphical/visual representations. An idea is to have it as a selection tooltip, but that is not possible. So I settle for a subtitle.
I don't think there is an easy way to insert a computed value within a subtitle, but you can achieve the same effect using a layer chart with a text mark that contains a computed value.
For example (open in editor):
{
"data": {"url": "data/stocks.csv"},
"transform": [{"filter": "datum.symbol==='GOOG'"}],
"width": 800,
"title": {"text": "Google's stock price over time."},
"layer": [
{
"transform": [
{"filter": {"selection": "interval"}},
{"aggregate": [{"op": "sum", "field": "price", "as": "total_price"}]}
],
"mark": "text",
"encoding": {
"x": {"value": 400},
"y": {"value": -10},
"text": {"field": "total_price", "type": "quantitative"}
}
},
{
"mark": "point",
"encoding": {
"x": {"field": "date", "type": "temporal"},
"y": {"field": "price", "type": "quantitative"}
},
"selection": {"interval": {"type": "interval", "encodings": ["x"]}}
}
]
}
Note that the text layer has x and y encoding values specified in pixels from the upper left of the chart.
I was going to say there are two possible approaches, but then #jakevdp post his answer, so I guess there are now three.
Use an ExprRef in title.subtitle. While that isn't explicitly supported in the documentation it doesn't make sense that only title.text would support an ExprRef. So I gave it a shot, and it works. Though the Vega editor will still raise schema validation warnings. I have a more involved example below using binned data.
Filter and aggregate the selection. This will modify the current data stream and Vega-Lite doesn't support more than one data stream (unless using layers), so you'll have to patch the generated Vega.
Access the text mark of the title using title.encode.subtitle.update.text. Once again, necessary to patch the generated Vega. (This was on the assumption that a subtitle couldn't be an ExprRef).
The neat thing about (2) is that it allows adding a text mark to the selection mark, so the text could be made to follow the selection. That said that's possible with #jakevdp's answer as well, and his answer is much simpler.
JavaScript loader ensuring that nothing runs out-of-order:
%%javascript
function loadjs(ls, o) {
let i = 0;
let b = JSON.parse(document.querySelector('#jupyter-config-data').text)["baseUrl"];
ls = ls.reduce((a,l) => {
if (!l.path)
return a;
let p = l.path;
if (l.local)
p = "/" + [b,"/files",p].map(s => s.replace(/^\/+|\/+$/, "")).filter(i => i).join("/");
if (document.querySelector("script[src='" + p + "']"))
return a;
return [...a, p];
}, [])
function load() {
if (i >= ls.length)
return o();
let t = document.createElement("script");
[t.type, t.src, t.onload] = ["text/javascript", ls[i], (i+1>=ls.length) ? o : load];
i = i+1;
document.head.appendChild(t);
}
return load();
}
window.loadjs = loadjs
JavaScript loader for the JupyterLab cell as an IPython magic:
import IPython
import IPython.core.magic as ipymagic
#ipymagic.magics_class
class LoadJSMagics(ipymagic.Magics):
#ipymagic.cell_magic
def loadjs(self, line, cell):
js = f"loadjs({line}, () => {{\n{cell}\n}});"
return IPython.display.Javascript(js)
IPython.get_ipython().register_magics(LoadJSMagics)
Jinja templating for JupyterLab cells as an IPython magic:
import jinja2
import IPython
import IPython.core.magic as ipymagic
#ipymagic.magics_class
class JinjaMagics(ipymagic.Magics):
#ipymagic.cell_magic
def jinja(self, line, cell):
t = jinja2.Template(cell)
r = t.render({k:v for k,v in self.shell.user_ns.items() if k not in self.shell.user_ns_hidden})
IPython.get_ipython().run_cell(r)
#d = getattr(IPython.display, line.strip(), IPython.display.display)
#return d(r)
IPython.get_ipython().register_magics(JinjaMagics)
Generate some example temporal data in Pandas:
import pandas as pd
import numpy as np
c1 = np.random.randint(1,6, size=15)
c2 = pd.date_range(start="2021-01-01",end="2021-01-15")
df = pd.DataFrame({"day": c2, "value": c1})
df = df.drop([2, 5,6,7,13])
df
The necessary imports:
# Convert the Pandas dataframe to a format suitable for Vega-Lite.
import altair
# Tag Vega-Embed div's with UUIDs ensuring the correct div is targeted.
import uuid
import json
vega_libs =\
[ {"path": "https://cdn.jsdelivr.net/npm/vega#5"}
, {"path": "/libs/vega-lite#4-fix.js", "local": True}
, {"path": "https://cdn.jsdelivr.net/npm/vega-embed#6"}
]
The Vega-Lite:
s =\
{ "title":
{ "text": "Daily Counts"
, "subtitle": {"expr": "selectionSum(data('interval_store'), data('data_0'))"}
, "subtitleFont": "monospace"
}
, "mark": "bar"
, "encoding":
{ "x":
{ "type": "temporal"
, "bin": "binned"
, "field": "start"
, "axis": { "tickCount": "day" }
}
, "x2": {"field": "end"}
, "y": {"type": "quantitative", "field": "value"}
}
, "selection":
{ "interval":
{ "type": "interval"
, "encodings": ["x"]
}
}
, "transform":
[ # Convert 'day' from 'string' to timestamp ('number')
{"calculate": "toDate(datum.day)", "as": "day"}
# Provide "start" and "end" as Date objects to match the
# type of temporal domain objects
, {"calculate": "timeOffset('hours', datum.day, -12)", "as": "start"}
, {"calculate": "timeOffset('hours', datum.day, 12)", "as": "end"}
]
, "height": 250
, "width": "container"
, "$schema": "https://vega.github.io/schema/vega-lite/v4.json"
, "config": {"customFormatTypes": "True"}
, "data": altair.utils.data.to_values(df)
}
And finally running the Vega-Lite:
%%jinja
%%loadjs {{json.dumps(vega_libs)}}
{% set visid = uuid.uuid4() %}
element.innerHTML = `
<style>.vega-embed.has-actions {width:90%}</style>
<div id="vis-{{visid}}"></div>
`
var spec = {{json.dumps(s)}}
vega.expressionFunction("selectionSum", function(selection, data) {
var view = this.context.dataflow;
function intersects(i1, i2) {
return (i1[1] >= i2[0] && i1[0] <= i2[1]);
}
function cmp_interval_pt(i0, i1, p) {
if (i1 < p)
return -1;
if (i0 > p)
return 1;
return 0;
}
function cmp_primitive(a,b) {
if (a < b)
return -1
if (a > b)
return 1;
return 0;
}
function bisect_left(l, v, fc=cmp_primitive) {
return _bisect_left(l, 0, l.length, v, fc);
}
function _bisect_left(l, l0, l1, v, fc) {
if (l1 <= l0)
return l0;
var i = Math.floor((l0+l1)/2);
var c = fc(l[i], v);
if (c < 0)
l0 = i + 1;
else
l1 = i;
return _bisect_left(l, l0, l1, v, fc);
}
function bisect_right(l, v, fc=cmp_primitive) {
return _bisect_right(l, 0, l.length, v, fc);
}
function _bisect_right(l, l0, l1, v, fc) {
if (l1 <= l0)
return l0;
var i = Math.floor((l0+l1)/2);
var c = fc(l[i], v);
if (c <= 0)
l0 = i + 1;
else
l1 = i;
return _bisect_right(l, l0, l1, v, fc);
}
function cmp_data(lv, v) {
return cmp_interval_pt(lv.start, lv.end, v);
}
function constant_len_digits(s,l) {
return " ".repeat(Math.max(0, l-s.toString().length)) + s
}
if (selection.length) {
var r = selection[0]["values"][0];
var d0 = bisect_left(data, r[0], cmp_data);
var d1 = bisect_right(data, r[1], cmp_data);
var s = data.slice(d0,d1).reduce((a,v)=>a+v.value, 0);
}
else
var s = 0
return `selected: ${constant_len_digits(s,3)}`;
});
vegaEmbed('#vis-{{visid}}', spec).then(function(result) {
}).catch(console.error);
And the result:
Note that when it comes to coloring and selecting binned regions, you'll have to calculate the intersections yourself.

Karate: I get missing property in path $['data'] while using json filter path

I have gone through karate documentation and questions asked on stack overflow. There are 2 json arrays under resp.response.data. I am trying to retrieve and assert "bId": 81 in below json from the resp.response.data[1] but I get this missing property error while retrieving id value 81. Could you please help if I am missing something ?
* def resp =
"""
{
"response": {
"data": [
{
"aDetails": {
"aId": 15,
"aName": "Test",
"dtype": 2
},
"values": [
{
"bId": 45,
"value": "red"
}
],
"mandatory": false,
"ballId": "1231231414"
},
{
"aDetails": {
"aId": 25,
"aName": "Description",
"dtype": 2
},
"values": [
{
"bId": 46,
"value": "automation"
},
{
"bId": 44,
"value": "NESTED ARRAY"
},
{
"bId": 57,
"value": "sfERjuD"
},
{
"bId": 78,
"value": "zgSyPdg"
},
{
"bId": 79,
"value": "NESTED ARRAY"
},
{
"bId": 80,
"value": "NESTED ARRAY"
},
{
"bId": 81,
"value": "NESTED ARRAY"
}
],
"mandatory": true,
"ballId": "1231231414"
}
],
"corId": "wasdf-242-efkn"
}
}
"""
* def expectedbID=81
* def RespValueId = karate.jsonPath(resp, "$.data[1][?(#.bId == '" + expectedbID + "')]")
* match RespValueId[0] == expectedbID
Maybe you are over-complicating things ?
* match resp.response.data[1].values contains { bId: 81, value: 'NESTED ARRAY' }

lodash filter array using query array

How can I filter an array of objects below using lodash? Here is my query
var query = { "body": ["Hatchback", "Sedan"] };
var objects = [{
"make": "BMW",
"model": "i3",
"maxRange": 81,
"price": "42,400",
"body": "Hatchback"
}, {
"make": "Chevrolet",
"model": "Spark EV",
"maxRange": 82,
"price": "25,120",
"body": "Hatchback"
}, {
"make": "Kia",
"model": "Soul EV",
"maxRange": 90,
"price": "31,950",
"body": "Wagon"
}, {
"make": "Tesla",
"model": "Model S",
"maxRange": 303.2,
"price": "75,000",
"body": "Sedan"
}, {
"make": "Tesla",
"model": "Model X",
"maxRange": 257,
"price": "83,000",
"body": "SUV"
}]
I tried to use _matches but it doesn't seem to match arrays. Here is my attempt
_.filter(objects, _.matches(query))
Ummm, I dont know about how to do with lodash but we can certainly do with vanillaJS in just two lines of code though.
var query = { "body": ["Hatchback", "Sedan"] };
var filteredObjArray = objects.filter(obj => query.body.includes(obj.body)))
Hope that helps :).
You can use JS .filter with .every to check multiple properties. If a query property is an array use .include to compare, if not make a simple comparison:
function multipleFilter(arr, query) {
var queryKeys = Object.keys(query); // create an array of the keys in the query object
return arr.filter(function(item) {
return queryKeys.every(function(key) { // use .every on the keys so if one fails, the item is filtered out
var keyData = item[key]; // get the data of the key from the item
var keyQuery = query[key]; // get the query from query object
return Array.isArray(keyQuery) ? keyQuery.includes(keyData) : keyQuery === keyData; // if the query is an array use include, if not use comparison
});
});
}
var objects = [{
"make": "BMW",
"model": "i3",
"maxRange": 81,
"price": "42,400",
"body": "Hatchback"
}, {
"make": "Chevrolet",
"model": "Spark EV",
"maxRange": 82,
"price": "25,120",
"body": "Hatchback"
}, {
"make": "Kia",
"model": "Soul EV",
"maxRange": 90,
"price": "31,950",
"body": "Wagon"
}, {
"make": "Tesla",
"model": "Model S",
"maxRange": 303.2,
"price": "75,000",
"body": "Sedan"
}, {
"make": "Tesla",
"model": "Model X",
"maxRange": 257,
"price": "83,000",
"body": "SUV"
}];
var query1 = {
"body": ["Hatchback", "Sedan"]
};
var query2 = {
"body": ["Hatchback", "Sedan"],
make: "BMW"
};
console.log('query1', multipleFilter(objects, query1));
console.log('query2', multipleFilter(objects, query2));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>

jsaTypeError: GoogleTiledMap is not a constructor

I define a class and then use it to create a layer.but it has error.but I don't know where it was wrong?
define(["dojo/_base/declare","esri/SpatialReference","esri/layers/TiledMapServiceLayer","esri/geometry/webMercatorUtils","esri/geometry/Extent",
"esri/layers/TileInfo"],function(declare,SpatialReference,TiledMapServiceLayer,webMercatorUtils,Extent,TileInfo){
declare("extras.layer.GoogleTiledMap", [TiledMapServiceLayer], {
online: false,
mapStyle: "roadmap",
constructor: function(a) {
this.spatialReference = new esri.SpatialReference({
wkid: 102113
});
this.online = a.online || false;
this.mapStyle = a.mapStyle || "roadmap";
this.layerId = a.layerId;
this.suffix = a.suffix || ".png";
this.tile_url = a.tile_url;
this.fullExtent = new Extent( - 20037508.342787, -20037508.342787, 20037508.342787, 20037508.342787, this.spatialReference);
this.initialExtent = new Extent(12557877.595482401, 2596928.9267310356, 12723134.450635016, 2688653.360673282);
this.tileInfo = new TileInfo({
"rows": 256,
"cols": 256,
"compressionQuality": 0,
"origin": {
"x": -20037508.342787,
"y": 20037508.342787
},
"spatialReference": {
"wkid": 102113
},
"lods": [{
"level": 3,
"scale": 73957190.948944,
"resolution": 19567.8792409999
},
{ ...
I use it in html file.
require([
"esri/map",
"extras/layer/GoogleTiledMap",
"dojo/domReady!"
], function(map,GoogleTiledMap) {
var layer=new GoogleTiledMap({
"id": "100",
"layerId":"GXX_XXXXX",
"online":false,
"name": "谷歌电子地图",
"suffix": "png",
"tileSize": "256",
"tileType": "googlemap",
"mapStyle":"roadmap",
"tile_url": "127.0.0.1:8080"
});
Just declaring is not sufficient, you need to return it as well. Like below
define(["dojo/_base/declare",...], function(declare,...){
return declare([...], {
//you module here
});
});