Cypress: Getting The task 'gmail:get-messages' returned undefined. in Cypress 10 but its working on older version of cypress - plugins

I am using cypress gmail-tester. I have updated cypress to 10 or above version and gmail-tester return the below error.
cy.task('gmail:get-messages') failed with the following error:
The task 'gmail:get-messages' returned undefined. You must return a value, null, or a promise that resolves to a value or null to indicate that the task was handled.
The task handler was:
async args => {
const messages = await gmail_tester.get_messages(
path.resolve(__dirname, "credentials.json"),
path.resolve(__dirname, "token.json"),
args.options
);
console.log(messages);
return messages;
}
Fix this in your setupNodeEvents method here:
/home/krupal/Desktop/Cypress Automation/RebelBase/cypress.config.js
In cypress's older version it's working fine.
Here is my plugin/index.js file
/// <reference types="Cypress" />
const debug = require("debug");
const path = require("path");
const gmail_tester = require("gmail-tester");
const cucumber = require('cypress-cucumber-preprocessor').default;
module.exports = (on, config) => {
on('file:preprocessor', cucumber());
on("task", {
"gmail:get-messages": async args => {
const messages = await gmail_tester.get_messages(
path.resolve(__dirname, "credentials.json"),
path.resolve(__dirname, "token.json"),
args.options
);
console.log(messages);
return messages;
}
});
on("task", { "setUserId": (val) => { return (userId = val); } });
on("task", { "getUserId": () => { return userId; } });
};
And here is my cypress.config.js file
const { defineConfig } = require('cypress')
module.exports = defineConfig({
e2e: {
// We've imported your old cypress plugins here.
// You may want to clean this up later by importing these.
setupNodeEvents(on, config) {
return require('./cypress/plugins/index.js')(on, config)
},
baseUrl: 'https://app.dev.rebelbase.co',
experimentalSessionAndOrigin: true,
specPattern: 'cypress/integration/**/*.feature',
},
})
And in my test I have used like...
cy.task("gmail:get-messages", {
options: {
from: "noreply#rebelbase.co",
subject: "Join CypressTestProject01 team on RebelBase",
include_body: true,
// before: new Date(2021, 9, 24, 12, 31, 13), // Before September 24rd, 2019 12:31:13
// after: new Date(2021, 7, 23) // After August 23, 2019
}
}).then(emails => {
assert.isAtLeast(
emails.length,
1,
"Expected to find at least one email, but none were found!"
);
const body = emails[0].body.html;
console.log(body)
cy.log(body);
assert.isTrue(
body.indexOf(
"/auth/sign-up?type=project_invitation&token="
) >= 0,
"Found link!"
);
window.token = extractData(body, startStr, endStr);
cy.visit(
`auth/sign-up?type=project_invitation&token=${token}&email=${randomEmail8}`
);
})

Related

Bot doesnt want to take id from db

