object is probably 'undefined' - Mocha - protractor

I am using Protractor. The below solution works, but i get this warning:
this.currentTest.state
- error TS2532: Object is possibly 'undefined'
(property) Mocha.Context.currentTest?: Mocha.Test | undefined
How do i fix this warning?
Test file:
const helper = new HelperClass();
afterEach(async ()=> {
const state = this.currentTest.state;
await helper.getSource(state);
});
Class File
import { browser, } from 'protractor';
export class HelperClass {
public getSource(state:any) {
if (state === 'failed') {
browser.driver.getPageSource().then(function (res) {
console.log(res);
});
}
}
}

I think the error occurs because the access to this.currentTest.state happens inside another function: the arrow function passed in to afterEach--flow analysis does not cross function boundaries. Try simply pulling that line outside of the function:
const helper = new HelperClass();
afterEach(async ()=> {
const state = this.!currentTest.state;
await helper.getSource(state);
});
Does that change anything?

Related

When I try to override a core function in converse.js I get an error

I am using converse.js 7.0.6 version. I am trying to set the subject topic button to be by default hidden, currently, it is visible by default. I have investigated I need to override this function toggleSubjectHiddenState, when I try to use _converse.api.user. I get an error TypeError: Cannot read properties of undefined (reading 'user')
This is how I tried, maybe I am doing wrong something.
export const addModifyHideTopicPlugin = () => {
window.converse.plugins.add('modify-hide-topic', {
overrides: {
ChatRoom: {
toggleSubjectHiddenState: async function () {
const _converse: any = this;
// const muc_jid = this.get('jid');
const jids = await _converse.api.user.settings.get(
'mucs_with_hidden_subject',
[],
);
return _converse.toggleSubjectHiddenState
.apply(_converse, arguments)
.then((response: any) => {
console.log(response, 'response');
return response;
});
},
},
},
});
};
This is the toggleSubjectHiddenState function I am trying to override because this function is handleing the show topic or hide topic.
async toggleSubjectHiddenState () {
const muc_jid = this.get('jid');
const jids = await api.user.settings.get('mucs_with_hidden_subject', []);
if (jids.includes(this.get('jid'))) {
api.user.settings.set('mucs_with_hidden_subject', jids.filter(jid => jid !== muc_jid));
} else {
api.user.settings.set('mucs_with_hidden_subject', [...jids, muc_jid]);
}
},

Mongoose plugin does not call next

I have created the following mongoose plugin.
module.exports = function(schema) {
const protectedFields = [];
for (const key in schema.obj) {
if(schema.obj[key].protected) {
protectedFields.push(key);
}
}
schema.pre('save', function(next) {
for (const field of protectedFields) {
this[field] = undefined;
}
next();
});
}
However, when I use it on my model, it does not call the next(). Or at least, once the plugin is applied it does not execute the line after the interaction with the database.
For example if I have following code,
const user = await User.create(req.body);
res.redirect('/backend/users'); // <----- This line is not executed
It does not execute the second line in the above code snippet.
Can anyone please point out to me what I am doing wrong?

Flow(InferError): Cannot call await with 'axios.get(...)' bound to 'p'

