I am trying to select an incorrect answer (radio button) to get an error message to appear, but the answers are random (except the correct answer).
How can I say get the radio buttons, and then click one that does not equal "correct answer" using cypress assertions?
cy.get('[data-cy="multipleChoiceQuestionAnswer"]')
.should('not.contain', 'correct answer')//.find('label').not('corect answer')//.not.includes('correct answer')
.click()
I would like to be able to select one of the two radio buttons for the incorrect answers, right now I can only select the correct answer.
well:
be aware that .should('not.contain', 'correct answer') is an assertion, is not a way to filter/get some elements.
It's, essentially, just a way to check (aka "assert") that something is like you expect it to be.
An assertion like yours is useful just to get the Cypress log print something like this
Read it like if you are telling
"Ehy Cypress, I selected an element, could you check that it doesn't contain the correct answer, please?"
What are assertions useful for? They aren't useful when everything goes right but when the test goes wrong.
Because without assertions, you can find yourself behind a broken test with Cypress telling you that "there isn't the element" but you can't know which element Cypress isn't finding.
Placing some "key point" assertions allows you to understand why a test failed in short time.
Anyway: if your HTML is something like this
<div data-cy="multipleChoiceQuestionAnswer"><label>correct answer<input type="checkbox"/></label></div>
<div data-cy="multipleChoiceQuestionAnswer"><label>no<input type="checkbox"/></label></div>
<div data-cy="multipleChoiceQuestionAnswer"><label>nope<input type="checkbox"/></label></div>
you can accomplish your goal making:
cy.get('[data-cy="multipleChoiceQuestionAnswer"]').then(els => {
// `els` is a jQuery instance, let's parse the various elements
let $el;
for(let i = 0, n = els.length; i < n; i++) {
// it transforms every element in a jQuery instance
$el = Cypress.$(els[i]);
// it uses jQuery to get the label text
if($el.find("label").text() !== "correct answer") {
// it stops as soon as the answer isn't the correct one
break;
}
}
// returns the element to be clicked
return $el.find("input");
})
// it assert about it (to have a useful hint in the Cypress command log)
.should("not.contain", "correct answer")
// clicks it
.click();
I hope the code is self-explanatory (in case it isn't, ask me some more clarifications) 😊
The PromptDialog.Choice in the Bot Framework display the choice list which is working well. However, I would like to have an option to cancel/escape/exit the dialog with giving cancel/escape/exit optioin in the list. Is there anything in PromptDialog.Choice which can be overridden since i have not found any cancel option.
here is my code in c#..
PromptDialog.Choice(
context: context,
resume: ChoiceSelectAsync,
options: getSoftwareList(softwareItem),
prompt: "We have the following software items matching " + softwareItem + ". (1), (2), (3). Which one do you want?:",
retry: "I didn't understand. Please try again.",
promptStyle: PromptStyle.PerLine);
Example:
Bot: We have the following software items matching Photoshop. (1), (2), (3). Which one do you want
Version 1
Version 2
Version 3
What I want if user enter none of above or a command or number, cancel, exit, that bypasses the options above, without triggering the retry error message.
How do we do that?
There are two ways of achieving this:
Add cancel as an option as suggested. While this would definitely work, long term you will find repeating yourself a lot, plus that you will see the cancel option in the list of choices, what may not be desired.
A better approach would be to extend the current PromptChoice to add your exit/cancelation logic. The good news is that there is something already implemented that you could use as is or as the base to achieve your needs. Take a look to the CancelablePromptChoice included in the BotBuilder-Samples repository. Here is how to use it.
Just add the option "cancel" on the list and use a switch-case on the method that gets the user input, then call your main manu, or whatever you want to do on cancel
Current Prompt Choice does not work in that way to allows user select by number. I have override the ScoreMatch function in CancleablePromptChoice as below
public override Tuple<bool, int> ScoreMatch(T option, string input)
{
var trimmed = input.Trim();
var text = option.ToString();
// custom logic to allow users to select by number
int isInt;
if(int.TryParse(input,out isInt) && isInt <= promptOptions.Options.Count())
{
text = promptOptions.Options.ElementAt(isInt - 1).ToString();
trimmed = option.ToString().Equals(text) ? text :trimmed;
}
bool occurs = text.IndexOf(trimmed, StringComparison.CurrentCultureIgnoreCase) >= 0;
bool equals = text == trimmed;
return occurs ? Tuple.Create(equals, trimmed.Length) : null;
}
#Ezequiel Once again thank you!.
basically the issue is taking place at the moment when I send some value which is appended to a default value '01/01/2000' somehow. I've tried different ways to do this without succeed, I've used these exact lines in other script and it worked but I don't know why this isn't working here. Please find below the last code I used followed by the picture with the issue displayed.
var targetStartDate = browser.driver.findElement(by.id('StartDate'));
targetStartDate.clear().then(function () {
targetStartDate.sendKeys('09/01/2016');
})
example of the issue
Thanks in advance for any response.
You can try issuing clear() call before sending keys:
targetStartDate.clear();
targetStartDate.sendKeys('09/01/2016');
The other option would be to select all text in the input prior to sending keys:
// protractor.Key.COMMAND on Mac
targetStartDate.sendKeys(protractor.Key.chord(protractor.Key.CONTROL, "a"));
targetStartDate.sendKeys('09/01/2016');
I have encountered this same issue before. There is an input mask formatting the input in the field. In order to solve this, you must write your test as if it were the actual user, with the formatting in mind:
var targetStartDate = browser.driver.findElement(by.id('StartDate'));
// Remove the forward slashes because the input field takes care of that.
var inputDate = '09012016';
targetStartDate.clear();
// Loop through each character of the string and send it to the input
// field followed by a delay of 250 milliseconds to give the field
// enough time to format the input as you keep sending keys.
for (var i = 0; i < inputDate.length; i++) {
targetStartDate.sendKeys(inputDate[i]);
browser.driver.sleep(250);
}
Depending on the latency of the site and performance, you may either need to decrease the 250 millisecond delay, or be able to decrease it.
Hope this helps!
I'm facing an issue with CKEditor 4, I need to have an output without any html entity so I added config.entities = false; in my config, but some appear when
an inline tag is inserted: the space before is replaced with
text is pasted: every space is replaced with even with config.forcePasteAsPlainText = true;
You can check that on any demo by typing
test test
eg.
Do you know how I can prevent this behaviour?
Thanks!
Based on Reinmars accepted answer and the Entities plugin I created a small plugin with an HTML filter which removes redundant entities. The regular expression could be improved to suit other situations, so please edit this answer.
/*
* Remove entities which were inserted ie. when removing a space and
* immediately inputting a space.
*
* NB: We could also set config.basicEntities to false, but this is stongly
* adviced against since this also does not turn ie. < into <.
* #link http://stackoverflow.com/a/16468264/328272
*
* Based on StackOverflow answer.
* #link http://stackoverflow.com/a/14549010/328272
*/
CKEDITOR.plugins.add('removeRedundantNBSP', {
afterInit: function(editor) {
var config = editor.config,
dataProcessor = editor.dataProcessor,
htmlFilter = dataProcessor && dataProcessor.htmlFilter;
if (htmlFilter) {
htmlFilter.addRules({
text: function(text) {
return text.replace(/(\w) /g, '$1 ');
}
}, {
applyToAll: true,
excludeNestedEditable: true
});
}
}
});
These entities:
// Base HTML entities.
var htmlbase = 'nbsp,gt,lt,amp';
Are an exception. To get rid of them you can set basicEntities: false. But as docs mention this is an insecure setting. So if you only want to remove , then I should just use regexp on output data (e.g. by adding listener for #getData) or, if you want to be more precise, add your own rule to htmlFilter just like entities plugin does here.
Remove all but not <tag> </tag> with Javascript Regexp
This is especially helpful with CKEditor as it creates lines like <p> </p>, which you might want to keep.
Background: I first tried to make a one-liner Javascript using lookaround assertions. It seems you can't chain them, at least not yet. My first approach was unsuccesful:
return text.replace(/(?<!\>) (?!<\/)/gi, " ")
// Removes but not <p> </p>
// It works, but does not remove `<p> blah </p>`.
Here is my updated working one-liner code:
return text.replace(/(?<!\>\s.)( (?!<\/)|(?<!\>) <\/p>)/gi, " ")
This works as intended. You can test it here.
However, this is a shady practise as lookarounds are not fully supported by some browsers.
Read more about Assertions.
What I ended up using in my production code:
I ended up doing a bit hacky approach with multiple replace(). This should work on all browsers.
.trim() // Remove whitespaces
.replace(/\u00a0/g, " ") // Remove unicode non-breaking space
.replace(/((<\w+>)\s*( )\s*(<\/\w+>))/gi, "$2<!--BOOM-->$4") // Replace empty nbsp tags with BOOM
.replace(/ /gi, " ") // remove all
.replace(/((<\w+>)\s*(<!--BOOM-->)\s*(<\/\w+>))/gi, "$2 $4") // Replace BOOM back to empty tags
If you have a better suggestion, I would be happy to hear 😊.
I needed to change the regular expression Imeus sent, in my case, I use TYPO3 and needed to edit the backend editor. This one didn't work. Maybe it can help another one that has the same problem :)
return text.replace(/ /g, ' ');
In Google Sheets, you can add some scripting functionality. I'm adding something for the onEdit event, but I can't tell if it's working. As far as I can tell, you can't debug a live event from Google Sheets, so you have to do it from the debugger, which is pointless since the event argument passed to my onEdit() function will always be undefined if I run it from the Script Editor.
So, I was trying to use the Logger.log method to log some data whenever the onEdit function gets called, but this too seems like it only works when run from the Script Editor. When I run it from the Script Editor, I can view the logs by going to View->Logs...
I was hoping I'd be able to see the logs from when the event actually gets executed, but I can't figure it out.
How do I debug this stuff?
UPDATE:
As written in this answer,
Stackdriver Logging is the preferred method of logging now.
Use console.log() to log to Stackdriver.
Logger.log will either send you an email (eventually) of errors that have happened in your scripts, or, if you are running things from the Script Editor, you can view the log from the last run function by going to View->Logs (still in script editor). Again, that will only show you anything that was logged from the last function you ran from inside Script Editor.
The script I was trying to get working had to do with spreadsheets - I made a spreadsheet todo-checklist type thing that sorted items by priorities and such.
The only triggers I installed for that script were the onOpen and onEdit triggers. Debugging the onEdit trigger was the hardest one to figure out, because I kept thinking that if I set a breakpoint in my onEdit function, opened the spreadsheet, edited a cell, that my breakpoint would be triggered. This is not the case.
To simulate having edited a cell, I did end up having to do something in the actual spreadsheet though. All I did was make sure the cell that I wanted it to treat as "edited" was selected, then in Script Editor, I would go to Run->onEdit. Then my breakpoint would be hit.
However, I did have to stop using the event argument that gets passed into the onEdit function - you can't simulate that by doing Run->onEdit. Any info I needed from the spreadsheet, like which cell was selected, etc, I had to figure out manually.
Anyways, long answer, but I figured it out eventually.
EDIT:
If you want to see the todo checklist I made, you can check it out here
(yes, I know anybody can edit it - that's the point of sharing it!)
I was hoping it'd let you see the script as well. Since you can't see it there, here it is:
function onOpen() {
setCheckboxes();
};
function setCheckboxes() {
var checklist = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("checklist");
var checklist_data_range = checklist.getDataRange();
var checklist_num_rows = checklist_data_range.getNumRows();
Logger.log("checklist num rows: " + checklist_num_rows);
var coredata = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("core_data");
var coredata_data_range = coredata.getDataRange();
for(var i = 0 ; i < checklist_num_rows-1; i++) {
var split = checklist_data_range.getCell(i+2, 3).getValue().split(" || ");
var item_id = split[split.length - 1];
if(item_id != "") {
item_id = parseInt(item_id);
Logger.log("setting value at ("+(i+2)+",2) to " + coredata_data_range.getCell(item_id+1, 3).getValue());
checklist_data_range.getCell(i+2,2).setValue(coredata_data_range.getCell(item_id+1, 3).getValue());
}
}
}
function onEdit() {
Logger.log("TESTING TESTING ON EDIT");
var active_sheet = SpreadsheetApp.getActiveSheet();
if(active_sheet.getName() == "checklist") {
var active_range = SpreadsheetApp.getActiveSheet().getActiveRange();
Logger.log("active_range: " + active_range);
Logger.log("active range col: " + active_range.getColumn() + "active range row: " + active_range.getRow());
Logger.log("active_range.value: " + active_range.getCell(1, 1).getValue());
Logger.log("active_range. colidx: " + active_range.getColumnIndex());
if(active_range.getCell(1,1).getValue() == "?" || active_range.getCell(1,1).getValue() == "?") {
Logger.log("made it!");
var next_cell = active_sheet.getRange(active_range.getRow(), active_range.getColumn()+1, 1, 1).getCell(1,1);
var val = next_cell.getValue();
Logger.log("val: " + val);
var splits = val.split(" || ");
var item_id = splits[splits.length-1];
Logger.log("item_id: " + item_id);
var core_data = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("core_data");
var sheet_data_range = core_data.getDataRange();
var num_rows = sheet_data_range.getNumRows();
var sheet_values = sheet_data_range.getValues();
Logger.log("num_rows: " + num_rows);
for(var i = 0; i < num_rows; i++) {
Logger.log("sheet_values[" + (i) + "][" + (8) + "] = " + sheet_values[i][8]);
if(sheet_values[i][8] == item_id) {
Logger.log("found it! tyring to set it...");
sheet_data_range.getCell(i+1, 2+1).setValue(active_range.getCell(1,1).getValue());
}
}
}
}
setCheckboxes();
};
As far as I can tell, you can't debug a live event from google docs, so you have to do it from the debugger, which is pointless since the event argument passed to my onEdit() function will always be undefined if I run it from the Script Editor.
True - so define the event argument yourself for debugging. See How can I test a trigger function in GAS?
I was trying to use the Logger.log method to log some data whenever the onEdit function gets called, but this too seems like it only works when run from the Script Editor. When I run it from the Script Editor, I can view the logs by going to View->Logs...
True again, but there is help. Peter Hermann's BetterLog library will redirect all logs to a spreadsheet, enabling logging even from code that is not attached to an instance of the editor / debugger.
If you're coding in a spreadsheet-contained script, for example, you can add just this one line to the top of your script file, and all logs will go to a "Logs" sheet in the spreadsheet. No other code necessary, just use Logger.log() as you usually would:
Logger = BetterLog.useSpreadsheet();
2017 Update:
Stackdriver Logging is now available for Google Apps Script. From the menu bar in the script editor, goto:
View > Stackdriver Logging to view or stream the logs.
console.log() will write DEBUG level messages
Example onEdit() logging:
function onEdit (e) {
var debug_e = {
authMode: e.authMode,
range: e.range.getA1Notation(),
source: e.source.getId(),
user: e.user,
value: e.value,
oldValue: e. oldValue
}
console.log({message: 'onEdit() Event Object', eventObject: debug_e});
}
Then check the logs in the Stackdriver UI labeled onEdit() Event Object to see the output
I've gone through these posts and somehow ended up finding a simple answer, which I'm posting here for those how want short and sweet solutions:
Use console.log("Hello World") in your script.
Go to https://script.google.com/home/my and select your add-on.
Click on the ellipsis menu on Project Details, select Executions.
Click on the header of the latest execution and read the log.
A little hacky, but I created an array called "console", and anytime I wanted to output to console I pushed to the array. Then whenever I wanted to see the actual output, I just returned console instead of whatever I was returning before.
//return 'console' //uncomment to output console
return "actual output";
}
If you have the script editor open you will see the logs under View->Logs. If your script has an onedit trigger, make a change to the spreadsheet which should trigger the function with the script editor opened in a second tab. Then go to the script editor tab and open the log. You will see whatever your function passes to the logger.
Basically as long as the script editor is open, the event will write to the log and show it for you. It will not show if someone else is in the file elsewhere.
I am having the same problem, I found the below on the web somewhere....
Event handlers in Docs are a little tricky though. Because docs can handle multiple simultaneous edits by multiple users, the event handlers are handled server-side. The major issue with this structure is that when an event trigger script fails, it fails on the server. If you want to see the debug info you'll need to setup an explicit trigger under the triggers menu that emails you the debug info when the event fails or else it will fail silently.
It's far from elegant, but while debugging, I often log to the Logger, and then use getLog() to fetch its contents. Then, I either:
save the results to a variable (which can be inspected in the Google Scripts debugger—this works around cases where I can't set a breakpoint in some code, but I can set one in code that gets executed later)
write it to some temporary DOM element
display it in an alert
Essentially, it just becomes a JavaScript output issue.
It grossly lacks the functionality of modern console.log() implementations, but the Logger does still help debug Google Scripts.
Just as a notice. I made a test function for my spreadsheet. I use the variable google throws in the onEdit(e) function (I called it e). Then I made a test function like this:
function test(){
var testRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(GetItemInfoSheetName).getRange(2,7)
var testObject = {
range:testRange,
value:"someValue"
}
onEdit(testObject)
SpreadsheetApp.getActiveSpreadsheet().getSheetByName(GetItemInfoSheetName).getRange(2,6).setValue(Logger.getLog())
}
Calling this test function makes all the code run as you had an event in the spreadsheet. I just put in the possision of the cell i edited whitch gave me an unexpected result, setting value as the value i put into the cell.
OBS! for more variables googles gives to the function go here: https://developers.google.com/apps-script/guides/triggers/events#google_sheets_events
Currently you are confined to the container bound nature of using scripts within docs. If you create a new script inside outside of docs then you will be able to export information to a google spreadsheet and use it like a logging tool.
For example in your first code block
function setCheckboxes() {
// Add your spreadsheet data
var errorSheet = SpreadsheetApp.openById('EnterSpreadSheetIDHere').getSheetByName('EnterSheetNameHere');
var cell = errorSheet.getRange('A1').offset(errorSheet.getLastRow(),0);
// existing code
var checklist = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("checklist");
var checklist_data_range = checklist.getDataRange();
var checklist_num_rows = checklist_data_range.getNumRows();
// existing logger
Logger.log("checklist num rows: " + checklist_num_rows);
//We can pass the information to the sheet using cell.setValue()
cell.setValue(new Date() + "Checklist num rows: " + checklist_num_rows);
When I'm working with GAS I have two monitors ( you can use two windows ) set up with one containing the GAS environment and the other containing the SS so I can write information to and log.
The dev console will log errors thrown by the app script, so you can just throw an error to get it logged as a normal console.log. It will stop execution, but it might still be useful for step by step debugging.
throw Error('hello world!');
will show up in the console similarly to console.log('hello world')
For Apps Script projects that are tied to a single Sheet (or doc) — in 2022 — there is no View menu like other answers suggest. Instead you need to look in the Executions menu on the left sidebar to see the executions of your onSelectionChange function (or any other function), from there you can click REFRESH until your console.log messages appear.
just debug your spreadsheet code like this:
...
throw whatAmI;
...
shows like this: