How to test redux state update with react testing library and jest
I'm trying to write a test with jest and react testing library to see if the store updates a state and the new state is shown inside the component.
I have a component like:
import { getName } from 'src/store/actions/hello/getName';
const HelloComponent = () => {
const dispatch = useDispatch();
const { name, isLoading } = useSelector((state:RootState) => state.Hello)
useEffect( () => {
dispatch(getName());
}, []);
return (
<div>
{ name &&
Hello {name}
}
</div>
)
}
There is the store which calls an API like:
const getName = () => (dispatch) => {
const URL = getUrl()
fetch(URL, {method: 'GET'})
.then((response) => response.json())
.then(({ data }) => dispatch({
type: 'SAVE_NAME',
payload: data.name
})) # This action updates the name inside the redux state
};
I'm using mswjs to mock the API call and I'd like to test that after the component mount, the DOM shows 'Hello John'.
This is the test I've written, but it doesn't work:
it('shows the name', async () => {
const {findByText} = renderWithStore(<HelloComponent />);
expect(await findByText('Hello John')).toBeInTheDocument();
});
renderWithStore mocks the store.
import configureStore from 'redux-mock-store';
import { render as rtlRender } from '@testing-library/react'
import { initialState as Hello } from '../src/store/reducers/helloReducer';
const mockStore = configureStore()
const initialStateMock = {
Hello
}
function render(
ui
) {
const store = mockStore(initialStateMock);
function Wrapper({ children }) {
return <Provider store={store}>{children}</Provider>
}
return rtlRender(ui, { wrapper: Wrapper })
}
It seems like it doesn't wait for the state to update.
any help is much appreciated
Thanks
See also questions close to this topic
-
Get channel's filesize limit
While most discord servers have an 8MB limit for files, some servers have a 50MB limit, and some even up to 100MB. Is it possible to detect this programmatically using the API?
-
WHAT DHOULD I DO TO covert this code into js code?
export default { "kind": "customsearch#search", "url": { "type": "application/json", "template": "https://www.googleapis.com/customsearch/v1?q={searchTerms}&num={count?}&start={startIndex?}&lr={language?}&safe={safe?}&cx={cx?}&sort={sort?}&filter={filter?}&gl={gl?}&cr={cr?}&googlehost={googleHost?}&c2coff={disableCnTwTranslation?}&hq={hq?}&hl={hl?}&siteSearch={siteSearch?}&siteSearchFilter={siteSearchFilter?}&exactTerms={exactTerms?}&excludeTerms={excludeTerms?}&linkSite={linkSite?}&orTerms={orTerms?}&relatedSite={relatedSite?}&dateRestrict={dateRestrict?}&lowRange={lowRange?}&highRange={highRange?}&searchType={searchType}&fileType={fileType?}&rights={rights?}&imgSize={imgSize?}&imgType={imgType?}&imgColorType={imgColorType?}&imgDominantColor={imgDominantColor?}&alt=json" }, "queries": { "request": [ { "title": "Google Custom Search - null", "totalResults": "714000000", "searchTerms": "null", "count": 10, "startIndex": 1, "inputEncoding": "utf8", "outputEncoding": "utf8", "safe": "off", "cx": "4dd5f1a91dbb3df63" } ], "nextPage": [ { "title": "Google Custom Search - null", "totalResults": "714000000", "searchTerms": "null", "count": 10, "startIndex": 11, "inputEncoding": "utf8", "outputEncoding": "utf8", "safe": "off", "cx": "4dd5f1a91dbb3df63" } ] }, "context": { "title": "Google" }, "searchInformation": { "searchTime": 0.621603, "formattedSearchTime": "0.62", "totalResults": "714000000", "formattedTotalResults": "714,000,000" }, "items": [ { "kind": "customsearch#result", "title": "null - JavaScript | MDN", "htmlTitle": "\u003cb\u003enull\u003c/b\u003e - JavaScript | MDN", "link": "https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/null", "displayLink": "developer.mozilla.org", "snippet": "6 days ago ... The value null represents the intentional absence of any object value. It is one of \nJavaScript's primitive values and is treated as falsy for ...", "htmlSnippet": "6 days ago \u003cb\u003e...\u003c/b\u003e The value \u003cb\u003enull\u003c/b\u003e represents the intentional absence of any object value. It is one of \u003cbr\u003e\nJavaScript's primitive values and is treated as falsy for ...", "cacheId": "gM3xYrhtmoYJ", "formattedUrl": "https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/.../null", "htmlFormattedUrl": "https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/.../\u003cb\u003enull\u003c/b\u003e", "pagemap": { "BreadcrumbList": [ {} ], "metatags": [ { "theme-color": "#ffffff", "viewport": "width=device-width,initial-scale=1", "position": "1" } ] } }, { "kind": "customsearch#result", "title": "Null | Definition of Null by Merriam-Webster", "htmlTitle": "\u003cb\u003eNull\u003c/b\u003e | Definition of \u003cb\u003eNull\u003c/b\u003e by Merriam-Webster", "link": "https://www.merriam-webster.com/dictionary/null", "displayLink": "www.merriam-webster.com", "snippet": "Null definition is - having no legal or binding force : invalid. How to use null in a \nsentence. Did You Know?", "htmlSnippet": "\u003cb\u003eNull\u003c/b\u003e definition is - having no legal or binding force : invalid. How to use \u003cb\u003enull\u003c/b\u003e in a \u003cbr\u003e\nsentence. Did You Know?", "cacheId": "7pVU1R0KV8kJ", "formattedUrl": "https://www.merriam-webster.com/dictionary/null", "htmlFormattedUrl": "https://www.merriam-webster.com/dictionary/\u003cb\u003enull\u003c/b\u003e", "pagemap": { "cse_thumbnail": [ { "src": "https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcSKksTSKYwpW8It403nrjw5t1_a8pLO2PI6ImEG7uvFrNfacgiziPZgG-_O", "width": "225", "height": "225" } ], "metatags": [ { "msapplication-tilecolor": "#2b5797", "og:image": "https://merriam-webster.com/assets/mw/static/social-media-share/mw-logo-245x245@1x.png", "twitter:title": "Definition of NULL", "twitter:card": "summary", "theme-color": "#ffffff", "twitter:url": "https://www.merriam-webster.com/dictionary/null", "og:title": "Definition of NULL", "twitter:aria-text": "Share the Definition of null on Twitter", "og:aria-text": "Post the Definition of null to Facebook", "og:description": "having no legal or binding force : invalid; amounting to nothing : nil; having no value : insignificant… See the full definition", "twitter:image": "https://merriam-webster.com/assets/mw/static/social-media-share/mw-logo-245x245@1x.png", "referrer": "unsafe-url", "fb:app_id": "178450008855735", "twitter:site": "@MerriamWebster", "viewport": "width=device-width, initial-scale=1.0", "twitter:description": "having no legal or binding force : invalid; amounting to nothing : nil; having no value : insignificant… See the full definition", "og:url": "https://www.merriam-webster.com/dictionary/null" } ], "cse_image": [ { "src": "https://merriam-webster.com/assets/mw/static/social-media-share/mw-logo-245x245@1x.png" } ] } }, { "kind": "customsearch#result", "title": "Gaerea -'Null' (official music video) 2020 - YouTube", "htmlTitle": "Gaerea -'\u003cb\u003eNull\u003c/b\u003e' (official music video) 2020 - YouTube", "link": "https://www.youtube.com/watch?v=v1ooMJ1jUxw", "displayLink": "www.youtube.com", "snippet": "May 13, 2020 ... Gaerea's official music video for the track 'Null', taken from their upcoming album '\nLimbo'. Release date: July 24, 2020. WE ARE GAEREA.", "htmlSnippet": "May 13, 2020 \u003cb\u003e...\u003c/b\u003e Gaerea's official music video for the track '\u003cb\u003eNull\u003c/b\u003e', taken from their upcoming album '\u003cbr\u003e\nLimbo'. Release date: July 24, 2020. WE ARE GAEREA.", "formattedUrl": "https://www.youtube.com/watch?v=v1ooMJ1jUxw", "htmlFormattedUrl": "https://www.youtube.com/watch?v=v1ooMJ1jUxw", "pagemap": { "cse_thumbnail": [ { "src": "https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcTkJbQm9TyOvkUyYLnMN9Ir7v1DywDFlR5wC-ek6ayT3izewvdkPAM0NDmk", "width": "300", "height": "168" } ], "imageobject": [ { "width": "1280", "url": "https://i.ytimg.com/vi/v1ooMJ1jUxw/maxresdefault.jpg", "height": "720" } ], "person": [ { "name": "Season of Mist", "url": "http://www.youtube.com/user/SeasonOfMistLabel" } ], "metatags": [ { "og:image": "https://i.ytimg.com/vi/v1ooMJ1jUxw/maxresdefault.jpg", "twitter:app:url:iphone": "vnd.youtube://www.youtube.com/watch?v=v1ooMJ1jUxw&feature=applinks", "theme-color": "rgba(255,255,255,0.98)", "og:image:width": "1280", "twitter:card": "player", "og:site_name": "YouTube", "twitter:url": "https://www.youtube.com/watch?v=v1ooMJ1jUxw", "al:android:package": "com.google.android.youtube", "title": "Gaerea -'Null' (official music video) 2020", "al:ios:url": "vnd.youtube://www.youtube.com/watch?v=v1ooMJ1jUxw&feature=applinks", "twitter:app:id:iphone": "544007664", "og:description": "Gaerea's official music video for the track 'Null', taken from their upcoming album 'Limbo'. Release date: July 24, 2020. WE ARE GAEREA.Order here: http://re...", "al:ios:app_store_id": "544007664", "twitter:image": "https://i.ytimg.com/vi/v1ooMJ1jUxw/maxresdefault.jpg", "twitter:site": "@youtube", "og:video:type": "text/html", "og:video:height": "720", "og:video:url": "https://www.youtube.com/embed/v1ooMJ1jUxw", "og:type": "video.other", "twitter:title": "Gaerea -'Null' (official music video) 2020", "al:ios:app_name": "YouTube", "og:title": "Gaerea -'Null' (official music video) 2020", "og:image:height": "720", "twitter:app:id:ipad": "544007664", "al:web:url": "http://www.youtube.com/watch?v=v1ooMJ1jUxw&feature=applinks", "og:video:secure_url": "https://www.youtube.com/embed/v1ooMJ1jUxw", "og:video:tag": "gaerea", "og:video:width": "1280", "al:android:url": "vnd.youtube://www.youtube.com/watch?v=v1ooMJ1jUxw&feature=applinks", "fb:app_id": "87741124305", "twitter:app:name:ipad": "YouTube", "twitter:description": "Gaerea's official music video for the track 'Null', taken from their upcoming album 'Limbo'. Release date: July 24, 2020. WE ARE GAEREA.Order here: http://re...", "og:url": "https://www.youtube.com/watch?v=v1ooMJ1jUxw", "al:android:app_name": "YouTube", "twitter:app:name:iphone": "YouTube" } ], "videoobject": [ { "embedurl": "https://www.youtube.com/embed/v1ooMJ1jUxw", "playertype": "HTML5 Flash", "isfamilyfriendly": "true", "uploaddate": "2020-05-13", "description": "Gaerea's official music video for the track 'Null', taken from their upcoming album 'Limbo'. Release date: July 24, 2020. WE ARE GAEREA.Order here: http://re...", "videoid": "v1ooMJ1jUxw", "url": "https://www.youtube.com/watch?v=v1ooMJ1jUxw", "duration": "PT6M1S", "unlisted": "False", "name": "Gaerea -'Null' (official music video) 2020", "paid": "False", "width": "1280", "regionsallowed": "AD,AE,AF,AG,AI,AL,AM,AO,AQ,AR,AS,AT,AU,AW,AX,AZ,BA,BB,BD,BE,BF,BG,BH,BI,BJ,BL,BM,BN,BO,BQ,BR,BS,BT,BV,BW,BY,BZ,CA,CC,CD,CF,CG,CH,CI,CK,CL,CM,CN,CO,CR,CU,CV,CW,CX,CY,CZ,DE,DJ,DK,DM,DO,DZ,EC,EE,EG,EH...", "genre": "Music", "interactioncount": "102475", "channelid": "UC5TaZWeRgdN7klKM60Hj6rQ", "datepublished": "2020-05-13", "thumbnailurl": "https://i.ytimg.com/vi/v1ooMJ1jUxw/maxresdefault.jpg", "height": "720" } ], "cse_image": [ { "src": "https://i.ytimg.com/vi/v1ooMJ1jUxw/maxresdefault.jpg" } ] } }, { "kind": "customsearch#result", "title": "Null - Wikipedia", "htmlTitle": "\u003cb\u003eNull\u003c/b\u003e - Wikipedia", "link": "https://en.wikipedia.org/wiki/Null", "displayLink": "en.wikipedia.org", "snippet": "Null may refer to: Contents. 1 Science, technology, and mathematics. 1.1 \nComputing; 1.2 Mathematics; 1.3 Physics; 1.4 Other uses in science and \ntechnology.", "htmlSnippet": "\u003cb\u003eNull\u003c/b\u003e may refer to: Contents. 1 Science, technology, and mathematics. 1.1 \u003cbr\u003e\nComputing; 1.2 Mathematics; 1.3 Physics; 1.4 Other uses in science and \u003cbr\u003e\ntechnology.", "cacheId": "N5Dv23xCZiAJ", "formattedUrl": "https://en.wikipedia.org/wiki/Null", "htmlFormattedUrl": "https://en.wikipedia.org/wiki/\u003cb\u003eNull\u003c/b\u003e", "pagemap": { "metatags": [ { "referrer": "origin" } ] } }, { "kind": "customsearch#result", "title": "The Terrible Mistake of Choosing 'Null' as a License Plate - YouTube", "htmlTitle": "The Terrible Mistake of Choosing '\u003cb\u003eNull\u003c/b\u003e' as a License Plate - YouTube", "link": "https://www.youtube.com/watch?v=_c1am8NSx_s", "displayLink": "www.youtube.com", "snippet": "Jun 9, 2020 ... The Terrible Mistake of Choosing 'Null' as a License Plate. 2,681,508 views2.6M \nviews. • Jun 9, 2020. 92K. 2.7K. Share. Save. 92,296 / 2,757 ...", "htmlSnippet": "Jun 9, 2020 \u003cb\u003e...\u003c/b\u003e The Terrible Mistake of Choosing '\u003cb\u003eNull\u003c/b\u003e' as a License Plate. 2,681,508 views2.6M \u003cbr\u003e\nviews. • Jun 9, 2020. 92K. 2.7K. Share. Save. 92,296 / 2,757 ...", "formattedUrl": "https://www.youtube.com/watch?v=_c1am8NSx_s", "htmlFormattedUrl": "https://www.youtube.com/watch?v=_c1am8NSx_s", "pagemap": { "cse_thumbnail": [ { "src": "https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcQ9bAI1kARF7wrS9sbBJVBc5GxrK8DXRtIu_dpbza3fhWp8fnSYsb-8JEeS", "width": "300", "height": "168" } ], "imageobject": [ { "width": "1280", "url": "https://i.ytimg.com/vi/_c1am8NSx_s/maxresdefault.jpg", "height": "720" } ], "person": [ { "name": "Half as Interesting", "url": "http://www.youtube.com/channel/UCuCkxoKLYO_EQ2GeFtbM_bw" } ], "metatags": [ { "og:image": "https://i.ytimg.com/vi/_c1am8NSx_s/maxresdefault.jpg", "twitter:app:url:iphone": "vnd.youtube://www.youtube.com/watch?v=_c1am8NSx_s&feature=applinks", "twitter:app:id:googleplay": "com.google.android.youtube", "theme-color": "rgba(255,255,255,0.98)", "og:image:width": "1280", "twitter:card": "player", "og:site_name": "YouTube", "twitter:url": "https://www.youtube.com/watch?v=_c1am8NSx_s", "twitter:app:url:ipad": "vnd.youtube://www.youtube.com/watch?v=_c1am8NSx_s&feature=applinks", "al:android:package": "com.google.android.youtube", "twitter:app:name:googleplay": "YouTube", "title": "The Terrible Mistake of Choosing 'Null' as a License Plate", "al:ios:url": "vnd.youtube://www.youtube.com/watch?v=_c1am8NSx_s&feature=applinks", "twitter:app:id:iphone": "544007664", "og:description": "Sign up for a CuriosityStream subscription and also get a free Nebula subscription (the new streaming platform built by creators) here: http://CuriosityStrea...", "al:ios:app_store_id": "544007664", "twitter:image": "https://i.ytimg.com/vi/_c1am8NSx_s/maxresdefault.jpg", "twitter:player": "https://www.youtube.com/embed/_c1am8NSx_s", "twitter:player:height": "720", "twitter:site": "@youtube", "og:video:type": "text/html", "og:video:height": "720", "og:video:url": "https://www.youtube.com/embed/_c1am8NSx_s", "og:type": "video.other", "twitter:title": "The Terrible Mistake of Choosing 'Null' as a License Plate", "al:ios:app_name": "YouTube", "og:title": "The Terrible Mistake of Choosing 'Null' as a License Plate", "og:image:height": "720", "twitter:app:id:ipad": "544007664", "al:web:url": "http://www.youtube.com/watch?v=_c1am8NSx_s&feature=applinks", "og:video:secure_url": "https://www.youtube.com/embed/_c1am8NSx_s", "og:video:tag": "null", "og:video:width": "1280", "al:android:url": "vnd.youtube://www.youtube.com/watch?v=_c1am8NSx_s&feature=applinks", "fb:app_id": "87741124305", "twitter:app:url:googleplay": "https://www.youtube.com/watch?v=_c1am8NSx_s", "twitter:app:name:ipad": "YouTube", "twitter:description": "Sign up for a CuriosityStream subscription and also get a free Nebula subscription (the new streaming platform built by creators) here: http://CuriosityStrea...", "og:url": "https://www.youtube.com/watch?v=_c1am8NSx_s", "twitter:player:width": "1280", "al:android:app_name": "YouTube", "twitter:app:name:iphone": "YouTube" } ], "videoobject": [ { "embedurl": "https://www.youtube.com/embed/_c1am8NSx_s", "playertype": "HTML5 Flash", "isfamilyfriendly": "true", "uploaddate": "2020-06-09", "description": "Sign up for a CuriosityStream subscription and also get a free Nebula subscription (the new streaming platform built by creators) here: http://CuriosityStrea...", "videoid": "_c1am8NSx_s", "url": "https://www.youtube.com/watch?v=_c1am8NSx_s", "duration": "PT6M10S", "unlisted": "False", "name": "The Terrible Mistake of Choosing 'Null' as a License Plate", "paid": "False", "width": "1280", "regionsallowed": "AD,AE,AF,AG,AI,AL,AM,AO,AQ,AR,AS,AT,AU,AW,AX,AZ,BA,BB,BD,BE,BF,BG,BH,BI,BJ,BL,BM,BN,BO,BQ,BR,BS,BT,BV,BW,BY,BZ,CA,CC,CD,CF,CG,CH,CI,CK,CL,CM,CN,CO,CR,CU,CV,CW,CX,CY,CZ,DE,DJ,DK,DM,DO,DZ,EC,EE,EG,EH...", "genre": "Education", "interactioncount": "2681508", "channelid": "UCuCkxoKLYO_EQ2GeFtbM_bw", "datepublished": "2020-06-09", "thumbnailurl": "https://i.ytimg.com/vi/_c1am8NSx_s/maxresdefault.jpg", "height": "720" } ], "cse_image": [ { "src": "https://i.ytimg.com/vi/c1am8NSx_s/maxresdefault.jpg" } ] } }, { "kind": "customsearch#result", "title": "Exclusion of the null hypothesis - Wikipedia", "htmlTitle": "Exclusion of the \u003cb\u003enull\u003c/b\u003e hypothesis - Wikipedia", "link": "https://en.wikipedia.org/wiki/Exclusion_of_the_null_hypothesis", "displayLink": "en.wikipedia.org", "snippet": "In inferential statistics, the null hypothesis is a default hypothesis that a quantity to \nbe measured is zero (null). Typically, the quantity to be measured is the ...", "htmlSnippet": "In inferential statistics, the \u003cb\u003enull\u003c/b\u003e hypothesis is a default hypothesis that a quantity to \u003cbr\u003e\nbe measured is zero (\u003cb\u003enull\u003c/b\u003e). Typically, the quantity to be measured is the ...", "cacheId": "xXuKx_39w9IJ", "formattedUrl": "https://en.wikipedia.org/wiki/Exclusion_of_the_null_hypothesis", "htmlFormattedUrl": "https://en.wikipedia.org/wiki/Exclusion_of_the\u003cb\u003enull\u003c/b\u003e_hypothesis", "pagemap": { "metatags": [ { "referrer": "origin" } ] } }, { "kind": "customsearch#result", "title": "NULL - Manual - PHP", "htmlTitle": "NULL - Manual - PHP", "link": "https://www.php.net/manual/en/language.types.null.php", "displayLink": "www.php.net", "snippet": "NULL ¶. The special null value represents a variable with no value. null is the \nonly possible value of type null. A variable is considered to be null if: it has been\n ...", "htmlSnippet": "\u003cb\u003eNULL\u003c/b\u003e ¶. The special \u003cb\u003enull\u003c/b\u003e value represents a variable with no value. \u003cb\u003enull\u003c/b\u003e is the \u003cbr\u003e\nonly possible value of type \u003cb\u003enull\u003c/b\u003e. A variable is considered to be \u003cb\u003enull\u003c/b\u003e if: it has been\u003cbr\u003e\n ...", "cacheId": "UdiDMCZEYiMJ", "formattedUrl": "https://www.php.net/manual/en/language.types.null.php", "htmlFormattedUrl": "https://www.php.net/manual/en/language.types.\u003cb\u003enull\u003c/b\u003e.php", "pagemap": { "metatags": [ { "viewport": "width=device-width, initial-scale=1.0" } ] } }, { "kind": "customsearch#result", "title": "Null Furniture", "htmlTitle": "\u003cb\u003eNull\u003c/b\u003e Furniture", "link": "https://nullfurniture.com/", "displayLink": "nullfurniture.com", "snippet": "Null Furniture. Twitter · LinkedIn · Instagram 888-995-0260. About Us · Dealer \nLogin · Join Our Sales Team · Home; Categories. Accents · Chairside End Tables\n ...", "htmlSnippet": "\u003cb\u003eNull\u003c/b\u003e Furniture. Twitter · LinkedIn · Instagram 888-995-0260. About Us · Dealer \u003cbr\u003e\nLogin · Join Our Sales Team · Home; Categories. Accents · Chairside End Tables\u003cbr\u003e\n ...", "cacheId": "gEIhg0oiOk0J", "formattedUrl": "https://nullfurniture.com/", "htmlFormattedUrl": "https://\u003cb\u003enull\u003c/b\u003efurniture.com/", "pagemap": { "cse_thumbnail": [ { "src": "https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcQnypjkLq9t0dZjMjVDzLRMn9ApIt_tI98AqJ15oB3U5ZMWQhTll5JGno6U", "width": "302", "height": "167" } ], "metatags": [ { "viewport": "width=device-width", "author": "nickgreene.com", "og:title": "Null Furniture", "og:url": "https://nullfurniture.com/" } ], "cse_image": [ { "src": "https://nullfurniture.com/uploads/media/images/homepage-panels/1219-home-panel.jpg" } ] } }, { "kind": "customsearch#result", "title": "guregu/null: reasonable handling of nullable values - GitHub", "htmlTitle": "guregu/null: reasonable handling of nullable values - GitHub", "link": "https://github.com/guregu/null", "displayLink": "github.com", "snippet": "If you need zero and null be considered separate values, use these. Types in \nzero are treated like zero values in Go: blank string input will produce a null zero.", "htmlSnippet": "If you need zero and \u003cb\u003enull\u003c/b\u003e be considered separate values, use these. Types in \u003cbr\u003e\nzero are treated like zero values in Go: blank string input will produce a \u003cb\u003enull\u003c/b\u003e zero.", "cacheId": "T7B1tmryJz0J", "formattedUrl": "https://github.com/guregu/null", "htmlFormattedUrl": "https://github.com/guregu/\u003cb\u003enull\u003c/b\u003e", "pagemap": { "cse_thumbnail": [ { "src": "https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcTwfHyCk0QSD0eByjSLIyu38h2iRVGLp2yJ9rDIMtazrYl55xcxKuiQjyA", "width": "225", "height": "225" } ], "softwaresourcecode": [ { "license": "LICENSE", "author": "guregu", "name": "null", "text": "null import "gopkg.in/guregu/null.v4" null is a library with reasonable options for dealing with nullable SQL and JSON values There are two packages: null and its subpackage zero. Types in..." } ], "metatags": [ { "apple-itunes-app": "app-id=1477376905", "og:image": "https://avatars.githubusercontent.com/u/131059?s=400&v=4", "twitter:card": "summary", "theme-color": "#1e2327", "og:site_name": "GitHub", "octolytics-event-url": "https://collector.githubapp.com/github-external/browser_event", "hovercard-subject-tag": "repository:23432446", "html-safe-nonce": "9b9962dd7f32f36f6ed30049425e360886bb898566853dab0841613e1d7ca225", "expected-hostname": "github.com", "octolytics-app-id": "github", "og:description": "reasonable handling of nullable values. Contribute to guregu/null development by
-
Return array from constructor function in Class
Let us suppose a Class of PriorityQueue it has many methods in Class i.e. add, peak, changePriority etc. So to call the Class we have
let priorityQueue = new PriorityQueue();
To add something to the PriorityQueue Class, i can do something
priorityQueue.add(10, 1); priorityQueue.add(100, 0); priorityQueue.add(200, 0);
My question is how can we do
- Array.from(priorityQueue)
That returns us [100, 200, 10]
I have to strictly use Array.from do we have any solution for this?
-
in react i want to select only one user my code is selecting every user
im facing issue when i click add friend button every button changes to requested how can i particularly set it to one user only which i clciked i tried few things but it is not working it is selecting every other user. i used handleproductselect function but it is not working i have given them individual id still it is not working
class SearchModal extends Component { constructor(props){ super(props); this.state = { Input:"Add Friend", backgroundColor: 'white', active_id: null, } } async handleProductSelect(elementid){ const id = elementid; const { backgroundColor } = this.state; let newBackgroundColour = backgroundColor === 'white' ? 'yellow' : 'white'; this.setState({ Input : "Requested", backgroundColor: newBackgroundColour, active_id: id }) console.log(id) } render() { const {currentUser} = this.props; return ( <div> <Modal show={this.state.show} onHide={this.handleClose} > <Modal.Header closeButton> <Modal.Title> <input type="text" placeholder="Search.." value={search} onChange={this.onTextboxChangeSearch} ></input> </Modal.Title> </Modal.Header> <Modal.Body> <h3>Users</h3> <div> <ul className="collection"> {userdetails.map((element) => { if(currentUser.user.username !== element.username){ return( <div key={element._id}> <li>{element.username}{' '}<input type="button" id={element._id} onClick={this.handleProductSelect.bind(this,element._id )} value={this.state.Input} style = {{backgroundColor: ( element._id === this.state.active_id ? 'yellow' : this.state.backgroundColor)}}></input></li> </div> ); }else{ return( <div key={element._id}> <li>{element.username}</li> </div> ); } })} </ul> </div> </Modal.Body> </Modal> </div> ) } }
-
How to pass a variable inside cellRendererFramework in ag-grid?
I'm using ag-grid in my react project. Now It's working finely. But I need to add one more alteration there. Inside the cellRendererFramework, I need to pass the relevant id of the ticket. It must be the id, not the ticketId.It's in a separate field. How can I pass it inside the cellRendererFramework? Is it possible?
TicketTable.js
import React from 'react'; import IssueSnippet from './IssueSnippet/IssueSnippet'; import AgGridTable from '../DataTables/AgGridTable/AgGridTable'; import FilterBar from './FilterBar/FilterBar'; import { Archive, ArrowClockwise, Share, Pencil } from 'react-bootstrap-icons'; import moment from 'moment'; import PriorityBadge from '../PriorityBadge/PriorityBadge'; import UserIcon from '../UserIcon/UserIcon'; import TicketAction from './TicketAction/TicketAction'; import 'ag-grid-community/dist/styles/ag-theme-alpine.css'; import 'ag-grid-community/dist/styles/ag-grid.css'; import './TicketTable.scss'; const TicketTable = (props) => { const gridOptions = { defaultColDef: { sortable: true, unSortIcon: true }, columnDefs: [ { checkboxSelection: true, maxWidth: 60, sortable: false, unSortIcon: false, headerCheckboxSelection: true, headerCheckboxSelectionFilteredOnly: true }, // { // headerName: 'ID', // field: 'id', // maxWidth: 180, // cellRendererFramework: Clickable, // cellClass: `cell-id text p3` // }, { headerName: 'ID', field: 'ticketId', maxWidth: 180, cellRendererFramework: Clickable, cellClass: `cell-id text p3` }, { headerName: 'Employer', field: 'employerId', maxWidth: 200 }, { headerName: 'Issue', field: 'c', maxWidth: 500, cellRendererFramework: IssueSnippet }, { headerName: 'Priority', field: 'ticketPriority', maxWidth: 130, cellRendererFramework: PriorityRenderer }, { headerName: 'Type', field: 'ticketType', maxWidth: 120 }, { headerName: 'Date', field: 'createdTs', maxWidth: 200 }, { headerName: 'Assignee', field: 'assignee', maxWidth: 150, cellRendererFramework: AssigneeRenderer } ], rowHeight: 60 }; const refreshFunct = () => { window.location.reload(); }; let time = props.data.map((item, key) => { item.createdTs = moment(item.createdTs).format('L'); }); const { data } = props; console.log(data); return ( <div className="ticket-table-wrapper"> <div className="table-actions"> <TicketAction icon={<ArrowClockwise />} tooltip="Refresh" onClick={refreshFunct} /> <TicketAction icon={<Archive />} tooltip="Archive" /> <TicketAction icon={<Share />} tooltip="E-mail" /> <TicketAction icon={<Pencil />} tooltip="E-mail" /> </div> <FilterBar /> <AgGridTable gridOptions={gridOptions} rowHeight={80} rowData={data} pagination={true} paginationPageSize={6} rowClass="ticket-row" ></AgGridTable> </div> ); }; const PriorityRenderer = (props) => { const priority = props.data.ticketPriority; return <PriorityBadge priority={priority} />; }; const AssigneeRenderer = (props) => { const { assignee } = props.data; return <UserIcon size="40" name={assignee} className="user-avatar" />; }; const Clickable = (props) => { console.log(props.value); let k = props.value; return <a href={`http://localhost:3002/viewTicket/${k}`}>{props.value}</a>; }; export default TicketTable;
This is the part with the problem.hough I try to pass
cellRendererFramework: Clickable(id),
it's not working{ headerName: 'ID', field: 'ticketId', maxWidth: 180, cellRendererFramework: Clickable, cellClass: `cell-id text p3` },
-
How to set profile picture usig react expo
Blockquote here I used avatar tag and mediaupload but I want to know how to use onpress function with help of usestate based on true or false condition
return( <View style={{flexDirection: 'row', margin: 5,justifyContent:'space-between'}}> <Avatar style={{ width:50, height:50,}} rounded icon={{name: 'user', type: 'font-awesome'}} onPress={() =>console.log("work!")} /> <MediaUpload mediaType={showMediaUploadFor} onMediaSelected={(result, mediaType) => { const params = { roomId, roomName: displayRoomDetails.displayName, userId, result }; navigation.navigate({ routeName: `${mediaType}Upload`, params: params, key: roomId + `${mediaType}-upload`, source: 'storage' }); setShowMediaUploadFor(null); }} onCancel={() => { setShowMediaUploadFor(null); }} />} );
Blockquote
this my avathor and mediaupload how to use in onpress function
-
Use Reselect with ownProps for best practice?
I want select stream info from my redux state. It's work but I very confuse when I try select deep state from my redux state. I want select (
state.livestream.subscribeLiveStream[postID].des
,state.livestream.subscribeLiveStream[postID].views
, ...) withpostID
fromownProps
. Here is my code. My question- Is the code in selector and component good ?
- If it's not, please explain for me why.
Thank you for your help. Here is what I have
reducer
state = { livestream: { subscribeLiveStream: { 'a': { des: 'My stream a', views: 0, status: 0, }, 'b': { des: 'My stream b', views: 0, status: 0, } // 'a', 'b' is ID } }, // other }
Selector
const livestreamSelector = state => state.livestream; /* select subscribeLiveStream */ export const selectSubLiveStream = createSelector( livestreamSelector, livestream => livestream.subscribeLiveStream ); /* select subscribeLiveStream info */ const getPostID = (_, postID) => postID; export const makeSelectSubLiveStreamViews = () => createSelector( [selectSubLiveStream, getPostID], (subLiveStream, postID) => subLiveStream[postID]?.views || 0 );
Using in component:
const LiveStream = ({ postID }) => { const selectSubLiveStreamViews = useMemo(makeSelectSubLiveStreamViews, []); const views = useSelector(state => selectSubLiveStreamViews(state, postID) ); return ( <div> <p>My stream views: {views}</p> </div> ); };
-
redux saga yield all cancel other effect when one failed
I have issues with yield all in saga effect, I provide my sample code below
function* fetchData(item) { try { const data = yield call(request, url); yield put(fetchDataSuccess(data)); } catch (error) { yield put(fetchDataFailure(error)); throw error; } } function* fetchSummary(action) { try { yield all( list.map(item=> call(fetchData, item) ) ); } catch (error) { yield put( enqueueSnackbar({ message: "Has Error", options: { variant: "error" } }) ); } }
The logic of it is that I want to call multiple requests (some success, and some failed).
Expected: If it has failed request, the error will be caught after yield all but those success requests still continue and it should dispatch action "fetchDataSuccess" after individual success request (Promise.all can do this)
Actual: If it has failed request, the error will be caught after yield all, and then saga immediately cancel all other "fetchData" call.
Can anyone help me to achieve this logic. Thanks in advance.
-
More than one test fails due to import after jest is torn down - Supertest Typescript and Express API
I am running into an issue where I am running multiple tests using
supertest
andjest
. When there is only one test running then it works just fine but the second one throws the following error:ReferenceError: You are trying to `import` a file after the Jest environment has been torn down.
I tested this with two very simple tests:
describe("Default API", () => { describe("Default:", () => { it("should create a user in the DB", (done) => { request(app).get("/").expect(200, done); }); it("should create a user in the DB", (done) => { request(app).get("/").expect(200, done); }); }); });
They are the same but the second one throws the error. If I run only the first one there is no issue. This must be a setup issue Does anyone have advice. In my index.ts where I have the main express code I export app as follows:
export default app;
This is at the bottom of the index.ts file.
-
TypeError: Cannot read property 'getContext' of null
I have created a game using canvas API and now I am testing using Jest. But when running a test for a simple function it throws me this error. my script tag is at the end of the HTML and I also added this event listener to wait for the DOM document.addEventListener("DOMContentLoaded", init,false);
jest
PASS tests/sum.test.js FAIL tests/mod.test.js ● Test suite failed to run
TypeError: Cannot read property 'getContext' of null 20 | const empty = 0; 21 | const nextPieceCanvas = document.querySelector("canvas#nextPiece") as HTMLCanvasElement; > 22 | const NPctx = nextPieceCanvas.getContext("2d")! as CanvasRenderingContext2D; | ^ 23 | 24 | //Gameboard Canvas 25 | const canvas = document.querySelector("canvas#tetris") as HTMLCanvasElement; at Object.<anonymous> (src/ts/app.ts:22:31) at Object.<anonymous> (tests/mod.test.js:2:1)
Test Suites: 1 failed, 1 passed, 2 total Tests: 1 passed, 1 total Snapshots: 0 total Time: 1.424 s Ran all test suites. npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR! tetris_ts@1.0.0 test:
jest
npm ERR! Exit status 1 npm ERR! npm ERR! Failed at the tetris_ts@1.0.0 test script. npm ERR! This is probably not a problem with npm. There is likely additional logging output above.npm ERR! A complete log of this run can be found in: npm ERR! /home/alex/.npm/_logs/2021-02-26T22_46_02_771Z-debug.log
enter code here
-
nestjs unit test createTestingModule Dependency Injection
I hope you can help me out. I am using Nx with latest angular/nestjs (date: February, 26)
... "@nestjs/common": "^7.0.0", "@nestjs/config": "^0.6.3", "@nestjs/core": "^7.0.0", "@nestjs/platform-express": "^7.0.0", "@nestjs/platform-socket.io": "^7.6.7", "@nestjs/websockets": "^7.6.7", "jest": "26.2.2", "@nrwl/jest": "11.4.0", ...
I cannot get my unit test running using NestJS with Jest I want to test following service:
@Injectable() export class CoreApiService { logger = new Logger('CoreApiService'); apiEndpoint; constructor(private httpService: HttpService, configService: ConfigService) { this.apiEndpoint = configService.get('API_SERVICE_ENDPOINT'); } }
and I get following error:
TypeError: Cannot read property 'get' of undefined
so it seems that the ConfigService (and also httpService) is always undefined.
when logging httpService and ConfigService, it will always be undefined. Even when I try to instantiate new Instances like
new CoreApiService(new HttpService(), new ConfigService())
I've even tried things likenew CoreApiService({} as any, {get: (...params} => {return 'foo'})
in the test itselfit will always be the same error mentioned above.
The test file:
import { Test, TestingModule } from '@nestjs/testing'; import { CoreApiService } from './core-api.service'; import { ConfigModule, ConfigService } from '@nestjs/config'; import { HttpModule } from '@nestjs/common'; class ConfigServiceMock { get(key: string): string { switch (key) { case 'API_SERVICE_ENDPOINT': return ''; } } } describe('CoreApiService', () => { let module: TestingModule; let service: CoreApiService; beforeEach(async () => { module = await Test.createTestingModule({ imports: [HttpModule, ConfigModule], providers: [ CoreApiService, { provide: ConfigService, useClass: ConfigServiceMock }, ], }).compile(); service = module.get<CoreApiService>(CoreApiService); }); it('should be defined', () => { expect(service).toBeDefined(); }); });
I've even tried:
.overrideProvider(ConfigService).useClass(ConfigServiceMock)
Thank you in advance!
-
Hi,How to test Reactjs Project using @testing-libray/react
I am new to testing I am trying to do unit testing on a function that is present in the global context. Text and button are tested but I am not able to test the function (userDataFunc) and data is stored in userData, which are present in global context. Library that I have used (@testing-library/react)
Can any one help me out
Codesandbox link : Link
Dashboard Page
import React, { useContext, useEffect } from "react"; import { globalC } from "./context"; export default function Dashboard() { const { count, handleSubmit, incrementFunc, user, handleChange, userDataFunc, userData } = useContext(globalC); useEffect(() => { userDataFunc(); }); return ( <div style={{ height: "100vh", backgroundColor: "#ea2345" }} className="d-flex justify-content-center align-items-center" > <div> <h4 style={{ color: "#fff" }}>Dashboard Page</h4> <form onSubmit={handleSubmit}> <input onChange={handleChange} className="form-control mb-1" name="username" type="text" /> <button type="submit">submit</button> </form> <h4 style={{ color: "#fff", marginTop: "15px" }}>Increment</h4> <button onClick={incrementFunc}>clickme</button> <h5 style={{ color: "#fff" }}>{count}</h5> <h5 style={{ color: "#fff" }}>{user}</h5> </div> <div style={{ overflowY: "auto", margin: "4px", border: "2px solid", padding: "12px", height: "80vh" }} > {userData !== undefined && userData.map((i) => { return ( <h5 key={i.id} style={{ color: "#fff" }}> {i.name} </h5> ); })} </div> </div> ); }
Context Page
import React, { Component, createContext } from "react"; import axios from "axios"; export const globalC = createContext(); export class Gprov extends Component { state = { authLogin: null, authLoginerror: null, count: 1, user: null }; componentDidMount() {} userDataFunc = async () => { await axios(`https://jsonplaceholder.typicode.com/users`) .then((res) => { if (res.status === 200) { this.setState({ userData: res.data }); // localStorage.setItem("loginDetail", JSON.stringify(res.data)); } }) .catch((err) => this.setState({ userDataerror: err }) ); }; incrementFunc = () => { const { count } = this.state; this.setState({ count: count + 1 }); }; handleChange = (e) => { this.setState({ [e.target.name]: e.target.value }); }; handleSubmit = (e) => { e.preventDefault(); this.setState({ user: this.state.username }); }; render() { // console.log(localStorage.getItem("loginDetail")); return ( <globalC.Provider value={{ ...this.state, loginData: this.loginData, incrementFunc: this.incrementFunc, handleChange: this.handleChange, handleSubmit: this.handleSubmit, userDataFunc: this.userDataFunc }} > {this.props.children} </globalC.Provider> ); } }
Dashboard.test file
import React from "react"; import { Gprov } from "./context"; import { render, screen } from "@testing-library/react"; import Dashboard from "./Dashboard"; function initialFunc() { render( <Gprov> <Dashboard /> </Gprov> ); } describe("dashboard Component", () => { test("dashboard Component render without crash", () => { initialFunc(); }); test("dashboard title render without crash", () => { initialFunc(); expect(screen.getByText("Dashboard Page")).toBeTruthy(); }); });
-
Return array from jest mock with React Hook
I'm trying to create a mock for a custom hook that makes use of useEffect and use/createContext and ultimately just returns something that looks like this:
[{ users: 0, hoursTested: 0, testDrives: 0 }, null];
My code is as follow:
import React from "react"; import { render, screen } from "@testing-library/react"; import BetaResults from "./BetaResults"; var mockResults = [{ users: 0, hoursTested: 0, testDrives: 0 }, null]; jest.mock("services/EAPStats/useEAPStats", () => { console.log("In Mock"); return jest.fn(() => { console.log("In jest.fn"); console.log("mock results", mockResults); return mockResults; }); }); test("renders BetaResults", async () => { mockResults = [{ users: 10, hoursTested: 10, testDrives: 10 }, undefined]; render(<BetaResults />); expect(screen.getAllByTestId("BetaResultsHeaderText").length).toEqual(1); });
When I execute the test I receive this error:
Error: Uncaught [TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator))]
Execution never reaches the function defined with jest.fn. What have I overlooked?
-
Jest setSystemTime not working with global scope
I am trying to tests a simple reducer which has a date property set to today.
const today = new Date(); export const initialState = { today }; console.log(new Date().toDateString()); // <--- real date export default function globalReducer(state = initialState, action) { console.log(new Date().toDateString()); // <--- mocked date switch (action.type) { default: return state; } }
with my basic test
import globalReducer from "./reducer"; describe("Global reducer", () => { beforeAll(() => { jest.useFakeTimers("modern"); jest.setSystemTime(new Date("2021-02-18")); }); afterAll(() => { jest.useRealTimers(); }); it("should return the mocked date", () => { expect(globalReducer(undefined, {}).today).toEqual(new Date('2021-02-18')); }); });
What I noticed is that the mock only works inside the reducer code, but today in its global scope always returns the real date instead of the mocked one.
If I call the
setSystemTime
in the test setup file, thentoday
is correctly mocked.Am I missing something here? What would be the way of mocking a date in global scope only for a specific test?
A test repo is here if you want to check it out https://github.com/dariospadoni/jestFakeTimersMock