I'm testing a data form using Cypress, but am stuck on a step that displays an alert on the page.
This is the test, but it's not working.
describe('Alert is displayed with warning text', () => {
it('Assert that the alert is displayed after entering data', () => {
cy.visit('/')
cy.get('input').type('some data').blur()
cy.on ('window:alert', (text) => {
cy.wrap(text).should('eq', 'alert text')
})
})
})
How do I test this alert that pops up on the page?
The code cy.on('window:alert') is an event listener.
Instead of adding a callback as you would do for other commands, you can add a stub and check the stub function has been called plus the text it is called with.
Also because it's a listener, you must set it up before the event that triggers the event.
describe('Alert is displayed with warning text', () => {
it('Assert that the alert is displayed after entering data', () => {
cy.visit('/')
const stub = cy.stub()
cy.on ('window:alert', stub)
cy.get('input').type('some data').blur()
// wait for the event to be handled
cy.then(() => {
expect(stub.getCall(0)).to.be.calledWith('alert text')
})
})
})
You can modify your code to use expect() instead of should().
The problem is Cypress does not like commands inside event listeners.
You must use a done() callback to avoid a false positive when the alert is not fired.
describe('Alert is displayed with warning text', () => {
it('Assert that the alert is displayed after entering data', (done) => {
cy.visit('/')
cy.on ('window:alert', (text) => {
expect(text).to.eq('alert text')
done() // waiting for event, fails on timeout
)
cy.get('input').type('some data').blur()
})
})
Hello – I hope someone could provide some advise or feedback.
Summary: I am trying to create a custom button (UE script) on Sales Order record. That custom button executes a function from a client side script. The function (snippet below) uses https.post.promise. It calls a Suitelet that I will be using to process some backend logic.
Problem: The “.then” portion is not called/executed.
Notes:
Everything is working expect for .then part. The suitelet is called by the post
When I tried to call the same function on pageInit, the .then part is executing
I have used chrome’s javascript profiler as well and tried to compare both executions (by clicking button and pageInit). I can see that .then is being called when the snippet is executed via pageInit but is not executed, when clicking the button
function createIntercoPo(soId){
log.debug('CS - Create Interco PO', 'START ' + soId);
var suiteletURL = url.resolveScript({
scriptId: 'customscript_swx_sl_auto_ic_so_po',
deploymentId: 'customdeploy_swx_sl_auto_ic_so_po',
});
log.debug('CS - Suitelet URL', suiteletURL);
/*https.post({
async: true,
url: suiteletURL,
body: {
soId: soId
},
callback: function(response) {
var result = JSON.parse(response.body);
redirectAfterProcess(result, transId, transType, "generation");
}
});*/
https.post.promise({
url: suiteletURL,
body: {
soId: soId
}
})
.then(function (response){
log.debug({
title: 'Response',
details: response
});
//redirectAfterProcess(soId);
log.debug('CS - Inside Promise', 'Test');
})
.catch(function onRejected(reason) {
log.debug({
title: 'Invalid Request: ',
details: reason
});
});
log.debug('CS - Create Interco PO', 'END');
}
Taking inspiration from Google's page, I pasted this into my website:
var CACHE_NAME = 'my-site-cache-v1';
var urlsToCache = [
'serviceworker.css'
];
debugger // 1
self.addEventListener('install', function(event) {
debugger // 2
event.waitUntil(
caches.open(CACHE_NAME)
.then(function(cache) {
console.log('Opened cache');
return cache.addAll(urlsToCache);
})
);
});
Debugger 1 stops the program flow, but debugger 2 is never reached.
ServiceWorker.css exists.
I'm navigating to the page using the Incognito window with the developer toolbar open.
The code in your snippet above must be loaded in via register. You will need to be developing with https to see this work
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('./codeWithYourJsAbove.js').then((function(registration) {
console.log('ServiceWorker registration successful with scope: ', registration.scope);
}), function(err) {
console.log('ServiceWorker registration failed: ', err);
});
});
}
Update 2:
Another update - I'm down to this one issue. The values from redux-form are being sent to the action, but even narrowed down to this:
export function signinUser(values) {
console.log('function about to run, email: ' values.get('email'));
}
I don't even see a console log entry. However, the same function with only a simple console log works:
export function signinUser() {
console.log('function about to run');
}
Update:
The only differences between the working code and non-working code is redux-form and immutablejs. I tried back-porting these to the working app and now the behaviour is the same.
I'm submitting my form and sending the redux-form values to the function, where I'm using values.get('email') and values.get('password') to pass the values to axios.
handleFormSubmit(values) {
console.log('sending to action...', values);
this.props.signinUser(values);
}
I have a login form and onSubmit I'm passing the values to a function which dispatches actions.
The code works in a repo I've forked, but I'm transferring it to my own app. The problem I'm having is that the function doesn't seem to fire, and I'm struggling to figure out where to add console.log statements.
The only console.log that fires is on line 2.
export function signinUser(values) {
console.log('function will run');
return function(dispatch) {
axios.post(TOKEN_URL, {
email: "a#a.com",
password: "a",
method: 'post',
credentials: 'include',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
})
.then(response => {
console.log('response: ', response.data.content.token );
// If request is good...
// - Update state to indicate user is authenticated
dispatch({ type: AUTH_USER });
// decode token for info on the user
var decoded_token_data = jwt_decode(response.data.content.token);
// - Save the JWT token
localStorage.setItem('token', response.data.content.token);
console.log(localStorage.getItem('token'));
// - redirect to the appropriate route
browserHistory.push(ROOT_URL);
})
.catch(() => {
// If request is bad...
// - Show an error to the user
dispatch(authError('Bad Login Info'));
});
}
}
I'm having an issue similar to the issues reported both here and here, with a only a few changes in how my form data is loaded.
The solution provided in the second link seemingly resolves my issue, but removing the show/hide scaling effects should not be required in order for CKEditor to instantiate properly. There's bound to be a much better alternative to resolving this conflict.
My issue:
When I open my page, and click the edit button, a jQueryUI Dialog pops up, loads its data via ajax, and then I attempt to replace the textarea added to the dialog with a CKEditor instance. The first time I load the page, the dialog works without a hitch. I'm able to modify the data within the editor, save my form data, and get on with life. However, if I close the dialog, then open it again, the editor is no longer enabled. The buttons still have hover effects, and are clickable, but do nothing. The text area of the editor is disabled and set to "style: visibility: hidden; display: none;". Nearly all the information I can find regarding this issue is from many years ago, and the fixes involve using functions/techniques that no longer exist or are applicable.
Control Flow
I open the page containing a text link 'Edit Update', which calls my Javascript function openEditTicketUpdateDialog.
function openEditTicketUpdateDialog(tup_id, url)
{
simplePost(null, url, new Callback
(
function onSuccess(data)
{
$('#editticketupdatedialog').dialog('option', 'buttons',
[
{
text: 'Save Edits',
click: function()
{
// Save the Update info
var formData = {
tup_update: CKEDITOR.instances.tup_update_edit.getData(),
tup_internal: +$('#tup_internal_edit').is(":checked"),
tup_important: +$('#tup_important_edit').is(":checked")
};
simplePost(formData, data['submitRoute'], new Callback
(
function onSuccess(data)
{
$('#update-' + tup_id).html(data.input['tup_update']);
$('#updateflags-' + tup_id).html(data.flags);
$('#editticketupdatedialog').dialog('close');
},
function onFail(errors)
{
console.log(errors);
}
));
}
},
{
text: 'Cancel',
click: function()
{
$(this).dialog("close");
}
}
]);
$('#editticketupdatedialog').dialog('option', 'title', data['title']);
$('#editticketupdatedialog').html(data['view']);
$('#editticketupdatedialog').dialog('open');
destroyEditor('tup_update_edit');
console.log('CKEDITOR.status: ' + CKEDITOR.status);
createEditor('tup_update_edit');
},
function onFail(errors)
{
console.log(errors);
}
));
}
This function uses three helper functions, simplePost, destroyEditor and createEditor.
function simplePost(data, url, callback)
{
post(data, url, true, false, callback);
}
function createEditor(name)
{
console.log('Create editor: ' + name);
console.log('Current Instance: ');
console.log(CKEDITOR.instances.name);
if (CKEDITOR.status == 'loaded')
{
CKEDITOR.replace(name,
{
customConfig: '/js/ckeditor/custom/configurations/standard_config.js'
});
}
else
{
CKEDITOR.on('load', createEditor(name));
CKEDITOR.loadFullCore && CKEDITOR.loadFullCore();
}
console.log('After instance created: ');
var instance = CKEDITOR.instances.name;
console.log(instance);
}
function destroyEditor(name)
{
console.log('Destroy editor: ' + name);
console.log('Current Instance: ');
console.log(CKEDITOR.instances.name);
if (CKEDITOR.instances.name)
{
console.log('Instance exists - destroying...');
CKEDITOR.instances.name.destroy();
$('#' + name).off().remove();
}
console.log('After instance removed: ');
var instance = CKEDITOR.instances.name;
console.log(instance);
}
This method of creating a CKEditor instance was gathered from here. This method of destroying a CKEditor instance was gathered from here.
As you can see, openEditTicketUpdateDialog fires an AJAX call to my getEditUpdateForm function through Laravel routes.
public function getEditUpdateForm($tup_id, $update_number)
{
$update = Update::find($tup_id);
$data = [
'title' => 'Editing update #' . $update_number . ' of ticket #' . $update->tup_ticket,
'view' => View::make('tickets.ticketupdate-edit')
->with('update', $update)
->render(),
'submitRoute' => route('tickets/update/submit', $tup_id)
];
return Response::json(array('status' => 1, 'data' => $data));
}
From here, a status of 1 is returned, and the onSuccess function is called. I've attempted to add the create/delete calls before the $('#editticketupdatedialog').dialog('open'); call, but to no avail. I've also tried multiple other solutions that I've found surfacing, which involve hacked implementations of jQueryUI's Dialog functions and attributes: _allowInteraction and moveToTop. I was originally successful in resolving this issue the first time it arose by calling this function before doing a CKEDITOR.replace:
function enableCKEditorInDialog()
{
$.widget( "ui.dialog", $.ui.dialog, {
/**
* jQuery UI v1.11+ fix to accommodate CKEditor (and other iframed content) inside a dialog
* #see http://bugs.jqueryui.com/ticket/9087
* #see http://dev.ckeditor.com/ticket/10269
*/
_allowInteraction: function( event ) {
return this._super( event ) ||
// addresses general interaction issues with iframes inside a dialog
event.target.ownerDocument !== this.document[ 0 ] ||
// addresses interaction issues with CKEditor's dialog windows and iframe-based dropdowns in IE
!!$( event.target ).closest( ".cke_dialog, .cke_dialog_background_cover, .cke" ).length;
}
});
}
After updating to Laravel 5, and making a few other changes serverside, this fix no longer works. I have been successful in resolving my issue by removing the show/hide properties from my dialog. I would very much prefer not to have to remove these properties, as half the reasoning for having the dialog is the aesthetics of an animation. Here is my dialog initialization.
$('#editticketupdatedialog').dialog({
modal: true,
draggable: false,
minWidth: 722,
autoOpen: false,
show:
{
effect: "scale",
duration: 200
},
hide:
{
effect: "scale",
duration: 200
},
closeOnEscape: true
});
When I have these animations enabled, the first time I use the dialog, it works perfectly. The second time, I receive the error TypeError: this.getWindow(...).$ is undefined - ckeditor.js:83:18 in the JS console, which refers to this line:
function(a)
{
var d = this.getWindow().$.getComputedStyle(this.$,null);
return d ? d.getPropertyValue(a) : ""
}
Recap
My main goal here is to find a fix for this issue, without having to remove the jQueryUI Dialog animation. I am unsure whom to point fingers at, as I really can't determine if the issue lies in CKEditor, jQueryUI or my implementation.
I finally found a solution that works in my case. losnir updated the outdated solution to a post here, and adding the open function to my dialog initialization resolved my issue.
My initialization is as follows:
$('#editticketupdatedialog').dialog({
modal: true,
draggable: false,
minWidth: 722,
autoOpen: false,
show:
{
effect: "scale",
duration: 200
},
hide:
{
effect: "scale",
duration: 200
},
closeOnEscape: true,
open: function()
{
$(this).parent().promise().done(function ()
{
destroyEditor('tup_update_edit');
console.log('CKEDITOR.status: ' + CKEDITOR.status);
createEditor('tup_update_edit');
});
}
});