Structure Dynamic TestCafe runs - testing

I'm trying to test that multiple types of users (separated out into roles) can log in and view a listing page and each applicable type of filter. Since it's redundant to write this N times for every user compounded by every filter I'm using the following:
export const filters = {
typeOne: {
'Alerts': 'alerts',
'Open': 'open',
'Pending': 'pending',
'Finished': 'finished',
'Closed': 'closed'
},
/* ... */
}
export const roleTitles = {
typeOne: 'User Type One',
typeTwo: 'User Type Two',
/* ... */
}
const getSelectorMenuItem = (label) => Selector('.marketplace-side-nav.menu').find('.item').withText(label)
const selectorMap = Selector('.map-container')
const selectorMarketplaceList = Selector('.marketplace-list')
Object.keys(roles).map(async (role) => {
await Promise.all(Object.keys(filters[role]).map(async (filterTitle) => {
test(`${roleTitles[role]} Can open ${filterTitle} filter`, async t => {
const expectedPath = `marketplace/all/${filters[role][filterTitle]}`
await t.useRole(roles[role])
.click(getSelectorMenuItem(filterTitle))
.expect(getLocation()).contains(expectedPath, { timeout: 3000 })
.expect(selectorMap.exists).ok()
.expect(selectorMarketplaceList.exists).ok()
})
}))
})
This works, however, it is extremely slow. I'm not foreign to the fact that e2e tests take time, but it seems to hang once it reaches the last element in any of the filter types.

Related

Prevstate in reactJs

