RxJs Marble testing concatMap with withLatestFrom - testing

How can be unit tested this Observable?
e1.pipe(
concatMap(x => of(x).pipe(withLatestFrom(e2)))
);
Following unit test fails:
it('test', () => {
const e1 = hot( '--1^---2----3-|');
const e2 = hot( '-a-^-b-----c--|');
const expected = cold( '----x----y-|', {
x: ['2', 'b'],
y: ['3', 'c']
});
const result = e1.pipe(
concatMap(x => of(x).pipe(
withLatestFrom(e2))
)
);
// but this works:
// const result = e1.pipe(withLatestFrom(e2));
expect(result).toBeObservable(expected);
});
How the marbles should be written in order to pass this unit test? What did I do wrong?
I expect by inserting concatMap operator in the chain (before withLatestFrom) I have to also somehow "mark" it in the marbles.

In your real example
e1.pipe(
concatMap(x => of(x).pipe(withLatestFrom(e2)))
);
everything works fine probably because is either a BehaviorSubject or a ReplaySubject, which it's not case in your test.
Although you're using hot( '-a-^-b-----c--|');, it does not imply that you're using a BehaviorSubject. If we look at the implementation, we'll see that HotObservable extends the Subject class:
export class HotObservable<T> extends Subject<T> implements SubscriptionLoggable { /* ... */ }
which should help understand why this works:
const result = e1.pipe(withLatestFrom(e2));
and this doesn't:
const result = e1.pipe(
concatMap(x => of(x).pipe(
withLatestFrom(e2))
)
);
In the first snippet, e2 is subscribed when e1 is subscribed. In the second one, because you're using concatMap, every time e1 emits, withLatestFrom(e2)) will be subscribed and then unsubscribed, due to the complete notification that comes from of(x).
With this in mind, here would be my approach:
Note: I'm using the built-in functions provided by rxjs/testing
it('test', () => {
// might want to add this in a `beforeEach` function
let testScheduler = new TestScheduler(
(actual, expected) => (console.log({actual, expected}),expect(actual).toEqual(expected))
);
testScheduler.run(({ hot, expectObservable }) => {
const e1 = hot( '--1^---2----3-|');
const e2src = hot( '-a-^-b-----c--|');
const e2 = new BehaviorSubject(undefined);
const result = e1.pipe(
concatMap(x => of(x).pipe(
withLatestFrom(e2))
)
);
const source = merge(
result,
e2src.pipe(
tap(value => e2.next(value)),
// this is important as we're not interesting in `e2src`'s values
// it's just a way to `feed` the `e2` BehaviorSubject
ignoreElements()
)
);
expectObservable(source).toBe('----x----y-|', {
x: ['2', 'b'],
y: ['3', 'c']
});
});
})

Related

what is the difference between writing composables and exporting stuff separately?

We're developing an application on vue3-composition-api.
so we are developing scripts on this concept called composables. We use this composables in different places for reusing stuff instead of rewriting them, The problem is that some parts of the composables are created but not being used and it seems to have an impact on performance. Checkout these three approaches.
useFeatureA.js - FIRST APPROACH (using stateful composables)
export function useFeatureA() {
const x = ref(false)
const y = computed(() => {
// uses x.value
})
const z = computed(() => {
// uses x.value
})
const foo = () => {
// uses y.value and z.value
// sets on x.value
}
const bar = () => {
// uses z.value
// sets on x.value
}
return { y, foo, bar }
}
useFeatureA.js - SECOND APPROACH (exporting separately and recompute everytime)
export const getX = () => {
return ref(false);
}
export const getY = (x) => {
return computed(() => {
// uses x.value
});
}
export const foo = (xValue, yValue) => {
const z = // using xValue
// uses yValue and z
return // something to write on x
}
export const bar = (xValue) => {
const z = // using xValue
// uses and z
return // something to write on x
}
ComponentA
<script setup>
const { getX, getY, foo, bar } = useFeatureA();
const x = getX();
const y = getY(x);
x.value = foo(x.value, y.value);
x.value = bar(x.value);
</setup>
useFeatureA.js - THIRD APPROACH (move state to component)
export const getX = () => {
return ref(false);
}
export const getY = (x) => {
return computed(() => {
// uses x.value
});
}
export const getZ = (x) => {
return computed(() => {
// uses x.value
});
}
export const foo = (yValue, zValue) => {
// uses yValue and zValue
return // something to write on x
}
export const bar = (zValue) => {
// uses and z
return // something to write on x
}
ComponentA
<script setup>
const { getX, getY, foo, bar } = useFeatureA();
const x = getX();
const y = getY(x);
const z = getZ(x);
x.value = foo(y.value, z.value);
x.value = bar(z.value);
</setup>
we are wondering whether this solution can be efficient or not and what the differences between these two approaches are.
NOTE: We came up with the idea of separating those two functions in two different composables but the problem is that the project is too big and this approach makes way too many composables while foo and bar are very close to each other because of being related to a specific feature. so we guess this approach of separating them on different composables is out of question.
UPDATE: we have this idea that if we need stateful composable, the second approach is a bottleneck since if the components uses the composable, after the component is destroyed, the state remains in memory.
we guess in second approach tree-shaking is more efficient.

