I have the issue described at http://wiki.apache.org/myfaces/Facelets_with_Trinidad. More specifically:
"There is an issue in the id generation for components when a PPR is executed. The symptom is that a click on an command does not execute the desired action but only reloads the whole page. Any subsequent click on any command succeeds.
To work around this issue manually set the id's for at least all commands on the affected pages.".
I already tried the above method but the problem keeps arising. Does anybody have any solution to this?
Finally, I solved the above problem by calling the function below on load page.
// Override function to solve ppr problems
function overrideFunc() {
TrPage.prototype._updateViewState = function(a59, a60, a61) {
var a62 = null;
if (a61)
a62 = a59.getElementById(a61);
for ( var i = 0; i < a59.forms.length; i++) {
a62 = a59.forms[i];
if (!a62)
return;
var a63 = a62.elements[TrPage._VIEW_STATE_ID];
if (!a63) {
a63 = a59.createElement("input");
a63.type = 'hidden';
if(_agent.isIE && _agent.version < 8) {
a63.id = TrPage._VIEW_STATE_ID;
}
a63.name = TrPage._VIEW_STATE_ID;
a62.appendChild(a63);
}
a63.value = TrPage._getTextContent(a60);
}
};
}
Related
I have 15 buttons on a page. I need to test each button.
I tried a simple for loop, like
for (var i = 1; i < 15; i++) {
cy.get("[=buttonid=" + i + "]").click()
}
But Cypress didn't like this. How would I write for loops in Cypress?
To force an arbitrary loop, I create an array with the indices I want, and then call cy.wrap
var genArr = Array.from({length:15},(v,k)=>k+1)
cy.wrap(genArr).each((index) => {
cy.get("#button-" + index).click()
})
Lodash is bundled with Cypress and methods are used with Cypress._ prefix.
For this instance, you'll be using the _.times. So your code will look something like this:
Cypress._.times(15, (k) => {
cy.get("[=buttonid=" + k + "]").click()
})
You can achieve something similar to a "for loop" by using recursion.
I just posted a solution here: How to use a while loop in cypress? The control of is NOT entering the loop when running this spec file? The way I am polling the task is correct?
Add this to your custom commands:
Cypress.Commands.add('recursionLoop', {times: 'optional'}, function (fn, times) {
if (typeof times === 'undefined') {
times = 0;
}
cy.then(() => {
const result = fn(++times);
if (result !== false) {
cy.recursionLoop(fn, times);
}
});
});
Then you can use it by creating a function that returns false when you want to stop iterating.
cy.recursionLoop(times => {
cy.wait(1000);
console.log(`Iteration: ${times}`);
console.log('Here goes your code.');
return times < 5;
});
While cy.wrap().each() will work (one of the answers given for this question), I wanted to give an alternate way that worked for me. cy.wrap().each() will work, but regular while/for loops will not work with cypress because of the async nature of cypress. Cypress doesn't wait for everything to complete in the loop before starting the loop again. You can however do recursive functions instead and that waits for everything to complete before it hits the method/function again.
Here is a simple example to explain this. You could check to see if a button is visible, if it is visible you click it, then check again to see if it is still visible, and if it is visible you click it again, but if it isn't visible it won't click it. This will repeat, the button will continue to be clicked until the button is no longer visible. Basically the method/function is called over and over until the conditional is no longer met, which accomplishes the same thing as a for/while loop, but actually works with cypress.
clickVisibleButton = () => {
cy.get( 'body' ).then( $mainContainer => {
const isVisible = $mainContainer.find( '#idOfElement' ).is( ':visible' );
if ( isVisible ) {
cy.get( '#idOfElement' ).click();
this.clickVisibleButton();
}
} );
}
Then obviously call the this.clickVisibleButton() in your test. I'm using typescript and this method is setup in a class, but you could do this as a regular function as well.
// waits 2 seconds for each attempt
refreshQuote(attempts) {
let arry = []
for (let i = 0; i < attempts; i++) { arry.push(i) }
cy.wrap(arry).each(() => {
cy.get('.quote-wrapper').then(function($quoteBlock) {
if($quoteBlock.text().includes('Here is your quote')) {
}
else {
cy.get('#refreshQuoteButton').click()
cy.wait(2000)
}
})
})
}
Try template literals using backticks:
for(let i = 0; i < 3; i++){
cy.get(`ul li:nth-child(`${i}`)).click();
}
I am using Ext JS v7.1 and I have overridden Ext.Base to set my naming scheme for the classes that inherits from Ext.Base: This eases my debugging.
Ext.define('App.class.Base', {
override: 'Ext.Base',
constructor: function() {
var me = this
/**
* App.base.store.Base => store-base-
* App.store.Menu => store-menu-
*/
if (me.isIdentifiable) {
if (!me.self.prototype.hasOwnProperty('identifiablePrefix')) {
const classNameParts = me.$className.match(/([^\.]+)/g)
if (classNameParts && classNameParts[0] === 'App') {
classNameParts.splice(0, classNameParts.length - 2)
me.self.prototype.identifiablePrefix = classNameParts.reduce((i, j) => i + '-' + j).toLocaleLowerCase() + '-'
}
}
}
return me.callParent()
}
})
This code was building before without an error but, after I upgraded Sencha Cmd to v7.3.0.19, I started the get the following error:
[ERR] C2016: Override target not found -- /...../packages/local/module-core/overrides/class/Base.js:2:64
[WRN] Override App.class.Base in file /..../packages/local/module-core/overrides/class/Base.js had no target detected
I don't know whether this is the right place/way to do this override, if not I can change my implementation. However, if there is no other way, how can get rid of the build error?
Thanks in advance,
Ipek
Because i am not using sencha build tools anymore, i can not help you directly but i would like to share another approach:
In case you have loaded the framework (ext-debug-all or ext-all, etc.) first and the class which should get overwritten is already defined you can do it like that:
Ext.Component.override({
initComponent: function () {
Ext.log('bootstraping ' + this.self.getName());
var me = this,
width = me.width,
height = me.height;
// If plugins have been added by a subclass's initComponent before calling up to here (or any components
// that don't have a table view), the processed flag will not have been set, and we must process them again.
// We could just call getPlugins here however most components don't have them so prevent the extra function call.
if (me.plugins && !me.plugins.processed) {
me.plugins = me.constructPlugins();
}
me.pluginsInitialized = true;
// this will properly (ignore or) constrain the configured width/height to their
// min/max values for consistency.
if (width != null || height != null) {
me.setSize(width, height);
}
if (me.listeners) {
me.on(me.listeners);
me.listeners = null; //change the value to remove any on prototype
}
if (me.focusable) {
me.initFocusable();
}
}
});
Depending on the further internal processing you can call callParent or callSuper.
More details here:
https://docs.sencha.com/extjs/6.5.3/classic/Ext.Class.html#cfg-override
You may be able to move this upper code inside a function and call it later, for example - when Ext.isReady. I guess this can solve or tackle some of the open tooling issues you are facing.
UPDATE:
Coming back to your question you can do the following and define it like that:
Ext.Base.override({
constructor: function() {
var me = this
/**
* App.base.store.Base => store-base-
* App.store.Menu => store-menu-
*/
if (me.isIdentifiable) {
if (!me.self.prototype.hasOwnProperty('identifiablePrefix')) {
const classNameParts = me.$className.match(/([^\.]+)/g)
if (classNameParts && classNameParts[0] === 'App') {
classNameParts.splice(0, classNameParts.length - 2)
me.self.prototype.identifiablePrefix = classNameParts.reduce((i, j) => i + '-' + j).toLocaleLowerCase() + '-'
}
}else{
console.log('isIdentifiable');
console.log(me.identifiablePrefix);
}
}
return me.callParent(arguments)
}
});
I have added an exampole fiddle here. It should log "helloWorld" in case identifiablePrefix is set.
https://fiddle.sencha.com/#view/editor&fiddle/3a8i
I am using the Microsoft Word Javascript API. I have used the .search() function to retrieve an array of ranges and then have saved them to state.definitions in my App.js React component state. This part works. When I try to print out the state using console.log(JSON.stringify(this.state.definitions)), I see the ranges that I just saved.
In a separate function, I want to retrieve those ranges and highlight them in a new color. This part does not work. I don't get any errors, but I don't see any highlight changes in the document.
Interestingly, if I try to highlight the ranges BEFORE saving them to state, it works. This makes me think that the ranges that I am retrieving from state are not actually the ranges understood by Word.
Any help would be much appreciated.
var flattenedTerms contains an array of range items that were retrieved from Word a few lines above. This code successfully changes the font
for (var i = 0; i < flattenedTerms.length; i++) {
console.log('flattenedTerms: ', flattenedTerms[i]);
flattenedTerms[i].font.color = 'purple';
flattenedTerms[i].font.highlightColor = 'pink';
flattenedTerms[i].font.bold = true;
}
return context.sync().then(function () {
return resolve(flattenedTerms);
})
})
Now the flattenedTerms array, which contains the range items, has been saved to state.definitions using this.setState. This fails to change the font. All of the console.logs do print.
highlightDefinedTerms = () => {
var self = this;
return Word.run(
function (context) {
var definitions = self.state.definitions;
console.log('Highlighting ', definitions.length, ' terms.');
for (var i = 0; i < definitions.length; i++) {
console.log('Highlighting definition: ', JSON.stringify(definitions[i]));
definitions[i].font.color = 'blue';
definitions[i].font.highlightColor = 'red';
definitions[i].font.bold = true;
}
return context.sync();
}
)
}
You need to pass a first parameter to “Word.run” to specify the object whose context you want to resume.
Word.run(self.state.definitions, function(context) ...)
I have the following case:
A window is shown the the reference to that is stored in a utility class.
Later a modal dialog needs to appear above that window; so I am doing the following:
OptionalMessageBox message = new OptionalMessageBox(title, errorMessage.ToString(), MessageImage.Warning);
if (UIUtilities.TopWindow != null)
{
UIUtilities.TopWindow.Dispatcher.Invoke(() => message.Owner = UIUtilities.TopWindow);
UIUtilities.TopWindow.Dispatcher.Invoke(() => message.ShowDialog());
}
else
{
message.ShowDialog();
}
However this is give the classic 'The calling thread cannot access this object because a different thread owns it' though I don't understand why as I am using the dispatcher for the TopWindow variable. As a note (and out of desperation) I tried putting the calls on the message variable I just created - that didn't work either but I didn't expect that to be the problem as how can I now own it if I have just made it!
Any advice would be greatly appreciated.
Try this:
if (UIUtilities.TopWindow != null)
{
UIUtilities.TopWindow.Dispatcher.Invoke(() =>
{
var message = new OptionalMessageBox(title, errorMessage.ToString(), MessageImage.Warning);
message.Owner = UIUtilities.TopWindow;
message.ShowDialog();
});
}
else
{
var message = new OptionalMessageBox(title, errorMessage.ToString(), MessageImage.Warning);
message.ShowDialog();
}
You can use this
App.Current.Dispatcher.Invoke(() => {
OptionalMessageBox message = new OptionalMessageBox(title, errorMessage.ToString(), MessageImage.Warning);
message.Owner = App.Current.MainWindow;
message.ShowDialog();
});
I don't really understand why the following code isn't working. I want iron-media-query to call a function when the query changes. I got it working using query-matches and template if's but that isn't what I want at all. Here is the code I have:
<iron-media-query
query="(max-width:1024px)"
query-matches="{{condensedscreen}}"
query-changed="switchToCondensed">
</iron-media-query>
I want the query-change="switchToCondensed" to be called once this query requirement is met.
The switchedToCondensed function is the following:
switchToCondensed: function(e) {
console.log("Condensed: "+this.condensedscreen);
if(this.condensedscreen === true) {
this.sectionbox = "section-boxes-condensed";
this.setScreenSize = "checkoutBodyMobile";
//this.sectionStyle = "sectionMobile";
this.shippingSectionStyle = "shippingSectionMobile";
this.allCardsStyle = "allCardsMobile";
this.submitBtnStyle = "submitBtnMobile";
this.gotocartStyle = "goToCartMobile";
}
else {
this.sectionbox = "section-boxes";
this.setScreenSize = "checkoutBody";
//this.sectionStyle = "section";
this.shippingSectionStyle = "shippingSection";
this.allCardsStyle = "allCards";
this.submitBtnStyle = "submitBtn";
this.gotocartStyle = "goToCart";
}
}
As you can see I want to use this to change around the CSS on my webpage. What exactly am I doing wrong here?
Did you try to use "on-query-matches-changed" instead of "query-changed"?
<iron-media-query
query="(max-width:1024px)"
query-matches="{{condensedscreen}}"
on-query-matches-changed="switchToCondensed">
</iron-media-query>
So I never got query-changed to work. Honestly that seems completely useless. Anyway, I got it to work by first adding the $ to my class like the following:
<div class$="[[allCardsStyle]]">
After that I removed the query-changed from iron-media-query so it looked like the following:
<iron-media-query
query="(max-width:1024px)"
query-matches="{{condensedscreen}}">
</iron-media-query>
Then back in the JS I added an observer to watch when the boolean variable changes:
condensedscreen:{observer:"switchToCondensed"}
Finally, with that watching the change I had it call my function "switchToCondensed" that actually set the variable to mobile vs not:
switchToCondensed: function() {
if(this.condensedscreen === true) {
this.allCardsStyle = "allCardsMobile";
}
else {
this.allCardsStyle = "allCards";
}
}
Then in my CSS I have two different styles that are call allCards and allCardsMobile.
Hopefully this helps someone that was struggling with this like me.