Problems with Protractor and sendingKeys - unit-testing

So I am trying to use Protractor to test a non-angular application (using Mocha). I have this code:
var page = createAccountPage.create('/noname');
page.typeFirstNameInput('jane');
page.typeLastNameInput('doe');
page.typePasswordInput('password');
page.clickAgreedToTermsInput();
page.clickCreateAccountButton();
page.redirectToCreateProfilePage();
Note that the type*() are all pretty much the same:
createAccountPage.typeFirstNameInput = function(value) {
$(selector).sendKeys(value);
};
This basically opens the browsers and should fill in the form fills and then clicks a button that redirect the page. The issue that I am running into is that it fills out all the form inputs except the first name. If I do this:
var page = createAccountPage.create('/noname');
page.typeFirstNameInput('jane');
page.typeFirstNameInput('jane');
page.typeLastNameInput('doe');
page.typePasswordInput('password');
page.clickAgreedToTermsInput();
page.clickCreateAccountButton();
page.redirectToCreateProfilePage();
Then it does fill out the first name however I get the error:
StaleElementReferenceError: Element is no longer attached to the DOM
The only reason I can see this happening is that the form is fill out correctly now and clicking the button redirects the pages and for whatever reason, the first page.typeFirstNameInput('jane'); is being executed last (which would also explain when when I have it there once, the first name is filled out).
Is there any reason why the first action page.typeFirstNameInput('jane'); would be executed last?

Related

How to remember past searches for anonymous users

