Why some tests are failing when running detox in parallel? - automated-tests

I'm running Detox with Jest.
If i'm running the tests on 2 workers they all pass, but if i'm running the same tests on 4 workers some of the tests failing
Thanks for helping in advance.

I Managed to overcome this issue and minimize the amount a the failing tests running in parallel.
First I reduced the amount of workers to 3 instead of 4.
Second I configured the before and after hooks in every test file.
From this:
beforeEach(async () => {
await device.launchApp({
permissions: {
notifications: 'YES',
location: 'always',
userTracking: 'YES',
camera: 'YES',
medialibrary: 'YES',
photos: 'YES',
},
})
})
afterAll(async () => {
await device.terminateApp()
})
To this:
beforeEach(async () => {
await device.terminateApp()
await device.launchApp({
permissions: {
notifications: 'YES',
location: 'always',
userTracking: 'YES',
camera: 'YES',
medialibrary: 'YES',
photos: 'YES',
},
})
})
afterAll(async () => {
await detox.cleanup()
await device.terminateApp()
})
So before every test run detox making sure the app is terminated.
in addition I add detox.cleanup() after the tests are done for a better test closure
Hope this will be helpful for anyone who encounter this issue as me.

Related

Vue 3 Vite Pinia Unit Testing - TypeError: [Function] is not a spy or a call to a spy! ONLY when running Coverage