I'm making a command where u can setup a bot status channel. Everything so far worked fine, db even writes down id of guild and channel but when I want to use it in ready.js is says its not defined.
Little help would be handy and grateful
Code:
https://pastebin.com/GnxtxFwG - main command
https://pastebin.com/hhy90czw - schema
https://pastebin.com/jVDGu43T - error
Error file:
const { EmbedBuilder } = require('discord.js');
const { channelId } = require('../../schemas/status');
module.exports = {
name: "ready",
once: "true",
async execute(client) {
console.log(channelId)
console.log('Bot is up and ready to work!')
const uptime = new EmbedBuilder()
.setColor('ffd9c0')
.addFields(
{ name: 'Capy is back and online!', value: 'Bot was probably offline due to a bug or maintenance.'},
{ name: '\u200b', value: 'If Capy isnt working how is he supposed to be contact on of our Developers or contact <#574849327650963469> directly.'},
)
const channel = await client.channels.cache.get(channelId);
channel.send({ embeds: [uptime] });
setInterval(client.pickPresence, 10 * 1000);
},
};
Client on function
const { EmbedBuilder } = require('discord.js');
const { Statuses } = require('../../schemas/status');
const uptime = require('../../commands/tools/status')
module.exports = {
name: "ready",
once: "true",
async execute(client) {
console.log(Statuses.channelId)
console.log('Bot is up and ready to work!')
const uptimeEmbed = new EmbedBuilder()
.setColor('ffd9c0')
.addFields(
{ name: 'Capy is back and online!', value: 'Bot was probably offline due to a bug or maintenance.'},
{ name: '\u200b', value: 'If Capy isnt working how is he supposed to be contact on of our Developers or contact <#574849327650963469> directly.'},
)
const channel = await client.channels.cache.get(Statuses.channelId);
Statuses.findById({ channelId: message.guild.id }, async (err, data) => {
if (data) {
channel.send({ embeds: [uptimeEmbed] });
} else {
new Statuses ({
guildId: interaction.guild.id,
chnanelId: uptime ? uptime : "None"
}).save()
console.log("Status channel wasnt set on this server yet!")
}
});
setInterval(client.pickPresence, 10 * 1000);
},
};
Schema
const { Schema, model } = require('mongoose');
const statusSchema = new Schema({
guildId: String,
channelId: String,
});
module.exports = model("Status", statusSchema, "Statuses");
Main command
const {
SlashCommandBuilder,
ChatInputCommandInteraction,
EmbedBuilder,
} = require("discord.js");
const Statuses = require('../../schemas/status');
module.exports = {
data: new SlashCommandBuilder()
.setName("status")
.setDescription("Select the language of the bot")
.addChannelOption(uptime => {
return uptime
.setName("channel")
.setDescription("Channel you want to send the FAQ embed in")
.setRequired(true)
}),
/**
*
* #param {ChatInputCommandInteraction} interaction
* #param {Client} client
*/
async execute(interaction, client) {
const { options } = interaction;
const uptime = options.getChannel("channel");
const user = interaction.user;
const status = new EmbedBuilder()
.setColor("#bb6464")
.setDescription(`Status message was set to ${uptime}!`)
.setFooter({ text: `Request from ${interaction.user.username}`, iconURL: user.displayAvatarURL()})
.setTimestamp();
const status2 = new EmbedBuilder()
.setColor("#bb6464")
.setDescription(`Status message was changed to ${uptime}!`)
.setFooter({ text: `Request from ${interaction.user.username}`, iconURL: user.displayAvatarURL()})
.setTimestamp();
let statusProfile = await Statuses.findOne({ channelId: interaction.guild.id });
if (!statusProfile) {
statusProfile = await new Statuses({
guildId: interaction.guild.id,
channelId: uptime,
});
await statusProfile.save().catch(console.error);
interaction.reply({ embeds: [status] })
console.log(statusProfile);
} else {
await interaction.reply({ embeds: [status2] });
console.log(statusProfile);
}
}
}

NEXT, upload file along with metadata (Axios and Formidable with Node JS)

