This what my console shows:
UnhandledPromiseRejectionWarning: ReferenceError: client is not defined
at Object.execute (/home/runner/Bot/commands/rr1.js:99:5)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
(node:2432) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag --unhandled-rejections=strict (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:2432) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
const Discord = require("discord.js")
const { MessageMenuOption, MessageMenu } = require("discord-buttons")
const { prefix } = require('../config.json')
module.exports = {
name: 'rr1',
description: 'send embedded level message',
async execute(message, args) {
const option1 = new MessageMenuOption()
.setLabel("Black Charcoal")
.setValue("Option 1")
.setDefault()
.setEmoji("🌑")
const option2 = new MessageMenuOption()
.setLabel("Love Magenta")
.setValue("Option 2")
.setDefault()
.setEmoji("❤️")
const selection = new MessageMenu()
.setID("Selection")
.setMaxValues(1)
.setMinValues(0)
.setPlaceholder("Select Role")
.addOption(option1)
.addOption(option2)
const embed = new Discord.MessageEmbed()
.setColor("0x00a6ff")
.setTitle("Colour Role")
.setDescription(`<#&x>\n<#&x>`)
const role1 = message.guild.roles.cache.find(r => r.id === "x")
const role2 = message.guild.roles.cache.find(r => r.id === "x")
async function menuselection(menu) {
switch(menu.values[0]) {
case "Option 1":
if(message.member.roles.cache.has("x") || message.member.roles.cache.has("x") || message.member.roles.cache.has("x")){
await message.member.roles.add(role1)
await message.member.roles.remove([role2])
await menu.reply.send("Claimed Black Charcoal!", true)}
break;
case "Option 2":
if(message.member.roles.cache.has("x") || message.member.roles.cache.has("782356910782677003") || message.member.roles.cache.has("780476718820884581")){
await message.member.roles.add(role2)
await message.member.roles.remove([role1])
await menu.reply.send("Claimed Love Magenta!", true)}
break;
}
}
let menumsg = await message.channel.send(embed, selection)
client.on("clickMenu", (menu) => {
if(menu.message.id == menumsg.id) {
if(menu.clicker.user.id == message.author.id) menuselection(menu)
else menu.reply.send("You are not allowed to pick!", true)
}
})
}
}
Main.js
client.on('message', async (message, guild) => {
if (!message.content.startsWith(prefix) || message.author.bot) return;
const args = message.content.slice(prefix.length).split(/ +/);
const command = args.shift().toLowerCase();
switch (message.content) {
case (prefix + "rr1"):
client.commands.get("rr1").execute(message, args);
break;
}
});
On this line
client.commands.get("rr1").execute(message, args);
You're only giving the message variable and the args array, but not the client so you have two choices.
Either do include client on your execute function
client.commands.get("rr1").execute(message, args, client);
Or don't include client and just replace every single client on your command files with message.client
message.client.on("clickMenu", (menu) => {
If I was you I'll go with the first one but it's up to you
Related
const accounts = await web3.eth.getAccounts();
App = {
load: async () => {
await App.loadWeb3(
await App.loadAccount()
)
},
loadWeb3: async () => {
if (typeof web3 !== 'undefined') {
App.web3Provider = web3.currentProvider
web3 = new Web3(web3.currentProvider)
} else {
window.alert("Please connect to Metamask.")
}
// Modern dapp browsers...
if (window.ethereum) {
window.web3 = new Web3(ethereum)
try {
// Request account access if needed
await ethereum.enable()
// Acccounts now exposed
web3.eth.sendTransaction({/* ... */})
} catch (error) {
// User denied account access...
}
}
// Legacy dapp browsers...
else if (window.web3) {
App.web3Provider = web3.currentProvider
window.web3 = new Web3(web3.currentProvider)
// Acccounts always exposed
web3.eth.sendTransaction({/* ... */})
}
// Non-dapp browsers...
else {
console.log('Non-Ethereum browser detected. You should consider trying MetaMask!')
}
},
loadAccount: async () => {
App.account = web3.eth.accounts[0]
console.log(App.account)
}
}
$(() => {
$(window).load(() => {
App.load()
})
})
The error is in LINE 1 where I get the accounts from Ganache but await is valid only for async.
What changes should I make in this code to remove the error? Please help me.
If I remove this line the error says that it cannot access accounts and after this await does not work.
Is there any way to make this piece of code in the form of an ASYNC function?
await calls can only be made in functions marked as async. As you have used await in line 1 it is not wrapped in an async function. You can wrap your code in a async function and then call that function. e.g something like:
const main = async () => { // <- the async wrapper function
const accounts = await web3.eth.getAccounts();
// .... rest of your code
$(() => {
$(window).load(() => {
App.load()
})
})
}
main()
Or if you want to be more advanced and not save the function at all
(async ()=>{
const accounts = await web3.eth.getAccounts();
// .... rest of your code
})() // <- call the function right after declaring it
i get error Your callback function returned a promise which never resolved and my code and i am cypress 3.4.1 version
```cy.xpath(LOGO).then(async $ele => {
for (const i in $ele) {
if ($ele.eq(i).text() === 'USA') {
$ele.eq(i).click();
cy.wait(5000);
}
const count = await cy.get(COUNT).invoke('text').promisify();
if(count>0) break;
}`enter code here`
});```
I have a function like this (the code is simplified to make this code more readable)
import Adapter from "adapter-package";
const adapter = new Adapter();
async powerOn(): Promise<MyClass> {
const myClass = new MyClass();
await adapter.powerOn();
return myClass;
}
as you can see I am using await on the call of adapter.powerOn(). Now I am writing unit tests for this using Jest.
it("can power on the adapter", async () => {
const spy = jest.spyOn(Adapter.prototype, "powerOn");
const myClass = await MyClass.powerOn();
expect(myClass).toBeInstanceOf(MyClass);
expect(spy).toHaveBeenAwaitedFor();
^^^^^^^^^^^^^^^^^^^^
spy.mockRestore();
}, 10000);
The test that I have underlined does not exist, but it is what I would like to test. Can I know if a method I have called has been waited for?
edit:
Will Jenkins pointed out that it is not clear what I am asking. Basically I want to make sure that the Promise returned by adapter.powerOn() has been resolved by the time my function has been resolved. Because I already had an issue where I accidentially had removed the await before adapter.powerOn().
async powerOn(): Promise {
const myClass = new MyClass();
adapter.powerOn();
return myClass;
}
So when I called my function with
await powerOn();
that function was resolved, but it did not await the call to adapter.powerOn() and I had to spend some time debugging. So I would like to make sure that adapter.powerOn() is resolved by the time await powerOn() completes.
How about something like this?
it("can power on the adapter", async () => {
let hasResolved = false;
const spy = jest.spyOn(Adapter.prototype, "powerOn");
const myClass = await MyClass.powerOn();
expect(myClass).toBeInstanceOf(MyClass);
let hasResolved = false;
//if it has been awaited then this should complete
spy.returnValues[0].then(()=>{
hasResolved=true;
})
expect(hasResolved).to.be.true;
spy.mockRestore();
}, 10000)
You could use setInmediate to wait for all pending promises:
const flushPromises = () => new Promise(setImmediate);
it("can power on the adapter", async () => {
const spy = jest.spyOn(Adapter.prototype, "powerOn");
await expect(MyClass.powerOn()).resolves.toBeInstanceOf(MyClass);
await expect(flushPromises()).resolves.toBeTruthy();
}, 10000);
This test first checks if powerOn resolves and returns an instance of MyClass and then checks if every pending promise has been resolved or rejected.
This is the solution I found:
import { inspect } from "util";
it("waits for the adapter to have been powered on", async () => {
const spy = jest
.spyOn(Adapter.prototype, "powerOn")
.mockImplementation(() => new Promise<void>(res => setTimeout(res, 0)));
await Sblendid.powerOn();
const spyPromise = spy.mock.results[0].value;
expect(inspect(spyPromise)).toBe("Promise { undefined }");
}, 10000);
the line
spy.mock.results[0].value
will get me the promise returned by my mock. Using util.inspect on a promise
expect(inspect(spyPromise)).toBe("Promise { undefined }");
will give me "Promise { undefined }" on a fulfilled promise (that is returning undefined) and would return "Promise { <pending> }" if it weren't fulfilled, that is how I test it has been resolved (fulfilled) when await Sblendid.powerOn(); completed.
I have a test that awaits an async function, then awaits a timeout, then awaits another async function.
it('runs a snipe successfully', async () => {
const exitCode = await john.chat.sendMoneyInChat(channel.topicName, channel.name, "0.01", botUsername);
console.log('timeout?')
await timeout(3000);
console.log('timeout!');
console.log('running bal check')
let values;
const nbl = await croupier.checkWalletBalance(process.env.CROUPIER_RINGO_USERNAME);
expect(nbl).toEqual(123);
})
Based on my console.log output, the afterAll teardown process begins right after the timeout? log statement. In other words, I don't see "timeout!" in the console log – I see the console.log statements within the afterAll teardown.
What gives?
EDIT:
Thanks to #Metalmi's help, I've fixed one bug. Now my code is:
it('runs a snipe successfully', async () => {
jest.useFakeTimers()
const exitCode = await john.chat.sendMoneyInChat(channel.topicName, channel.name, "0.01", botUsername);
console.log('timeout?')
jest.advanceTimersByTime(20000)
console.log('timeout.');
console.log('running bal check')
let values;
const nbl = await croupier.checkWalletBalance(process.env.CROUPIER_RINGO_USERNAME);
expect(nbl).toEqual(123);
});
Here's the checkWalletBalance function:
public checkWalletBalance(username: string): Promise<any> {
let balance: number = 0;
const self = this;
return new Promise(async (resolve) => {
try {
const acct = await self.bot1.wallet.lookup(username);
console.log("acct", acct);
const balances = await self.bot2.wallet.balances(acct.accountId);
console.log("balances", balances);
balances.forEach((acctDetail) => {
console.log(acctDetail.balance[0].amount);
balance += parseFloat(acctDetail.balance[0].amount);
});
resolve(balance);
} catch (e) {
console.log(e);
throw e;
}
});
}
I am guessing there is some problem of having async functions inside the Promise?
The Jest teardown starts before console.log("acct", acct) happens within checkWalletBalance, so something's still wrong.
To use/test standard timer functions, you need to instruct jest to use fake timers: jest.useFakeTimers(). Then you need to manually advance time: jest.advanceTimersByTime(msToRun)
EDIT:
Issue is that you declared Promise as async, and not the checkWalletBalance() itself. Changing that should fix it.
Also, to be sure about assertion being checked, you can call expect.assertions(1) at the beginning of test, so jest knows that test must have at least one assertion and won't finish before it's checked.
I have an epic that catch each dispatch of getting status (just item from state, like state.process:{ status: fail, success, inWork}, not an request status like 200, 500 etc).
When status == success (by getting status from state) i need to dispatch another action like SET_STATUS_SUCCESS
const getStatus = (action, state) =>
action.pipe(
ofType(GET_STATUS),
withLatestFrom(state),
mergeMap(([action, state]) => {
const { status } = state.api.process; //here is what i need, there is no problem with status.
if (status === "success") {
return mapTo(SET_STATUS_SUCCESS) //got nothing and error.
}
})
);
Now i receive error:
Uncaught TypeError: You provided 'function (source) { return
source.lift(new MapToOperator(value)); }' where a stream was expected.
You can provide an Observable, Promise, Array, or Iterable.
at subscribeTo (subscribeTo.js:41)
What should i do? I tried just return setStatusSuccess action but it doesn't work too.
You need to return an observable from the function you pass to mergeMap. Try this:
const getStatus = (action, state) =>
action.pipe(
ofType(GET_STATUS),
withLatestFrom(state),
mergeMap(([action, state]) => {
const { status } = state.api.process;
if (status === 'success') {
return of({ type: SET_STATUS_SUCCESS });
} else {
return EMPTY;
}
}),
);
of and EMPTY are imported from rxjs.