This might be a silly question, but how do I get data if I saved the state using prevState.
I am trying to retrieve data from database and send that data through navigation.
const [dataFromDatabase, setDataFromDatabase] = useState('');
const retrieveFromDatabase = () => {
db.transaction(
tx => {
tx.executeSql("SELECT * FROM PreLoveeedTable",
[],
(_, { rows }) => {
console.log("ROWS RETRIEVED");
// clear data currently stored
setDataFromDatabase('');
let entries = rows._array;
entries.forEach((entry) => {
setDataFromDatabase(prev => prev + `${entry.id}, ${entry.image}, ${entry.title}, ${entry.price}, ${entry.description}\n
});
},
(_, result) => {
console.log('SELECT failed!');
console.log(result);
}
)
}
);
}
{dataFromDatabase} will give me the whole entire data in the database.
But wanted to have each entry in the Database. For example entry for title.
I have been stuck on this for a while now and would be appreciated it if i can get a hint.

How to share the composition across components in api-composition style?

In my application I have two separate components:
products component (show the products in the ui)
filter-products component (show the criteria in ui)
total-filter-products component (show the total criteria items was applied in ui, for example my current search is age,name so on)
They are separate and not communicate with input (:) or output (#).
I also have a ts file, with function useProducts as "api-composition style".
export const useProducts = () => {
const criteria = ref({ category: null, age: null, color: null });
const items = computed(() => { return store.get('products').filter(p => filterByCritiria(p)) });
const load = () => {
const params = parseSome(criteria.value);
axios.post('/api/...', { params }).then(r => { store.set('products', r.data)});
}
return { criteria, items, load }
}
In the products component, I just get the products from useProducts and bind to the template:
setup() {
const { products } = useProducts();
return { products }
}
In the filter-products, I get the criteria from useProducts and bind to the template. every time some value change in criteria ref (using v-model), I run the load function.
setup() {
const { criteria, load } = useProducts();
watch(() => criteria.value, (v) => load() });
return { criteria }
}
In total-filter-products component I do some logic to display the criteria:
setup() {
const { criteria } = useProducts();
return { criteria: parse(criteria) }
}
The problem with this is every time I call to useProducts I execute the function and get new variables.
I get three times the criteria. so if I change the criteria in filter-products, the total-filter-products and products components will never know about it.
How to share the composition across components in api-composition style?

How to compare results of two vuejs computed properties

Our application has events that users can apply to, as well as blog posts written about different events. We want to show users all of the blog posts for events where they have applied.
Each post has an eventId and each application object contains event.id. We want to show all of the posts where the the eventId is equal to one of the application.event.id's.
Here are our computed properties...
computed: {
...mapState(['posts', 'currentUser', 'applications']),
myApplications: function() {
return this.applications.filter((application) => {
return application.user.id === this.currentUser.uid
})
},
myEventPosts: function() {
return this.posts.filter((post => {
post.eventId.includes(this.myApplications.event.id)
})
}
How can we change meEventPosts to get the show the correct results?
Thanks!
This question is mostly related to JS, not Vue and calculated properties. It will be better if you create such a code snippet the next time, as I did below.
const posts = [{eventId: 1, name: 'Post 1'}, {eventId: 2, name: 'Post 2'}, {eventId: 3, name: 'Post 3'}];
const myApplications = [{eventId: 2, name: 'App 2'}];
const myEventPosts = function () {
const eventsIds = myApplications.map((app) => app.eventId);
return posts.filter((post) => eventsIds.includes(post.eventId));
}
console.log('posts:', myEventPosts());
So your myEventPosts computed property should look like:
myEventPosts: function() {
const eventsIds = this.myApplications.map((app) => app.eventId);
return this.posts.filter((post) => eventsIds.includes(post.eventId));
}

redux-observables mergeMap w/ two outputs

I have an epic like this
/**
* Request a new account from the API
*/
export function signupApiRequest(action$: Observable, store: Store) {
return action$.ofType(SIGNUP)
.map(action => [ action, store.getState().accounts.signup ])
.mergeMap(([ action, signup ]) =>
sendCommand('/api/accounts/signup', {
name: signup.name,
email: signup.email
})
.map(response => [ response, signup.email ])
)
.mergeMap(([ response, email ]) => {
switch (response.status) {
case 409:
return [existingUser(email)];
case 201:
const succ = { type: successOf(SIGNUP) },
user = mapTokenToUser(response.body.data),
created = userCreated(user);
console.log('signup success', [succ, created]);
return [succ, created];
default:
throw new Error(`Unknown response code ${response.code}`);
}
});
}
When signing up, 'signup success' is printed and both actions are logged as they should.
However, only the first of the actions is outputted from the epic.
Why and what am I doing wrong?
Changing the order in the array makes the other value get outputted.
We've discovered this appears to be a bug in RxJS itself starting in 5.1.0. There's an exception being thrown in your reducer but it's being swallowed silently by RxJS.
https://github.com/redux-observable/redux-observable/issues/263#issuecomment-310180351
How it's interacting with redux/redux-observable is a little complicated, but ultimately not related as this can be reproduced with:
https://jsbin.com/dukixu/edit?html,js,output
const input$ = new Rx.Subject();
input$
.mergeMap(() => Rx.Observable.of(1, 2))
.subscribe(d => {
throw new Error('some error');
});
input$.next();

Using map to reduce in Gun

I am new to Gun. I have existing code that very effectively reduces an array of objects based on a pattern. I am thinking I should tweak this to run in the context of Gun's .map and return undefined for non-matches. I think I will also have to provide two arguments, one of which is the where clause and the other the properties I want shown on returned objects. I also presume that if I use .on future matches will automagically get spit out! Am I on the right path?
const match = (object,key,value) => {
const type = typeof(value);
if(value && type==="object") {
return Object.keys(value).every(childkey =>
match(object[key],childkey,value[childkey]));
if(type==="function") return value(object[key]);
return object[key]===value;
}
const reduce = (objects,where) => {
const keys = Object.keys(where);
return objects.reduce((accumulator,current) => {
if(keys.every(key => match(current,key,where[key]))) {
accumulator.push(current);
}
return accumulator;
},[]);
}
let rows = reduce([{name: "Joe",address:{city: "Seattle"},age:25},
{name: "Mary",address:{city: "Seattle"},age:16},
{name: "Joe",address:{city: "New York"},age:20}],
{name: () => true,
address: {city: "Seattle"},
age: (age) => age > 10});
// results in
[{name: "Joe",address:{city: "Seattle"},age:25},
{name: "Mary",address:{city: "Seattle"},age:16}]
Further exploration of this resulted in the code below, which is stylistically different, but conforms to the immediate responsive nature of Gun. However, it is unclear how to deal with nested objects. The code below only works for primitives.
const match = (object,key,value) => {
const type = typeof(value);
if(!object || typeof(object)!=="object") return false;
if(value && type==="object") {
const child = gun.get(object[key]["#"]);
for(let key in value) {
const value = {};
child.get(key).val(v => value[key] = v,{wait:0});
if(!match(value,key,value[key])) return;
}
}
if(type==="function") return value(object[key]);
return object[key]===value;
}
const gun = Gun(["http://localhost:8080/gun"]),
users = [{name: "Joe",address:{city: "Seattle"},age:25},
{address:{city: "Seattle"},age:25},
{name: "Mary",address:{city: "Seattle"},age:16},
{name: "Joe",address:{city: "New York"},age:20}];
//gun.get("users").map().put(null);
for(let user of users) {
const object = gun.get(user.name).put(user);
gun.get("users").set(object);
}
gun.get("users").map(user => {
const pattern = {name: (value) => value!=null, age: (age) => age > 20}; //, address: {city: "Seattle"}
for(let key in pattern) {
if(!match(user,key,pattern[key])) return;
}
return user;
}).on(data => console.log(data));
Yes. GUN's .map method does more than what it seems.
Say we have var users = gun.get('users'). We can do:
users.map() with no callback acts like a forEach because the default callback is to return the data as-is.
users.map(user => user.age * 2) with a callback, it lets you transform the data like you would expect from a map, except where:
users.map(function(){ return }) if you return undefined, it will filter out that record.
WARNING: As of the current time, .map(transform) function is currently experimental and my have bugs with it. Please try it and report any you find.
Now we can combine it with some other methods, to get some cool behavior:
users.map().on(cb) will get current and future users as they are added to the table, and gets notified for updates on each of those users.
users.map().val(cb) will get current and future users as they are added to the table, but only gets each one once.
users.val().map().on(cb) gets only the current users (not future), but gets the updates to those users.
users.val().map().val(cb) gets only the current users (not future), and only gets them once.
So yes, you are on the right track. For instance, I have a test in gun core that does this:
list.map(user => user.age === 27? user.name + "thezombie" : u).on(function(data){
// verify
});
list.set({name: 'alice', age: 27});
list.set({name: 'bob', age: 27});
list.set({name: 'carl', age: 29});
list.set({name: 'dave', age: 25});
This creates a live map that filters the results and locally (view only) transforms the data.
In the future, this is how the SQL and MongoDB Mango query extensions will work for gun.
Note: GUN only loads the property you request on an object/node, so it is bandwidth efficient. If we do users.map().get('age') it will only load the age value on every user, nothing else.
So internally, you can do some efficient checks, and if all your conditionals match, only /then/ load the entire object. Additionally, there are two other options: (1) you can use an in-memory version of gun to create server-side request-response patterns, so you can have server-side filtering/querying that is efficient. (2) if you become an adapter developer and learn the simple wire spec and then write your own custom query language extensions!
Anything else? Hit me up! More than happy to answer.
Edit: My reply in the comments, comments apparently can't have code. Here is pseudo-code of how to "build up" more complex queries, which will be similar to how SQL/Mango query extensions will work:
mutli-value & nested value matching can be "built up" from this as the base, but yes, you are right, until we have SQL/Mango query examples, there isn't a simple/immediate "out of the box" example. This is pseudo code, but should get the idea across:
```
Gun.chain.match = function(query, cb){
var gun = this;
var fields = Object.keys(query);
var check = {};
fields.forEach(function(field){
check[field] = true;
gun.get(field).val(function(val){
if(val !== query[field]){ return }
check[field] = false;
//all checks done?
cb(results)
});
});
return gun;
}
```
Solution, the trick is to use map and not val:
Gun.chain.match = function(pattern,cb) {
let node = this,
passed = true,
keys = Object.keys(pattern);
keys.every(key => {
const test = pattern[key],
type = typeof(test);
if(test && type==="object") {
node.get(key).match(test);
} else if(type==="function") {
node.get(key).map(value => {
if(test(value[key])) {
return value;
} else {
passed = false;
}
});
} else {
node.get(key).map(value => {
if(value[key]===test) {
return value;
} else {
passed = false;
}
});
}
return passed;
});
if(passed && cb) this.val(value => cb(value))
return this;
}
const gun = new Gun();
gun.get("Joe").put({name:"Joe",address:{city:"Seattle"},age:20});
gun.get("Joe").match({age: value => value > 15,address:{ city: "Seattle"}},value => console.log("cb1",value));