I want to upload a file to NEXT apis along with metadata:
const data = new FormData();
data.append('file', file);
data.append('body', JSON.stringify({ hello: 'world' }));
console.log('Sending');
axios
.post('/api/test-route', data, {
headers: {
'content-type': 'multipart/form-data',
'Authorization': 'json-token',
},
})
.then((response: AxiosResponse) =>
console.log('data = ', response.data)
)
.catch((error: unknown) => console.log(error));
Here's my API Code:
// Backend
import formidable from 'formidable';
import { NextApiRequest, NextApiResponse } from 'next';
import {
errorResponse,
genericResponse,
getErrorDetailsFromKey,
} from '#global-backend/utils/api/responseSynthesizer';
import {
ErrorCodes,
IResponse,
} from '#constants/interfaces/gcorn/backend/apis/response.interfaces';
export const config = {
api: {
bodyParser: false,
},
};
// eslint-disable-next-line import/no-anonymous-default-export
export default async (req: NextApiRequest, res: NextApiResponse) => {
const form = new formidable.IncomingForm();
//#ts-ignore
form.uploadDir = './'; //#ts-ignore
form.keepExtensions = true;
const opsDetails = getErrorDetailsFromKey(
ErrorCodes.INVALID_OR_CORRUPTED_FILE
);
let response = errorResponse({ opsDetails });
let status_code = 400;
const payload: { response: IResponse; status_code: number; error: boolean } =
await new Promise((resolve) => {
let flag = 0;
form.parse(req, (err, _, files) => {
const isError = err?.message !== undefined;
if (isError) {
response = errorResponse({
message: err.message,
opsDetails,
});
status_code = 400;
}
console.log('Files = ', Object.keys(files.file));
const fileCheck = checkImageFileValidity(files.file as unknown as File);
if (fileCheck.error) {
opsDetails.details = fileCheck.message;
response = errorResponse({
message: fileCheck.message,
opsDetails,
});
status_code = 400;
}
response = genericResponse({
status_code: 201,
opsDetails: getErrorDetailsFromKey(
ErrorCodes.FUNFUSE_PROFILE_UPDATE_SUCESS
),
});
status_code = 201;
flag = 1;
resolve({ response, status_code, error: false });
});
});
return res.status(payload.status_code).json(payload.response);
};
const checkImageFileValidity = (
file: File
): { error: boolean; message: string } => {
const { type, size } = file;
// Must be less than 5MBs in Size and Must be Image File
if (size > 5000000)
return { error: true, message: 'File Size More than 5MBs' };
if (!type.includes('image'))
return { error: true, message: 'File is not an image' };
return { error: false, message: 'File is valid' };
};
But for some reason, I don't know how can I parse body part of my form which extracts the info: {hello:world}.
Does anyone know a way to parse it and collect in the backend ?
Assuming everything else is correct, you need to check the _ variable

Rewinding to an unloaded section stops the audio

There is a track stored in mongo, it needs to be selected in the ReactNative application (so it doesn’t matter, although the link in the browser), in general, this does not cause problems, but as soon as I try to rewind to an unloaded section, stops the audio. With headers, with bytes, everything seems to be ok.
async playTrack(id: string, res: Response, req: RequestWithTokenData) {
const track = await this.findOneById(id);
if (!track) {
throw new CustomHttpException(ErrorTranslateKey.trackNotFound, HttpStatus.NOT_FOUND);
}
let fondedFile: { length: number, chunkSize: number } | undefined;
const { db } = this.connection;
const bucket = new mongo.GridFSBucket(db, {
bucketName: 'tracks',
});
await bucket.find({ _id: new ObjectId(track.trackId) }).forEach((file) => {
fondedFile = file;
});
if (!fondedFile) {
throw new CustomHttpException(ErrorTranslateKey.trackNotFound, HttpStatus.NOT_FOUND);
}
// #ts-ignore
const { range: rangeHeader } = req.headers;
const range = rangeHeader ? rangeHeader.replace(/bytes=/, '').split('-') : [];
range[0] = range[0] ? parseInt(range[0], 10) : 0;
range[1] = range[1] ? parseInt(range[1], 10) : fondedFile.length;
const { start, end } = { start: range[0], end: range[1] };
const downloadStream = bucket.openDownloadStream(track.trackId);
res.set('content-length', String(end - start));
res.set('content-range', `bytes ${start}-${end - 1}/${fondedFile.length}`);
res.set('content-type', 'audio/mp3');
res.set('accept-ranges', 'bytes');
downloadStream.on('data', (chunk) => {
res.write(chunk);
});
downloadStream.on('error', () => {
res.sendStatus(404);
});
downloadStream.on('end', () => {
res.end();
});
}

about vscode api for executeCommand("explorer.newFolder")