I'm getting some Flow errors using axios.
Cannot call await with 'axios.get(...)' bound to 'p' because:
Either property 'error_message' is missing in 'AxiosXHR'.
Or property 'data' is missing in 'Promise'
Here is my code, with an attempted type annotation. (Same error without the AxiosPromise<Object> annotation.) The error is on axios.get(url).
async handleAddressChange(): AxiosPromise<Object> {
const url = `https://maps.googleapis.com/maps/api/place/autocomplete/json?key=${GoogleMapsApiKey}&input=${this.state.address}`;
try {
const { data, error_message } = await axios.get(url);
if (error_message) throw Error(error_message);
this.setState({
addressPredictions: data.predictions,
showPredictions: true
});
} catch (err) {
console.warn(err);
}
}
Funny thing is that in another file axios gives no Flow problems:
export async function loginWithApi(creds: AuthParams) {
const res = await axios.get(ApiUrls.login, { params: creds });
return res.data;
}
I have import type { AxiosPromise, $AxiosXHR } from "axios"; in my file.
Anyone know how to fix this?
In case of error there will be no error_message in returned payload, but the error goes into the catch block.
Also, the handleAddressChange does not returns AxiosPromise, instead it returns implicit promise, as it defined with async
So, something like this:
async handleAddressChange(): Promise<void> {
const url = `https://maps.googleapis.com/maps/api/place/autocomplete/json?key=${GoogleMapsApiKey}&input=${this.state.address}`;
try {
const { data } = await axios.get(url);
this.setState({
addressPredictions: data.predictions,
showPredictions: true
});
} catch (err: AxiosError) {
new Error(err);
}
}
Might work for you. Note the AxiosError definition.
One extra note is that you can add returned payload into the AxiosPromise generic, i.e.:
type TExpectedLoginResponse = {
ok: boolean,
token: string
}
export async function loginWithApi(creds: AuthParams): AxiosPromise<TExpectedLoginResponse> {
const res = await axios.get(ApiUrls.login, { params: creds });
return res.data; // so now flow knows that res.data is type of TExpectedLoginResponse
}
Hope it helps.

using a function from Page Object in Protractor

I have this code in my afterEach block that works to console log the page source for a failed spec. But I want to move it to another class instead.
afterEach(function () {
const state = this.currentTest.state;
if (state === 'failed') {
browser.driver.getPageSource().then(function (res) {
console.log(res);
});
}
});
but when i try to use the following in another class, i get 'Property 'currentTest' does not exist on type 'HelperClass'. How do i declare the currentTest property?
import { browser, } from 'protractor';
export class HelperClass {
public getSource() {
const state = this.currentTest.state;
if (state === 'failed') {
browser.driver.getPageSource().then(function (res) {
console.log(res);
});
}
}
}
Try like below
test file:
const helper = new HelperClass(); // create object for class
afterEach(async ()=> {
const state = this.currentTest.state;
await helper.getSource(state);
});
Class File
import { browser, } from 'protractor';
export class HelperClass {
public getSource(state:any) {
if (state === 'failed') {
browser.driver.getPageSource().then(function (res) {
console.log(res);
});
}
}
}
Here we are sending the State from your test file.
Hope it helps you

How to use node-simple-schema reactively?

Given that there is not much examples about this, I am following the docs as best as I can, but the validation is not reactive.
I declare a schema :
import { Tracker } from 'meteor/tracker';
import SimpleSchema from 'simpl-schema';
export const modelSchema = new SimpleSchema({
foo: {
type: String,
custom() {
setTimeout(() => {
this.addValidationErrors([{ name: 'foo', type: 'notUnique' }]);
}, 100); // simulate async
return false;
}
}
}, {
tracker: Tracker
});
then I use this schema in my component :
export default class InventoryItemForm extends TrackerReact(Component) {
constructor(props) {
super(props);
this.validation = modelSchema.newContext();
this.state = {
isValid: this.validation.isValid()
};
}
...
render() {
...
const errors = this.validation._validationErrors;
return (
...
)
}
}
So, whenever I try to validate foo, the asynchronous' custom function is called, and the proper addValidationErrors function is called, but the component is never re-rendered when this.validation.isValid() is supposed to be false.
What am I missing?
There are actually two errors in your code. Firstly this.addValidationErrors cannot be used asynchronously inside custom validation, as it does not refer to the correct validation context. Secondly, TrackerReact only registers reactive data sources (such as .isValid) inside the render function, so it's not sufficient to only access _validationErrors in it. Thus to get it working you need to use a named validation context, and call isValid in the render function (or some other function called by it) like this:
in the validation
custom() {
setTimeout(() => {
modelSchema.namedContext().addValidationErrors([
{ name: 'foo', type: 'notUnique' }
]);
}, 100);
}
the component
export default class InventoryItemForm extends TrackerReact(Component) {
constructor(props) {
super(props);
this.validation = modelSchema.namedContext();
}
render() {
let errors = [];
if (!this.validation.isValid()) {
errors = this.validation._validationErrors;
}
return (
...
)
}
}
See more about asynchronous validation here.