How to check number exists in Firebase Database? - react-native-firebase

I use react native through firebase database
I have a database creating products each product has a number
I want to take a number and compare it with the product number
And if there is then I want to get a product
the function its give me my correct name but where i use it on render its not found the variable (name)
getAllContact = async key => {
let barCodeData2 = this.props.navigation.state.params.barcodeData
let self = this;
let contactRef = firebase.database().ref()
contactRef.on("value", dataSnapsot => {
if (dataSnapsot.val()) {
let contactResult = Object.values(dataSnapsot.val())
let contactKey = Object.keys(dataSnapsot.val())
contactKey.forEach((value, key) => {
contactResult[key]["key"] = value
})
self.setState({
fname: contactResult.fname,
data: contactResult.sort((a, b) => {
var nameA = a.barcode
var nameB = barCodeData2
const name = a.fname
console.log(`${nameA} What numers issssssss`);
if (nameA == nameB) {
alert(`${name} ........`)
console.log(`${nameA == nameB}is Equqlqlqlql`);
return name
}
}),
})
}
})
}
render() {
let t=this.state.name
alert(`${t} how?`)// is give Not found
// let d = this.props.navigation.state.params.barcodeData
return (
)
}
When you try such a comparison query i.e.
let ref = firebase.firestore();
ref.collection('zoo')
.where("id", "==", myID)
.get()
.then((snapshot) => {
console.log(snap.empty); //this will denote if results are empty
snapshot.forEach(snap => {
console.log(snap.exists); //alternatively this will also tell you if it is empty
})
})
well what you can do is run query based on you product no and if there's a product you will a product if there's none you will get an empty array.
read firebase documentation on queries
https://firebase.google.com/docs/reference/js/firebase.database.Query

Multiple props in Ramda lens

Is there a way to apply transforms to multiple keys of an object in Ramda? I am aware this is achievable by R.evolve, but I am interested in knowing if this can be achieved by some modification of lenses.
E.g.:
const data = {
a: "100",
b: "non_numeric_string",
c: "0.5"
}
const numerize = x => +x
const mapping = {
a: numerize,
c: numerize
}
magicFunction(mapping, data)
output:
{
a: 100,
b: "non_numeric_string",
c: 0.5
}
The whole point of a lens is to focus on one part of a data structure. While it is not hard to write something using lensProp to achieve this, I'm don't think it's either very satisfying or a particularly appropriate use of lenses. Here's one Ramda solution:
const magicFunction = (mapping, data) =>
reduce
( (o, [k, fn]) => over (lensProp(k), fn, o)
, data
, toPairs (mapping)
)
const numerize = x => Number (x)
const mapping = {
a: numerize,
c: numerize
}
const data = {a: "100", b: "non_numeric_string", c: "0.5"}
console .log (
magicFunction (mapping, data)
)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
<script> const { lensProp, over, reduce, toPairs } = R </script>
But note that a plain ES6 function does the job just as simply, without using lenses:
const magicFunction = (mapping, data) =>
Object.entries (mapping). reduce
( (o, [k, fn]) => ({...o, [k]: fn (o [k]) })
, data
)
Lenses simply don't gain you much here.

How to Improve The axios.spread