I want callback for after newFolder,
executeCommand("explorer.newFolder").then(value => console.log(value))
but The value is not the value of folderName.
I analyzed the code of the command you executed.
The explorer.newFolder command is defined as NEW_FOLDER_COMMAND_ID, and is connected with the openExplorerAndCreate handler. (The result is received through the handler of CommndsRegistry.)
The return of the openExplorerAndCreateis a callback function (Promise).
When i look closely inside,, if the input parameter is not isFolder, that is, if it is a file, a callback function is provided by the return commandService.executeCommand(NEW_UNTITLED_FILE_COMMAND_ID); command.\
but if it is a folder, there is no return value. That is undifined.
in vscode API documentation
return type of executeCommand() is Thenable<T | undefined>. That is, in the case of the corresponding command, it is returned as undefined, not Thenable<T>. If an error is not thrown and undefined is returned, it can be determined that it has been normally executed.
// src/vs/workbench/contrib/files/browser/fileAction.ts
...
export const NEW_FOLDER_COMMAND_ID = 'explorer.newFolder';
...
CommandsRegistry.registerCommand({
id: NEW_FOLDER_COMMAND_ID,
handler: async (accessor) => {
await openExplorerAndCreate(accessor, true);
}
});
...
async function openExplorerAndCreate(accessor: ServicesAccessor, isFolder: boolean): Promise<void> {
const explorerService = accessor.get(IExplorerService);
const fileService = accessor.get(IFileService);
const editorService = accessor.get(IEditorService);
const viewsService = accessor.get(IViewsService);
const notificationService = accessor.get(INotificationService);
const commandService = accessor.get(ICommandService);
const wasHidden = !viewsService.isViewVisible(VIEW_ID);
const view = await viewsService.openView(VIEW_ID, true);
if (wasHidden) {
// Give explorer some time to resolve itself #111218
await timeout(500);
}
if (!view) {
// Can happen in empty workspace case (https://github.com/microsoft/vscode/issues/100604)
if (isFolder) {
throw new Error('Open a folder or workspace first.');
}
return commandService.executeCommand(NEW_UNTITLED_FILE_COMMAND_ID);
}
const stats = explorerService.getContext(false);
const stat = stats.length > 0 ? stats[0] : undefined;
let folder: ExplorerItem;
if (stat) {
folder = stat.isDirectory ? stat : (stat.parent || explorerService.roots[0]);
} else {
folder = explorerService.roots[0];
}
if (folder.isReadonly) {
throw new Error('Parent folder is readonly.');
}
const newStat = new NewExplorerItem(fileService, folder, isFolder);
folder.addChild(newStat);
const onSuccess = async (value: string): Promise<void> => {
try {
const resourceToCreate = resources.joinPath(folder.resource, value);
await explorerService.applyBulkEdit([new ResourceFileEdit(undefined, resourceToCreate, { folder: isFolder })], {
undoLabel: nls.localize('createBulkEdit', "Create {0}", value),
progressLabel: nls.localize('creatingBulkEdit', "Creating {0}", value)
});
await refreshIfSeparator(value, explorerService);
if (isFolder) {
await explorerService.select(resourceToCreate, true);
} else {
await editorService.openEditor({ resource: resourceToCreate, options: { pinned: true } });
}
} catch (error) {
onErrorWithRetry(notificationService, error, () => onSuccess(value));
}
};
await explorerService.setEditable(newStat, {
validationMessage: value => validateFileName(newStat, value),
onFinish: async (value, success) => {
folder.removeChild(newStat);
await explorerService.setEditable(newStat, null);
if (success) {
onSuccess(value);
}
}
});
}

redux observable with axios onProgress

