react-hook, sparate tests that expected update same hook over re-render - react-testing-library

let assume I have that hook
function useTest(initValue=0) {
const value = useRef(initValue)
useEffect(() => {
value.current +=1
})
return value.current;
}
And I want to test it behevur on multiple tests
describe.only('auto increment', () => {
let testedHook;
beforeAll(() => {
// const Hook = renderHook((items, options) => useAnimeManager(items, options))
testedHook = renderHook(() => useTest())
})
test('first run', () => {
expect(testedHook.result.current).toBe(0)
testedHook.rerender()
expect(testedHook.result.current).toBe(1)
})
test('second run', () => {
testedHook.rerender() // throw : Cannot update an unmounted root.
expect(testedHook.current).toBe(2)
})
})
The problem now is the the next test after I call rerender() in the second time it Throw "Cannot update an unmounted root."

Related

Failed to add new elements when set initialState as an empty object

I try to use redux toolkit and I have this as menu-slice.js
I try to use property accessors to add a new property to fileItems, its initial value is an empty object.
import { createSlice } from "#reduxjs/toolkit";
const menuSlice = createSlice({
name: "ui",
initialState: {
fileItems: {},
},
reducers: {
setFileDate: (state, action) => {
state.FileDate = action.payload;
},
replaceFileItems: (state, action) => {
const filesList = action.payload.map((fileName) =>
fileName.slice(fileName.indexOf("/") + 1)
);
state.fileItems[state.FileDate] = filesList;
console.log(`filesList: ${filesList}`);
console.log(`state.fileItems: ${JSON.stringify(state.fileItems)}`);
console.log(`state.FileDate: ${state.FileDate}`);
state.fileContents = null;
},
I call dispatch with the api return value ( dispatch(menuActions.replaceFileItems(fileResponse.data));)
in menu-action.js:
the return value is an array of strings.
export const fetchFiles = (fileDate) => {
return async (dispatch) => {
const fetchFilesList = async () => {
const response = await fetch(
"some url" +
new URLSearchParams({
env: "https://env.com",
date: fileDate,
})
);
if (!response.ok) {
throw new Error("Fail to fetch files list!");
}
const data = await response.json();
return data;
};
try {
const fileResponse = await fetchFilesList();
dispatch(menuActions.setFileDate(FileDate));
dispatch(menuActions.replaceFileItems(fileResponse.data));
} catch (error) {
dispatch(
menuActions.showNotification({....
})
);
}
};
};
But it never prints console logs and didn't display where went wrong in the console or in the chrome redux extension.
I want to add data into state.fileItems on each click that triggers fetchFiles() when it returns a new array:
from state.fileItems = {}
check if state.fileItems already has the date as key,
if not already has the date as key,
change to ex: state.fileItems = {"2022-01-01": Array(2)}
and so on..
ex: state.fileItems = { "2022-01-01": Array(2), "2022-01-02": Array(2) }
I also tried to set state.fileItems as an empty array, and use push, but it didn't work either, nothing printed out, state.fileItems value was always undefined.
Can anyone please tell me why this didn't work?
Thanks for your time to read my question.

PWA cache gets deleted on redirects?

Both the static and dynamic cache get deleted from the browser when you want to visit another link. So if you go offline and try to make a request you then get an error page instead of a cached response. If you then click the back button in browser and then the forward button the cache comes back and it works. I might have something wrong with verifying the cache on activation?
This is my service worker:
const staticCacheName = "CacheV1";
const dynamicCacheName = "DynamicCacheV1";
const dynamicCacheLimit = 18;
const assets = [
'/',
'/css/main_styles.css',
'/js/ui.js',
'/js/jquery-3.6.0.slim.min.js',
'/icons/search.svg',
'/icons/favicon.svg',
'/img/bg.png',
'/img/og.png',
'/img/generated.svg',
'/icons/at.svg',
'/icons/heartFull.svg',
'/icons/comment.svg',
'/icons/share.svg',
'/icons/report.svg',
'/manifest.json',
'/fonts/titillium-web-300.woff2',
/* ... */
];
// This just deletes access dynamic cache
const limitCacheSize = (name, size) => {
caches.open(name).then(cache => {
cache.keys().then(keys => {
if(keys.length > size) {
cache.delete(keys[0]).then(limitCacheSize(name, size));
}
});
});
}
// Install service worker
self.addEventListener('install', evt => {
evt.waitUntil(
caches.open(staticCacheName).then(cache => {
cache.addAll(assets);
})
);
});
// Activate event
self.addEventListener('activate', evt => {
evt.waitUntil(
caches.keys().then(keys => {
return Promise.all( keys
.filter(key => key !== staticCacheName && key !== dynamicCacheName)
.map(key => caches.delete(key))
)
})
)
});
// Fetch event
self.addEventListener('fetch', evt => {
evt.respondWith(
caches.match(evt.request).then(cacheRes => {
return cacheRes || fetch(evt.request).then(fetchRes => {
return caches.open(dynamicCacheName).then(cache => {
if (evt.request.headers.has('range')) {
return cacheRes;
} else {
cache.put(evt.request.url, fetchRes.clone());
limitCacheSize(dynamicCacheName, dynamicCacheLimit);
return fetchRes;
}
});
});
}).catch(() => {
if (!/./.test(evt.request.url)) {
return caches.match('/img/fallback.html');
} else if(/.jpeg|.jpg|.png|.webp/.test(evt.request.url)) {
return caches.match('/img/fallbackImage.png');
} else if(/.gif/.test(evt.request.url)) {
return caches.match('/img/fallbackImage.png');
} else if(/.mp3|.ogg|.aac|.wav/.test(evt.request.url)) {
return caches.match('/img/beepBoop.mp3');
}
})
)
});

How to use Grid.js with data being updated every second

setInterval(() => {
// lets update the config
grid.updateConfig({
server: {
url: document.location.href + 'api.json/',
then: data => data.map(obj => {
return [obj.name, obj.value]
}),
handle: (res) => {
// no matching records found
if (res.status === 404) return { data: [] }
if (res.ok) return res.json()
throw Error('oh no :(')
}
}
}).forceRender()
}, 2000)
This snippet make the work, but loading message and flicking/redraw all table are ruining UX.

How to set axios token for client side in nuxt server init?

I'm trying to authenticate my user when the page is loading. So I have the following code :
actions: {
nuxtServerInit ({dispatch, commit, app}, context) {
return new Promise((resolve, reject) => {
const cookies = cparse.parse(context.req.headers.cookie || '')
if (cookies.hasOwnProperty('x-access-token')) {
app.$axios.setToken(cookies['x-access-token'], 'Bearer')
api.auth.me2()
.then(result => {
commit('setUser', result.data.user)
resolve(true)
})
.catch(error => {
commit('resetUser')
resetAuthToken()
resolve(false)
})
} else {
resetAuthToken()
resolve(false)
}
})
}
However I have the following error :
Cannot read $axios property of undefined. What is wrong with my code ?
App should come from context e.g. from second argument.
So your code should be
context.app.$axios.setToken(cookies['x-access-token'], 'Bearer')
Another way. You could pass app in the second argument such that
nuxtServerInit ({dispatch, commit}, {app}) {
The complete code:
actions: {
nuxtServerInit ({dispatch, commit}, {app}) {
return new Promise((resolve, reject) => {
const cookies = cparse.parse(context.req.headers.cookie || '')
if (cookies.hasOwnProperty('x-access-token')) {
app.$axios.setToken(cookies['x-access-token'], 'Bearer')
api.auth.me2()
.then(result => {
commit('setUser', result.data.user)
resolve(true)
})
.catch(error => {
commit('resetUser')
resetAuthToken()
resolve(false)
})
} else {
resetAuthToken()
resolve(false)
}
})
}
}

How I can call Observable.complete callback function? It doesn't work

In ionic 2, (and angularfire2#4.0.0-rc.0, firebase#3.9.0)
I tried this code, but complete function doesn't work!
constructor(public af: AngularFireDatabase, ...) {
this.temp = af.list('/myTest').subscribe(data => {
... // my tastks
}, error => {
console.log(error);
}, () => {
console.log("done!"); // I can't see this output!
});
}
I already tried very many times, but I can't see "done".
In another function, I tried this but the result is same with first.
console.log(this.temp.closed); // false
this.temp.unsubscribe()
console.log(this.temp.closed); // true
,, What can I do..?
AngularFire list and object observables do not complete. Their internal Firebase refs remain connected, listening for changes to the database.
If you want the list to complete after the first value is received, you can use the first operator:
import "rxjs/add/operator/first";
constructor(public af: AngularFireDatabase, ...) {
this.temp = af.list('/myTest')
.first()
.subscribe(data => {
... // my tastks
}, error => {
console.log(error);
}, () => {
console.log("done!");
});
}
Note that complete handlers are not called upon unsubscription. They are called when the observable completes.
If you want a callback to be invoked upon either completion or unsubscription, you can use the finally operator instead:
import "rxjs/add/operator/finally";
constructor(public af: AngularFireDatabase, ...) {
this.temp = af.list('/myTest')
.finally(() => {
console.log("done!");
})
.subscribe(data => {
... // my tastks
}, error => {
console.log(error);
});
}