The below code i use for doing multiple HTTP calls depending on the studentList.
It works well; however, I think the axios spread is not necessary
export default {
getFee (studentList: { studentId: string }[]) {
if (studentList.length < 1) {
Promise.resolve()
}
let promises = []
for (const student of studentList) {
if (!student.studentId) {
Promise.resolve()
}
var url = `${API_URL}/${student.studentId}`
promises.push(Axios.get(url))
}
return Axios.all(promises)
.then(Axios.spread((...args) => {
// customise the response here
return args
.map(response => response.data)
.map(data => {
// #ts-ignore
data.totalMark = data.markinPhysics + data.markinMaths + data.markinChemistry // total mark sum of marks in differnet discplines
return data
})
}))
.catch(error => {
switch (error.response.status) {
case 400:
console.log('student not found')
break
case 500:
console.log('error invoking')
break
default:
console.log('unknown error')
I have to do multiple network calls in Vue and I am using Axios.
I got it working by axios, all and axios.spread, but I think the code can be improved.
The logic is to do multiple calls for the student list and get the outputs back
Can anyone help?
Axios.all
as well as Promise.all accepts array of promises and returns a new Promise which is resolved whenever all of the given promises are resolved with an array with the result of each promise
e.g.
const promise1 = Promise.resolve('data1');
const promise2 = Promise.resolve('data2');
Promise.all([
promise1,
promise2,
]).then(results => {
// results is an array with 2 elements
console.log(results[0]); // data1
console.log(results[1]); // data2
});
you can use Axios.spread to to assign each result to a variable like this:
Promise.all([
promise1,
promise2,
]).then(Axios.spread(( result1, result2 ) => {
// args is an array with 2 elements
console.log(result1); // data1
console.log(result2); // data2
});
alternatively you can use ES6 Destructuring assignment:
Promise.all([
promise1,
promise2,
]).then(([ result1, result2 ]) => {
// args is an array with 2 elements
console.log(result1); // data1
console.log(result2); // data2
});
Unnecessary Promise.resolve()
Your Promise.resolve() function calls have no effect on the getFee method since you're not returning them
What would my implementation be
async function getFee(studentList) {
try {
const promises = studentList.reduce((acc, student) =>
student.studentId
? acc.concat(Axios.get(`${API_URL}/${student.studentId}`))
: acc
, []);
const responses = await Axios.all(promises);
return responses
.map(response => response.data)
.map(data => ({
// return new object
// with data's properties
// instead of assinging the new ones directly to the data
...data,
// total mark sum of marks in differnet discplines
totalMark: data.markinPhysics + data.markinMaths + data.markinChemistry,
}));
} catch (error) {
switch (error.response.status) {
case 400:
console.log("student not found");
break;
case 500:
console.log("error invoking");
break;
default:
console.log("unknown error");
}
}
}
export default {
getFee
}
Since you're only using args as an array, you could remove axios.spread.
axios.spread() might only be useful in older browsers now that ES2015 introduced its own spread operator. The main purpose of axios.spread() is to expand the result of axios.all() into an argument list, such that you could do:
axios.all(promiseArray).then(axios.spread(function(arg1, arg2, arg3) {
/*...*/
}))
instead of:
axios.all(promiseArray).then(function(args) {
var arg1 = args[0]
var arg2 = args[1]
var arg3 = args[2]
/*...*/
})
ES2015's rest operator does the inverse of axios.spread(), so when you combine them (as seen below), you end up with the result above, as if axios.spread() and the rest operator weren't even used:
axios.all(promiseArray).then(axios.spread(function(...args) {
var arg1 = args[0]
var arg2 = args[1]
var arg3 = args[2]
/*...*/
}))
// or newer syntax:
axios.all(promiseArray).then(axios.spread((...args) => {
const arg1 = args[0]
const arg2 = args[1]
const arg3 = args[2]
/*...*/
}))
To avoid promise chaining and improve readability, I think below can be used.
const [arg1, arg2] = await Promise.all(promises)

How to assert function invocation order in jest

I am mocking two functions with with jest.fn:
let first = jest.fn();
let second = jest.fn();
How can I assert that first called before second?
What I am looking for is something like sinon's .calledBefore assertion.
Update
I used this simple "temporary" workaround
it( 'should run all provided function in order', () => {
// we are using this as simple solution
// and asked this question here https://stackoverflow.com/q/46066250/2637185
let excutionOrders = [];
let processingFn1 = jest.fn( () => excutionOrders.push( 1 ) );
let processingFn2 = jest.fn( () => excutionOrders.push( 2 ) );
let processingFn3 = jest.fn( () => excutionOrders.push( 3 ) );
let processingFn4 = jest.fn( () => excutionOrders.push( 4 ) );
let data = [ 1, 2, 3 ];
processor( data, [ processingFn1, processingFn2, processingFn3, processingFn4 ] );
expect( excutionOrders ).toEqual( [1, 2, 3, 4] );
} );
The solution by clemenspeters (where he wanted to make sure logout is called before login) works for me:
const logoutSpy = jest.spyOn(client, 'logout');
const loginSpy = jest.spyOn(client, 'login');
// Run actual function to test
await client.refreshToken();
const logoutOrder = logoutSpy.mock.invocationCallOrder[0];
const loginOrder = loginSpy.mock.invocationCallOrder[0];
expect(logoutOrder).toBeLessThan(loginOrder)
Instead of your workaround you can install jest-community's jest-extended package which provides support for this via .toHaveBeenCalledBefore(), e.g.:
it('calls mock1 before mock2', () => {
const mock1 = jest.fn();
const mock2 = jest.fn();
mock1();
mock2();
mock1();
expect(mock1).toHaveBeenCalledBefore(mock2);
});
Note: per their doc you need at least v23 of Jest to use this function
https://github.com/jest-community/jest-extended#tohavebeencalledbefore
P.S. - This feature was added a few months after you posted your question, so hopefully this answer still helps!