How to trigger events on a row in ag-grid? - ag-grid

I am trying to test ag-grid functionality and not able to trigger events.
it('should open Component on double click', () => {
component.gridOptions.api.setRowData(ordersStub);
fixture.detectChanges();
const node = component.gridOptions.api.getRowNode(ordersStub[0].id);
const nodeData = node.data;
const element = (fixture.debugElement.nativeElement as HTMLElement).querySelector(`[row-id="${nodeData.id}"]`);
const onRowDoubleClickedSpy = spyOn(component, 'onRowDoubleClicked');
element.dispatchEvent(new MouseEvent('dblclick', { bubbles: true, view: window, cancelable: true }));
expect(onRowDoubleClickedSpy).toHaveBeenCalled();
});
What am I doing wrong?

The event you are dispatching looks fine. So I think you need a delay between when the event is dispatched, and when you expect the component function to be called:
it('should open Component on double click', (done) => {
...
element.dispatchEvent(new MouseEvent('dblclick', { bubbles: true, view: window, cancelable: true }));
setTimeout(() => {
expect(onRowDoubleClickedSpy).toHaveBeenCalled();
done();
});
});
You could also use async tests:
it('should open Component on double click', async(async() => {
...
element.dispatchEvent(new MouseEvent('dblclick', { bubbles: true, view: window, cancelable: true }));
await fixture.whenStable();
expect(onRowDoubleClickedSpy).toHaveBeenCalled();
}));

Related

Redux Toolkit state doesn't update even after adding extraReducers