In my Vue 3 (using Vite and vi-test) app I am using Pinia and I've written some unit basic tests which run ok when I run
npm run test:unit
but when I run
npm run coverage
I get test errors:
TypeError: [Function] is not a spy or a call to a spy!
Anyone know why one would work but not the other?
This is my script setup in package.json:
"test:unit": "vitest --environment jsdom",
"coverage": "vitest run --coverage",
Here's an example of a test - this will run fine with the first command but with the second command will give the above error on the expect(store.clearCheckedData) line
describe("ContactBook", () => {
let mockProps = {};
let wrapper:any;
beforeEach(() => {
wrapper = render(ContactBook, {
props: mockProps,
global: {
components: {ProgressSpinner,Button,InputText,BaseButton},
plugins: [PrimeVue,
createTestingPinia({
initialState: {contact:{
mockRegistrationData: mockRegistrationData,
loading: false,
}},
stubActions: false,
createSpy: vi.fn,
fakeApp:true
}),
],
},
});
setActivePinia(createPinia());
});
afterEach(() => {
cleanup();
});
it("when Year / Reg Group tab is clicked, registrations component is rendered", async() => {
const button = screen.getByText('Year / Reg Group')
await userEvent.click(button);
const store = useContactBookStore();
expect(store.clearCheckedData).toHaveBeenCalledTimes(1) // ERROR ON THIS LINE
expect(store.fetchRegistrationData).toHaveBeenCalledTimes(2)
wrapper.getByTestId("registrations-component")
});

Nextjs and workbox integration

Requirement: I am trying to use service worker and cache static files so as to have a benefit to reduce HTTP requests and make the site performance better. 
Down the lane I would switch to offline, caching images, api's etc.
I have seen the plugins:
https://github.com/hanford/next-offline and
https://www.npmjs.com/package/next-pwa
It seems to work. Although I was trying to find out if there were examples of (nextjs + workbox).
Next js do have an example for https://github.com/vercel/next.js/tree/canary/examples/with-next-offline. But I would like just using workbox for this.
Anyone got any working examples? Even a basic one would do.
Currently am not using a custom server. Just using the inbuilt builder of nextjs (https://nextjs.org/docs/getting-started#manual-setup)
I figured out an answer on my own:
Reference: https://developers.google.com/web/tools/workbox/reference-docs/latest/module-workbox-build#.generateSW
I have done runtime caching for my app here and added the workbox file into the base file:
// Use the window load event to keep the page load performant
useEffect(() => {
window.addEventListener("load", () => {
const serviceWorkerScope = `/${country}/workbox-worker.js`
navigator.serviceWorker
.register(serviceWorkerScope)
.then(() => {
logger.info(`Service worker registered at ${serviceWorkerScope}`)
})
.catch(error => {
logger.error("Error in serviceWorker registration: ", error)
})
})
})
I have added comments,
// File to generate the service worker.
require("dotenv").config()
const workboxBuild = require("workbox-build")
const { COUNTRY: country, NODE_ENV } = process.env
const urlPattern = new RegExp(`/${country}\/static|_next\/.*/`)
// https://developers.google.com/web/tools/workbox/reference-docs/latest/module-workbox-build#.generateSW
const buildSW = () => {
return workboxBuild.generateSW({
swDest: "public/workbox-worker.js",
clientsClaim: true,
mode: NODE_ENV,
skipWaiting: true,
sourcemap: false,
runtimeCaching: [
{
urlPattern: urlPattern,
// Apply a cache-first strategy.
handler: "CacheFirst",
options: {
cacheName: "Static files caching",
expiration: {
maxEntries: 50,
maxAgeSeconds: 15 * 60, // 15minutes
},
},
},
],
})
}
buildSW()

SQlite3 and knexjs results in Timeout acquiring a connection

I am trying to run the following code and getting an error
{ TimeoutError: Knex: Timeout acquiring a connection. The pool is
probably full. Are you missing a .transacting(trx) call?
Is there anyway to make sqlite wait until the pool is empty? if not, what would you suggest?
const path = require('path');
const knex = require('knex')({
client: 'sqlite3',
useNullAsDefault: true,
connection: {
filename: path.join(__dirname, '/db/sqlite.db')
}
});
knex('lorem')
.insert({ rowid: 'Slaughterhouse Five' })
var z = 0;
while (z < 20000) {
knex('lorem')
.select('rowid')
.then(result => {
console.log('res', result);
})
.catch(error => console.log('Error in select', error));
z++;
}
I would suggest to not trying to run 20000 parallel queries. At which point would you like to wait the pool being empty? You could run all the queries one by one or you could use for example Bluebird's .map() which allows to pass concurrency paramater to limit how many queries are resolved at the same time.

Jest finishing async test before done()

I'm writing an async test in Jest and having trouble. I'm pretty sure the test is finishing and passing before the async call returns anything in spite of everything I've tried. I know the function works because it logs out the correct response after the test suite has finished. Here is the test code:
describe('updateUser', () => {
test('should update a user', (done) => {
updateUser(user).then(({err, res}) => {
console.log('updated user:', err, res); // this show up after the test is done
expect(err).toBeFalsy();
expect(res).toBeTruthy();
done();
});
});
});
console output:
updateUser
✓ should update a user (68ms)
Test Suites: 1 passed, 1 total
Tests: 3 passed, 3 total
Snapshots: 0 total
Time: 6.058s
Ran all test suites.
console.log server/db/crud_Users/crud_user.test.js:38
updated user: null { homeLocations: [],
meetingPlaces: [],
hostedEvents: [],
attendingEvents: [],
flags: [],
tokens: [],
_id: 5b2147495995cb45f9c4f079,
name: 'test',
email: '83277963493533480000#test.com',
password: 'testtest',
ageRange: '1',
gender: 'Female',
accountCreatedAt: null,
__v: 0 }
Expected behavior: the test suite waits for the console.log statement and the assertions to run before finishing.
Actual behavior: it doesn't.
I also tried making the test callback an async function and awaiting the updateUser call, but nothing changed; I tried tacking the done() callback on in a second .then block as well, with no results.
It's just about how Jest output things in async tests. I have just checked but don't see how to proof that.
If you remove done(); call you will get test failed because of timeout exceeded.
If you change your expectation to be invalid you will also get your test failed.
So it works fine. For sure.
Also since updateUser returns Promise you don't need to run done(). Just return Promise so test would be slightly lighter:
test('should update a user', () => {
return updateUser(user).then(({err, res}) => {
expect(err).toBeFalsy();
expect(res).toBeTruthy();
});
});

How can I write use previous returned value of an observable with redux-observable?

I don't know my question title is suitable for this question.
I would like to use returned value of someAsync1 (same as v2) as argument of action1 inside of flatMap.
const anEpic = ($action: ActionsObservable<MyAction>, store: Store<MyRootStore>) => {
return $action.ofType(ActionTypes.AN_ASYNC_ACTION)
.switchMap((v1) => someAsync1(v1))
.switchMap((v2) => someAsync2(v2))
.map((v) => applyToUI(v))
.flatMap((v) => Observable.concat(Observable.of(action1(v)), Observable.of(action2(true)))) //
}
I guess I can use that value by injecting v2 to returned value of someAsync2. But that code looks disgusting.
What is clever way to do this with redux-observable?
switchMap technically means, well, switch to another Observable stream. That means there is no way for you to retain the value because your observer is now observing a different source.
There are a few ways to do the so called "retaining" the values from one stream to another, depending on which one you prefer.
1. Behaviour Subject
This is the most preferred way, because the purpose of BehaviourSubject is to retain a value of an Observable:
//initialize a BehaviourSubject
let v2BSubject = new BehaviourSubject<any>(null);
const anEpic = ($action: ActionsObservable<MyAction>, store: Store<MyRootStore>) => {
return $action.ofType(ActionTypes.AN_ASYNC_ACTION)
.switchMap((v1) => someAsync1(v1))
.switchMap((v2) => {
//store your v2 value here!
v2BSubject.next(v2);
return someAsync2(v2)
})
.map((v) => applyToUI(v))
.flatMap((v) => {
//get your v2 values here
let v2Value = v2BSubject.value;
return Observable.concat(Observable.of(action1(v)), Observable.of(action2(true)))
}) //
}
or you can use it as an Observable. That way you can treat it as an observable and use whatever rxjs operator can provide:
.flatMap((v) => {
return Observable.concat(Observable.of(action1(v)), v2BSubject.asObservable())
})
2. Use .map to propagate the value.
This is rather hacky, but gets the job done. However do note it's modifying the stream source. If you have many operations along the pipe, it may blow up quickly and hard to manage:
const anEpic = ($action: ActionsObservable<MyAction>, store: Store<MyRootStore>) => {
return $action.ofType(ActionTypes.AN_ASYNC_ACTION)
.switchMap((v1) => someAsync1(v1))
.switchMap((v2) => {
someAsync2(v2)
.map(afterSomeAsync2 => {
return {
v1Value: v2,
v2Value: afterSomeAsync2
}
})
})
.map(({v1Value, v2Value}) => {
return applyToUI(v1Value).map(v1 => {
return {
v1Value: v1,
v2Value: v2Value
}
})
})
.flatMap(({v1Value, v2Value}) => {
return Observable.concat(Observable.of(action1(v1Value)), Observable.of(v2Value))
})
The easiest solution is to apply your operators directly on the returned inner Observables instead of on the collapsed outer chain. You can then access the values emitted because they're part of the closures.
That's probably confusing, but hopefully this code makes it clear:
const anEpic = ($action: ActionsObservable<MyAction>, store: Store<MyRootStore>) => {
return $action.ofType(ActionTypes.AN_ASYNC_ACTION)
.switchMap((v1) =>
someAsync1(v1)
.switchMap((v2) =>
someAsync2(v2)
.map((v) => applyToUI(v))
.flatMap((v) => Observable.of(action1(v, v1, v2), action2(true))
)
)
}
This pattern is also what you would have to use if you wanted to catch any errors by someAsync1 or someAsync2 because if you let the error propagate to the top-level chain the epic will have stopped listening for future actions.
e.g. if your epic looks like this:
const somethingEpic = (action$, store) => {
return action$.ofType(SOMETHING)
.switchMap(action => someAsync1(v1))
.map(() => ({ type: SOMETHING_FULFILLED }))
.catch(error => Observable.of({
type: SOMETHING_REJECTED,
error
}));
}
When the error reaches the catch operator it's too late, your epic is no longer listening for future actions. You could "restart" it, but this can have unexpected consequences so its best to avoid this pattern.
Instead, catch the error before it propagates out
const somethingEpic = (action$, store) => {
return action$.ofType(SOMETHING)
.switchMap(action =>
someAsync1(v1)
.map(() => ({ type: SOMETHING_FULFILLED }))
.catch(error => Observable.of({
type: SOMETHING_REJECTED,
error
}))
);
}
Some people refer to this as "isolating your observer chains".
Also notice how I didn't need to use concat with multiple of because of supports any number of arguments.

Resources