i am creating an upload function that will show a progress bar to the client inside a React Redux and Redux-observable, and i use axios to do a put request to AWS S3.
My epics is as follow
...
function uploadFile(mimetype, url, file) {
const config = {
headers: {
'Content-Type': mimetype,
},
onUploadProgress(progress) {
const percentCompleted = Math.round((progress.loaded * 100) / progress.total)
uploadProgress(percentCompleted)
},
}
axiosRetry(axios, { retries: 3 })
return axios.put(url, file[0], config)
}
export const uploadEpic = (action$, store) => action$
.ofType(SIGNED_URL_SUCCESS)
.mergeMap(() => {
const file = store.getState().File.droppedFile
const mimetype = file[0].type
const { url } = store.getState().SignedUrl
const { fileData } = store.getState().Upload
return of(uploadFile(mimetype, url.data, file))
.concatMap(() => {
const uploadedData = {
url: fileData.url,
thumbUrl: `${fileData.folder}/${fileData.filename}-00001.png`,
}
return [
upload(uploadedData),
uploadSuccess(),
]
})
.catch(error => of(uploadFailure(error)))
})
export default uploadEpic
The upload seems to work, as i received an AWS SNS email telling that its done, but i can't seem to see that it is updating the Upload.progress state inside my Upload reducer.
The reason i am using axios is particulary because its axios-retry and its onUploadProgress, since i can't seem to find an example doing an onProgress using universal-rx-request
so two questions probably
How can i achieve this using axios
How can i achieve this using universal-rx-request
Thanks to this SO answer
I ended up not using axios at all
I got it working with this
import { of } from 'rxjs/observable/of'
import { Subject } from 'rxjs/Subject'
import { Observable } from 'rxjs/Observable'
import 'rxjs/add/observable/dom/ajax'
import { SIGNED_URL_SUCCESS } from 'ducks/SignedUrl'
import {
upload,
uploadIsLoading,
uploadSuccess,
uploadFailure,
uploadProgress,
} from 'ducks/Upload'
export const uploadEpic = (action$, store) => action$
.ofType(SIGNED_URL_SUCCESS)
.mergeMap(() => {
const file = store.getState().File.droppedFile
const mimetype = file[0].type
const { url } = store.getState().SignedUrl
const { fileData } = store.getState().Upload
const progressSubscriber = new Subject()
const request = Observable.ajax({
method: 'PUT',
url: url.data,
body: file[0],
headers: {
'Content-Type': mimetype,
},
progressSubscriber,
})
const requestObservable = request
.concatMap(() => {
const uploadedData = {
...
}
return [
upload(uploadedData),
uploadIsLoading(false),
uploadSuccess(),
]
})
.catch(error => of(uploadFailure(error)))
return progressSubscriber
.map(e => ({ percentage: (e.loaded / e.total) * 100 }))
.map(data => uploadProgress(data.percentage))
.merge(requestObservable)
})
UPDATE: on rxjs 6 the merge operators is deprecated, so if you're using rxjs 6, change the code above to
// some/lib/folder/uploader.js
import { of, merge } from 'rxjs' // import merge here
import { ajax } from 'rxjs/ajax'
import { map, catchError } from 'rxjs/operators' // instead of here
import { Subject } from 'rxjs/Subject'
export function storageUploader(...args) {
const progressSubscriber = new Subject()
const request = ajax({...someRequestOptions})
.pipe(
map(() => success()),
catchError((error) => of(failure(error))),
)
const subscriber = progressSubscriber
.pipe(
map((e) => ({ percentage: (e.loaded / e.total) * 100 })),
map((upload) => progress(upload.percentage)),
catchError((error) => of(failure(error))),
)
return merge(subscriber, request) // merge both like this, instead of chaining the request on progressSubscriber
}
//the_epic.js
export function uploadEpic(action$, state$) {
return action$
.pipe(
ofType(UPLOAD),
mergeMap((someUploadOptions) => uploaderLib(
{ ...someUploadOptions },
actionSuccess,
actionFailure,
actionProgress,
)),
catchError((error) => of(actionFailure(error))),
)
}