I have a very limited understanding of the redux toolkit compared to its previous version. I am struggling to understand why isn't my state getting updated on the trigger of getUsers.
I have added the extraReducers as well.
import { createAsyncThunk, createSlice } from '#reduxjs/toolkit';
import { fetchSample } from './filterAPI';
export const getUsers = createAsyncThunk(
'primaryFilters/getUsers',
async (dispatch, getState) => {
console.log(getState, dispatch);
const response = await fetchSample();
return response;
}
);
const primaryFiltersSlice = createSlice({
name: 'primaryFilters',
initialState: {
dateFilter: {
dates: {
key: 'selection',
startDate: new Date(),
endDate: new Date(),
},
dummyData: null,
},
status: null,
},
extraReducers: (builder) => {
builder
.addCase(getUsers.pending, (state) => {
state.status = 'loading';
})
.addCase(getUsers.fulfilled, (state, action) => {
state.status = 'idle';
state.dummyData = action.payload;
})
.addCase(getUsers.rejected, (state, action) => {
state.status = 'failed';
});
},
});
export default primaryFiltersSlice.reducer;
Here's fetchSample function:
export const fetchSample = async () => {
const response = await fetch('https://jsonplaceholder.typicode.com/todos/1');
return response.json();
};
Additionally, I want to point out that my status is triggering from pending to idle and so on but my actual state isn't updating.
Here's the screenshot for the same:
I would also like to know how can we log the messages within those extraReducers.
For one, looking at your data structure, you probably want to update state.dateFilter.dummyData, not state.dummyData - at least assuming you want to match your initialState structure.
Also, createAsyncThunk does not take a callback dispatch, getState:
correct would be
export const getUsers = createAsyncThunk(
'primaryFilters/getUsers',
async (arg, {dispatch, getState}) => {
(but that does not make a difference here since you are using neither)
As for logging... just console.log? Or do you mean you are getting a Proxz object? In that case console.log(current(state))
For some reason, I am able to dispatch actions by keeping the status update at the bottom instead of the top. I would love to have a better explanation for the same, here's what exactly fixed my code:
import { createAsyncThunk, createSlice } from '#reduxjs/toolkit';
import { fetchSample } from './filterAPI';
export const getUsers = createAsyncThunk(
'primaryFilters/getUsers',
async (dispatch, getState) => {
console.log(getState, dispatch);
const response = await fetchSample();
return response;
}
);
// export const updateDates = () => {
// }
const primaryFiltersSlice = createSlice({
name: 'primaryFilters',
initialState: {
dateFilter: {
dates: {
key: 'selection',
startDate: new Date(),
endDate: new Date(),
},
dummyData: null,
},
status: null,
},
reducer: {
updateDate: (state, action) => {
console.log('Actions = ', action);
},
},
extraReducers: (builder) => {
builder
.addCase(getUsers.pending, (state) => {
state.status = 'loading';
})
.addCase(getUsers.fulfilled, (state, action) => {
state.dummyData = action.payload;
state.status = 'idle';
})
.addCase(getUsers.rejected, (state, action) => {
state.status = 'failed';
});
},
});
export default primaryFiltersSlice.reducer;

Ionic 4 action sheet: Accessing returned value in other component

I have a 1 service and 1 component and I'd like to keep the action sheet functionality in the service and then pass the result to the component. For some reason I cannot access the returned value. Here are the docs to the actionsheetcontroller.
// photo.service
async selectImageSheet() {
const actionSheet = await this.actionSheetController.create({
header: "Select Image source",
buttons: [
{
text: 'Load from Library',
handler: () => {
this.imageSource = this.camera.PictureSourceType.PHOTOLIBRARY
return this.imageSource
}
},
{
text: 'Use Camera',
handler: () => {
this.imageSource = this.camera.PictureSourceType.CAMERA
return this.imageSource
}
},
{
text: 'Cancel',
role: 'cancel',
}
]
})
}
And in my component I do the following:
//component
selectImage() {
this.photo.selectImageSheet().then(() => console.log(this.photo.imageSource))
console.log(this.photo.imageSource)
}
Neither of the console.logs appear in the component. I've tried returning a promise with no luck.
you need to use onDismiss - check the doc - https://ionicframework.com/docs/api/action-sheet
const actionSheet = await actionSheetController.create({
header: "Sheet Header",
buttons: [ ]
});
await actionSheet.present();
let result = await actionSheet.onDidDismiss();
console.log(results)

hapi lab AssertionError [ERR_ASSERTION]: Plugin crumb already registered

i'm not sure why i am receiving this. I am trying to create a simple test while using #hapi/crumb. i am only registering it once in my server.js.
const Path = require("path");
const hapi = require("hapi");
const inert = require("inert");
const vision = require("vision");
const Ejs = require("ejs");
const Crumb = require("#hapi/crumb");
const Blankie = require("blankie");
const Scooter = require("#hapi/scooter");
const routes = require("./routes");
// Configure the server
const server = hapi.Server({
host: "0.0.0.0",
port: process.env.PORT || 3000,
routes: {
files: {
relativeTo: Path.join(__dirname, "..", "public")
},
state: {
parse: true,
failAction: "ignore"
},
security: {
xframe: true,
noOpen: false
},
cors: {
origin: ["banglarelief.org"],
headers: ["Authorization"], // an array of strings - 'Access-Control-Allow-Headers'
exposedHeaders: ["Accept"], // an array of exposed headers - 'Access-Control-Expose-Headers',
additionalExposedHeaders: ["Accept"], // an array of additional exposed headers
maxAge: 60,
credentials: true // boolean - 'Access-Control-Allow-Credentials'
}
}
});
const plugins = async () => {
const pluginsToRegister = [
inert,
vision,
require("hapi-mobile-views"),
{ plugin: Crumb, options: { cookieOptions: { isSecure: false } } },
Scooter,
{
plugin: Blankie,
options: {} // specify options here
}
];
await server.register(pluginsToRegister);
};
const init = async () => {
await plugins();
server.state("player", {
ttl: null,
clearInvalid: true,
isSecure: false
});
server.views({
engines: { ejs: Ejs },
path: `${__dirname}/views`,
layout: "layout"
});
await server.route(routes);
return server;
};
const start = async () => {
try {
await init();
await server.start();
} catch (err) {
console.log(err);
process.exit(1);
}
};
module.exports = { init, start };
My test file is very basic and i have tried to move around where the start should be called but it keep throwing same error.
'use strict';
const Lab = require('#hapi/lab');
const { expect } = require('#hapi/code');
const { afterEach, beforeEach, describe, it } = exports.lab = Lab.script();
const { init, start } = require('../src/server');
let server = start();
describe('GET /', () => {
//let server;
//server = start();
beforeEach(async () => {
//server = start();
});
afterEach(async () => {
//await server.stop();
});
it('responds with 200', async () => {
const res = await server.inject({
method: 'get',
url: '/'
});
expect(res.statusCode).to.equal(200);
});
});
I have been following https://hapijs.com/tutorials/testing?lang=en_US
The solution seems to work if you break up your plugins function into two parts. One part will init 3rd party plugins like #Hapi/*. The other function will init your 1st party plugins that you wrote. You will only init the 3rd party plugins in your start function.
It's critical that you include { once: true } because that will prevent your error. It will only initialize the plugin once, which will prevent your error. You cannot always specify { once: true } on 3rd party plugins. Thus, we have to handle that a different way. Since we moved all the 3rd party plugins to their own function, which is invoked on start, that should prevent 3rd party plugins from causing an issue of being reinitialized.
const hapiPlugins = async () => {
const pluginsToRegister = [
inert,
vision,
require("hapi-mobile-views"),
{ plugin: Crumb, options: { cookieOptions: { isSecure: false } } },
Scooter,
{
plugin: Blankie,
options: {} // specify options here
}
];
};
const myPlugins = async () => {
await server.register([
allOfMyPlugins...
],
{
once: true //critical so that you don't re-init your plugins
});
};
const init = async () => {
server.state("player", {
ttl: null,
clearInvalid: true,
isSecure: false
});
server.views({
engines: { ejs: Ejs },
path: `${__dirname}/views`,
layout: "layout"
});
await server.route(routes);
return server;
};
const start = async () => {
try {
await hapiPlugins();
await init();
await server.start();
} catch (err) {
console.log(err);
process.exit(1);
}
};
Then, you should be able to call init in your test's before function. Use that server object to inject.

How to use the Loading Controller with duration

I have my LoadingController :
const loader = this.loadCtrl.create({
content: 'Loading ...',
duration: 5000
});
loader.present();
Just after i have an api call
myApi.Function().then(res => {
console.log(res);
}
I want to dismiss my LoadingController when my api call is end OR if my duration is end.
How can i call the event loader.dismiss() after the duration ?
thanks,
You can use Promise.race() for that:
The Promise.race() method returns a promise that resolves or rejects
as soon as one of the promises in an iterable resolves or rejects,
with the value or reason from that promise.
const delayPromise = new Promise(resolve => window.setTimeout(() => resolve(), 3000));
const apiPromise = myApi.Function();
const loader = this.loadCtrl.create({
content: 'Loading ...',
});
loader.present();
Promise.race([delayPromise, apiPromise]).then(res => {
loader.dismiss();
if(res) {
// apiPromise finished first
} else {
// delayPromise finished first
}
});

fetching data from api and shows on Render Method

I am fetched data from api but the problem is
when i am show data in render method then it showing "Undefine"
Please Help me to fix it
This is my code:-
var ProductData=''
export default class ApiProduct extends Component {
FetchProduct=()=>{
fetch('https://drawtopic.in/projects/wordpress/wp- json/wc/v2/products?consumer_key=ck_044491712632ef889ec13c75daff5879a8291674&consumer_secret=cs_a8e16c732e1812017e15d278e1dce2765a88c49b',{
method:'GET',
})
.then((response) => response.json())
.then((res) =>{
ProductData= res;
})
}
render() {
{this.FetchProduct()}
{console.warn(ProductData)}
return (
<View/>
)}
i Want to Show All data in render method
Here is a quick Expo example that should show you how to render a simple list. It is not a good idea to call fetch inside the render method, as every re-render will call the fetch.
Here is an expo snack https://snack.expo.io/S1-LKIyQE
import React from 'react';
import { Text, View, StyleSheet, FlatList, SafeAreaView } from 'react-native';
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
productData: []
}
}
async componentDidMount () {
await this.getData();
}
async getData() {
try {
let url ='https://drawtopic.in/projects/wordpress/wp-json/wc/v2/products?consumer_key=ck_044491712632ef889ec13c75daff5879a8291674&consumer_secret=cs_a8e16c732e1812017e15d278e1dce2765a88c49b'
let response = await fetch(url, { method:'GET' });
let responseJson = await response.json();
this.setState({productData: responseJson});
} catch (err) {
console.warn(err);
}
}
renderItem = ({item}) => {
return (
<View style={styles.mainItem}>
<Text>{item.name}</Text>
</View>
);
}
keyExtractor = (item, index) => {
return index.toString();
}
render() {
return (
<SafeAreaView style={styles.container}>
<FlatList
extraData={this.state}
data={this.state.productData}
keyExtractor={this.keyExtractor}
renderItem={this.renderItem}
/>
</SafeAreaView>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'white'
},
mainItem: {
width:200,
height: 80,
justifyContent: 'center',
alignItems: 'center',
margin: 10,
backgroundColor: 'yellow',
borderColor: 'black',
borderWidth: 1
},
});
Here I have used async/await as it can make for much cleaner and clearer code. This is a great article on the differences between promises and async/await https://medium.com/#bluepnume/learn-about-promises-before-you-start-using-async-await-eb148164a9c8.
I have also given you a quick example on how to use a FlatList to display your data. You should check the docs on how to use it properly https://facebook.github.io/react-native/docs/flatlist
If you want to edit how each item is displayed on the screen then you need to update the renderItem method.
Try this way, if you have a question of how it works makes me to know.
let self;
export default class ApiProduct extends Component {
constructor(){
super();
self = this;
this.state = {
productData: null;
};
}
FetchProduct=()=>{
fetch('https://drawtopic.in/projects/wordpress/wp- json/wc/v2/products?consumer_key=ck_044491712632ef889ec13c75daff5879a8291674&consumer_secret=cs_a8e16c732e1812017e15d278e1dce2765a88c49b',{
method:'GET',
})
.then((response) => response.json())
.then((res) =>{
self.setState({ productData: res});
});
}
render() {
this.FetchProduct();
console.warn(self.state.productData);
return (
<View/>
);
}
I'll try to make order in your code.
Fetching data in the render method is not a good idea, it's better to use lifecycle methods, like componentDidMount. In order to handle your request result, set a state field and in your render read data from that field. So:
export default class ApiProduct extends Component {
constructor(){
super();
this.state = {
productData: undefined;
};
}
async componentDidMount(){
await this.fetchProduct();
}
fetchProduct = () => {
fetch('https://drawtopic.in/projects/wordpress/wp- json/wc/v2/products?consumer_key=ck_044491712632ef889ec13c75daff5879a8291674&consumer_secret=cs_a8e16c732e1812017e15d278e1dce2765a88c49b',{
method:'GET',
})
.then((response) => response.json())
.then((res) =>{
this.setState({
productData: res
})
})
}
render() {
const {productData} = this.state;
console.log(productData);
return (
<View/> // add here your code to render data properly
)
}}