My application doesn't have user accounts, the users anonymously interact with it.
I want to be able to remember what a user has searched for previously without attaching it to their account (as they don't have one). How would I go about doing this?
Is cookies the answer I am looking for? If so, can you point me in the right direction.
Clarification: when the users clicks the search bar to search for something, I want to be able to display what that specific user has searched for in the past in a drop-down box.
you can use localStorage in this situation
There are code snippets which will help you (preliminarily add jQuery in you project for example in head of html
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
). Just add it in your templates
//selector by id - #selector, by class - .selector, by tag - selector
function getItemsFromLS(){
return JSON.parse(localStorage.getItem('search'))
}
function addNewItemToLS(item){
localStorage.setItem('search',JSON.stringify([...getItemsFromLS(), item]))
}
$(document).ready(function(){
//if there are no storage create it
if(!localStorage.getItem('search')){
localStorage.setItem('search', JSON.stringify([]))
}
//click on the search button
$('search-button-selector').click(function(){
//get item form input
let newItem = $('input-type-selector').val()
addNewItemToLS(newItem)
})
//show items on focus of search bar
$('input-type-selector').focus(function(){
let searchItems = []
$(this).change(function(){
searchItems = getItemsFromLS().filter((item)=>item.includes($(this).val()))
$('list-of-search').empty()
searchItems.forEach((item)=>{
$('list-of-search').append(`<span>${item}</span>`)
})
})
})
})

Attachments moved away from Item after validation and before submit process in Apex

I have multiple File Browser Item fields on one page of Application in Oracle Apex.
What happens: When I miss any Item for which validation error fires, I want to hold that file to the browser but I usually loose it if I get that validation error. Is there a solution for the same like other Items fields hold previous value except File Browser Item field. Please see below ss:
Anshul,
APEX 4.2 is very old and no longer supported. A later (or preferably latest) version of APEX will behave differently as Dan explained above.
Can you import your application into apex.oracle.com (which is running APEX 20.1) and you will probably see better results. Based on this you can hopefully use it as justification to upgrade your environment.
Regards,
David
Go to your page-level attributes and a function like the following in the Function and Global Variable Declaration:
function validateItems(request) {
var $file1 = $('#P68_FILE_1');
var $file2 = $('#P68_FILE_2');
var errorsFound = false;
if ($file1.val() === '') {
errorsFound = true;
// Show item in error state
}
if ($file2.val() === '') {
errorsFound = true;
// Show item in error state
}
if (!errorsFound) {
// I think doSubmit was the name of the function back then. If not, try apex.submit
doSubmit(request);
} else {
// Show error message at top of page, I'll use a generic alert for now
alert('You must select a file for each file selector.');
}
}
Then, right-click the Create button and select Create a Dynamic Action. Set the name of the Dynamic Action to Create button clicked.
For the Action, set Type to Execute JavaScript Code. Enter the following JS in code:
validateItems('CREATE');
Finally, ensure that Fire on Initialization is disabled.
Repeat the process for the Save button, but change the request value passed to validateItems to SAVE.

Regex Validation for TreelistEx is not working

In Sitecore Content editor/Page editor, when I add items to TreelistEx I would like the TreelistEx to allow only 12 items. To achieve this solution, I have added a Regex ^.{0,467}$ in the validation field inside the template section in which I want to limit the items.
I have referred this article
This Regex works properly in Content editor. But for the page editor whenever I add an items in treelistEx it works fine for the first time but again if I add/remove items it gives me validation message for both greater and less number of items just after on click of "Ok"and items are also not saved.
Ideally it should give validation message if number of items are greater than 12 and only on Click of "save" button same as it is working in Content editor. How can I solve this Regex validation problem in Page editor? I am using Sitecore 8.1
I also had the same issue a while ago and because of the limited time i had i implemented a not so ideal way but you can implement it if you want.
Let the user add the items and then just grab the first 12 in your code. It will be something like this:
Create a method to get the multicast item (For flexibility).
public static MultilistField GetMultilistField(Item item, string fieldName)
{
if (item != null && !string.IsNullOrWhiteSpace(fieldName))
{
MultilistField field = item.Fields[fieldName];
if (field != null)
{
return field;
}
}
return null;
}
Get the items within the Miltilist field.
MultilistField field = GetMultilistField[DatasourceItem, "fieldName"];
var returnList = field.GetItems().Where(c => c.TemplateName.Equals("someValidationIfYouWant")).ToList().Take(12);

setting an input field using xpath

I have a form such as this:
I am trying to set the input field value to a postal code value "M3C1B4" and then I would like to click the button.
Although I can click the button I am unable to set the value of the input field.
I've tried the following code with no success:
driver.execute_script('arguments[0].value = "M3C1B4";', driver.find_element_by_xpath('//div[#class="shippingBox-update"]//input'))
driver.find_element_by_xpath('//div[#class="shippingBox-update"]//input').send_keys('M3C1B4')
Clicking the button works using this code:
driver.find_element_by_xpath('//div[#class="shippingBox-update"]//button').click()
You are using _ instead of - in "shippingBox_update". Should be
driver.find_element_by_xpath('//div[#class="shippingBox-update"]//input').send_keys('M3C1B4')
By the way, why don't you use the <input> class?
driver.find_element_by_class_name("PC_change_input").send_keys('M3C1B4')
driver.find_element_by_class_name("button-submit").click()
Sorry for the trouble. I got it to work. Apart from the error where I had _ instead of - that was pointed out by "guy", there was another problem.
The box was populated by a default value that had to be cleared first because the box only allowed for 6 values.
This did the trick:
driver.find_element_by_xpath('//div[#class="shippingBox-update"]//input').clear()
driver.find_element_by_xpath('//div[#class="shippingBox-update"]//input').send_keys('M3C1B6')
driver.find_element_by_xpath('//div[#class="shippingBox-update"]//button').click()

Unit testing React component using Material UI Dialog

I am currently writing unit tests for my React + MaterialUi application.
In my application I have a Dialog. I want to make sure depending on what button pressed on the dialog:
<FlatButton
label="Cancel"
secondary={true}
onTouchTap={this._cancelDialog.bind(this)}
/>
<FlatButton
label="Submit"
primary={true}
onTouchTap={this._confirmDialog.bind(this)}
/>
that the internal state changes accordingly.
Unfortunately i cannot get ahold of the dialog content using
TestUtils.scryRenderedComponentsWithType(FlatButton)
or
scryRenderedComponentsWithTag("button")
and so on.
Any ideas on how that flow can be tested?
Update 1
So I can get the Dialog instance by calling TestUtils.scryRenderedComponentsWithType(Dialog). But I can not get the dialogs content. DOM wise the content does not render inside the view itself. Its rendered in a new created node on document level (div). So i tried this:
let cancelButton = window.document.getElementsByTagName("button")[0];
Simulate.click(cancelButton);
cancelButton in the case above is the correct DOM element. Simulate.click however does not trigger the components click function.
regards
Jonas
just ran into the same problem. I looked into the source code, and the Dialog component's render method actually creates an instance of the component RenderToLayer. this component behaves as a portal and breaks react's DOM tree by returning null in its' render function and instead appending directly to the body.
Luckily, the RenderToLayer component accepts the prop render, which essentially allows the component to pass to the portal a function to be called when it is in a render cycle. This means that we can actually manually trigger this event ourselves. It's not perfect, i admit, but after a few days of poking around trying to find a solution for this hack i am throwing in the towel and writing my tests like this:
var component = TestUtils.renderIntoDocument(<UserInteractions.signupDialog show={true}/>)
var dialog = TestUtils.renderIntoDocument(component.refs.dialog.renderLayer())
var node = React.findDOMNode(dialog)
and here is what my UserInteractions.signupDialog looks like:
exports.signupDialog = React.createClass({
...
render: function() {
var self = this;
return (
<div>
<Dialog
ref='dialog'
title="Signup"
modal={false}
actions={[
<Button
label="Cancel"
secondary={true}
onTouchTap={self.__handleClose}
/>,
<Button
label="Submit"
primary={true}
keyboardFocused={true}
onTouchTap={self.__handleClose}
/>
]}
open={self.props.show}
onRequestClose={self.__handleClose}
>
<div className='tester'>ham</div>
<TextField id='tmp-email-input' hintText='email' type='text'/>
</Dialog>
</div>
)
}
})
Now i can make assertions against the child components rendered in the dialog box, and can even make assertions about events bound to my original component, as their relationship is maintained.
I definitely recommend setting up a debugger in your testing stack if you are going to continue using material ui. Theres not a lot of help for things like this. Heres what my debug script looks like:
// package.json
{
...
"scripts": {
"test": "mocha --compilers .:./test/utils/compiler.js test/**/*.spec.js",
"debug": "mocha debug --compilers .:./test/utils/compiler.js test/**/*.spec.js"
}
}
and now you can use npm test to run mocha tests, and npm run debug to enter debugger. Once in the debugger, it will immediately pause and wait for you to enter breakpoints. At this juncture, enter c to continue. Now you can place debugger; statements anywhere in your code to generate a breakpoint which the debugger will respond to. Once it has located your breakpoint, it will pause and allow you to engage your code using local scope. At this point, enter repl to enter your code's local scope and access your local vars.
Perhaps you didnt need a debugger, but maybe someone else will find this helpful. Good luck, happy coding!
Solved it as follows:
/*
* I want to verify that when i click on cancel button my showModal state is set * to false
*/
//shallow render my component having Dialog
const wrapper= shallow(<MyComponent store={store} />).dive();
//Set showModal state to true
wrapper.setState({showModal:true});
//find out cancel button with id 'cancelBtn' object from actions and call onTouchTap to mimic button click
wrapper.find('Dialog').props().actions.find((elem)=>(elem.props.id=='cancelBtn')).props.onTouchTap();
//verify that the showModal state is set to false
expect(wrapper.state('showModal')).toBe(false);
I ran into the same issue and solve it like that :
const myMock = jest.genMockFunction();
const matcherComponent = TestUtils.renderIntoDocument(
<MatcherComponent onClickCancel={myMock} activAction/>
);
const raisedButton = TestUtils.findRenderedComponentWithType(
matcherComponent, RaisedButton);
TestUtils.Simulate.click(ReactDOM.findDOMNode(raisedButton).firstChild);
expect(myMock).toBeCalled();
It works fine for me. However I'm still struggling with Simulate.change
Solution by avocadojesus is excellent. But I have one addition. If you try to apply this solution and get an error:
ERROR: 'Warning: Failed context type: The context muiTheme is marked
as required in DialogInline, but its value is undefined.
You should modify his the code as follows:
var component = TestUtils.renderIntoDocument(
<MuiThemeProvider muiTheme={getMuiTheme()}>
<UserInteractions.signupDialog show={true}/>
</MuiThemeProvider>
);
var dialogComponent = TestUtils.findRenderedComponentWithType(component, UserInteractions.signupDialog);
var dialog = TestUtils.renderIntoDocument(
<MuiThemeProvider muiTheme={getMuiTheme()}>
{dialogComponent.refs.dialog.renderLayer()}
</MuiThemeProvider>
);
var node = React.findDOMNode(dialog);
Material UI fork the 2 enzyme methods. You need to use the createMount or the createShallow with dive option https://material-ui.com/guides/testing/#createmount-options-mount