I am testing an Ext JS frontend with Siesta.
Here is my login/logout test:
StartTest(function(t) {
t.diag("Login/Logout");
t.chain(
{ waitForCQ : '#loginPanel' },
function(next) {
t.cq1("#username").setValue();
t.cq1("#password").setValue();
next();
},
{ click: '>> #username' },
{ type: '******', target : '>> #username' },
{ type: '******', target : '>> #password' },
{ click: '>> #loginButton' },
{ waitForCQ: '#mainView' },
{ click: '>> #logoutButton' },
{ waitForCQ: 'messagebox #ok' },
function(next) {
t.waitForEvent(Ext.globalEvents, 'logoutComplete', function () {});
next();
},
{ click : '>> messagebox #ok' },
function() {
t.done();
}
);
});
The test inputs the username and password into the login panel, then clicks the login button. After the main view is loaded, it logs off.
For some reason, this test never finishes.
Every action in the chain is successful, but the test is still stuck running.
How can I fix this?
I am using siesta-3.0.2-lite with ExtJS 5.1.0.
1# First you can try to remove t.done() , it's not generally needed in the tests, unless you are really waiting for it. needDone in the harness settings has default value False.
2# You are using waitForEvent, this is usually done when you pass the callback there. So your function would look like this:
function(next) {
t.waitForEvent(Ext.globalEvents, 'logoutComplete', next);
},
But if you just want to know that the event was fired, you can use function firesOnce . Don't forget that you need to register checking the event before executing the actions which triggers it.
So your code could look like this:
function(next) {
t.firesOnce(Ext.globalEvents, 'logoutComplete','Logout completed!');
next();
},
{ click: '>> #logoutButton' },
{ waitForCQ: 'messagebox #ok' },
{ click : '>> messagebox #ok' },
But I have never used Ext.globalEvents to check the events, so I am not sure if it works.
Siesta developers on the forum suggested to solve this by setting overrideSetTimeout to false in your harness config.
Harness.configure({
...
overrideSetTimeout: false,
...
});
Siesta overrides the native "setTimeout" from the context of each test for asynchronous code tracking, but it seems to cause issues.
It worked for many users on the forum, tell me if it works for you, because it did not solve my issues.
Update:
The problem on my side turned out to be due to the logout itself, which uses window.location.reload(). This makes the browser act if there are two separate pages/applications.
Apparently, you need to set separateContext option in harness object to true. This option is available only in Standard (Commercial) package.
Related
I'm trying to override ajax timeout in a Documentum xCP application.
Ext.Ajax.setTimeout(120000) and Ext.override(Ext.data.proxy.Ajax, { timeout:120000 }) didn't help. Every time an instance of Ext.data.proxy.Ajax is created, it has timeout: 30000. Maybe it's reverted after my call, but I don't know how to check this.
With Ext.override I can create new properties in Ext.data.proxy.Ajax prototype, but existing properties don't change.
I debugging my app in Chrome and using the special parameter in app url to load the debug version of ext-all script.
upd:
If I call
Ext.override(Ext.data.proxy.Ajax, { timeout:120004 })`
just once, then
Ext.data.proxy.Ajax.prototype.getConfigurator().values["timeout"]==120004
Ext.data.proxy.Ajax.prototype.timeout==30000
The value 30000 is used in Ext.data.proxy.Ajax.doRequest().
If I call it again:
Ext.override(Ext.data.proxy.Ajax, { timeout:120005 })`
then
Ext.data.proxy.Ajax.prototype.getConfigurator().values["timeout"]==120004
Ext.data.proxy.Ajax.prototype.timeout==120005
I'm not familiar with Documentum xCP but on my web application using Ext.js (v.4.1), I used the following snippet to change general timeout:
Ext.onReady(function(){
Ext.Ajax.timeout = 150000;
});
Maybe the onReady event is the key.
If you want to override the proxy defaults, use:
Ext.define(null, {
override: 'Ext.data.proxy.Server',
config: {
timeout: 120000
}
});
If you want to override the proxy defaults. Put this class under app/overrides folder.
Ext.define('Ext.overrides.data.proxy.Proxy', {
override: 'Ext.data.proxy.Proxy',
timeout: 10000,
completeOperation: function(operation) {
try {
this.callParent(operation);
} catch (e) {
}
}
});
Or add your view model as give below
Ext.define('Model', {
extend: 'Ext.app.ViewModel',
alias: ..
stores: {
xstore: {
model: 'type'
proxy: {
type: 'ajax',
timeout: 90000, // increasing time.
url: url
}
}
}
});
I am trying to make sing post page a route where it does a several things using iron:router
Uses the template postPage
Subscribes to publication of singlePost, userStatus (shows status and info of Author of single post page'), comments .
Grabs Comments documents that has field of postId : this.params._id
Increments Comments List by Session.get('commentLimit')
Here is the code I currently have.
Router.js
Router.route('/posts/:_id', {
name: 'postPage',
subscriptions: function() {
return [
Meteor.subscribe('singlePost', this.params._id),
Meteor.subscribe('userStatus'),
Meteor.subscribe('comments', {
limit: Number(Session.get('commentLimit'))
})
];
},
data: function() {
return Posts.findOne({_id:this.params._id});
},
});
Publications.js
Meteor.publish('singlePost', function(id) {
check(id, String);
return Posts.find(id);
});
Meteor.publish('comments', function(options) {
check(options, {
limit: Number
});
return Comments.find({}, options);
});
Template.postPage.onCreated
Template.onCreated( function () {
Session.set('commentLimit', 4);
});
Template.postPage.helpers
Template.postPage.helpers({
comments: function () {
var commentCursor = Number(Session.get('commentLimit'));
return Comments.find({postId: this._id}, {limit: commentCursor});
},
});
Template.postPage.events
Template.postPage.events({
'click a.load-more-comments': function (event) {
event.preventDefault();
Session.set('commentLimit', Number(Session.get('commentLimit')) + 4)
}
});
Everything works fine, but I found one thing to be inconsistent.
Here is the problem I am having...
User goes into single post page and adds comment (everything works fine).
User goes into a different single post page and adds comment (everything works fine).
Here is where the problem begins
The user at any time, goes into another route that is not the single post page.
User goes back into single post page
The comments are not showing.
New comments will be added into DB but still wont show
This problem only goes away when meteor reset or manual deletion of all comments in MongoDB is performed.
Is there a better way that I can code my routing and related code to stop this weird behavior from happening?
Or even if there is a better practice.
Your publish is publishing comments without any postId filter.
Your helper, filters by postId. Maybe the 4 comments that get published are the ones that do not belong to the current post that is open?
Could you try updating, your subscription to
Meteor.subscribe('comments', {
postId: this.params._id
}, {
limit: Number(Session.get('commentLimit'))
})
and your publication to
Meteor.publish('comments', function(filter, options) {
check(filter, {
postId: String
});
check(options, {
limit: Number
});
return Comments.find(filter, options);
});
so that only the same posts' comments are published?
I have figured it out. I have updated the following codes.
So far it is not showing weird behavior...
Publications.js
Meteor.publish('comments', function(postId, limit) {
check(postId, String);
check(limit, Number);
return Comments.find({postId:postId}, {limit:limit});
});
Router.js
Router.route('/posts/:_id', {
name: 'postPage',
subscriptions: function () {
return [
Meteor.subscribe('singlePost', this.params._id),
Meteor.subscribe('userStatus'),
Meteor.subscribe('comments', this.params._id, Number(Session.get('commentLimit')))
];
},
data: function() {
return Posts.findOne({_id:this.params._id});
},
});
Parse.com with JavaScript SDK - unnecessary duplictions
Every time I create a Parse object of "message", it duplicates that object in my Parse Core. It is so bizarre. The first time I run the code, everything is fine and Parse will create only one object. But when I run the code again, it will duplicate the most recent object twice. If I run it a third time, it will duplicate the most recent object five times. The number of duplications increases based upon how many objects have already been created. Does anyone have any idea how to make sure that it create one object in my Parse Core backend? Thank you so much!!! I wish I could post a picture, but I am a newbie and stackoverflow wont let me
This is where I create the Parse object:
App.Models.Message = Parse.Object.extend({
className: 'Message',
idAttribute: 'objectId',
defaults: {
name : '',
email : '',
subject : '',
message : ''
}
});
This is where I create an instance of the Parse object, and where I save it to Parse:
App.Views.Contact = Parse.View.extend({
el : '#middle',
template : _.template($('#contactTemp').html()),
events: {
'click .submit' : 'submit',
},
initialize : function () {
this.render();
},
render : function () {
this.$el.html(this.template);
},
submit : function (e) {
e.preventDefault();
var message = new App.Models.Message({
name: $('.nameVal').val(),
email: $('.emailVal').val(),
subject: $('.subVal').val(),
message:$('.messVal').val(),
});
message.save(null, {
success:function() {
console.log("Success");
},
error:function(e) {
alert('There was an error in sending the message');
}
});
}
});
Yes! So I figured out the problem with the help of Hector Ramos from the Parse Developers Google group.
https://groups.google.com/forum/#!topic/parse-developers/2y-mI4TgpLc
It was my client-side code. Instead of creating an event attached to my App.Views.Contact(); a.k.a. - an instance of Parse.View.extend({}), I went ahead and created a 'click' event using jquery within the sendMessage function that I recently defined. If you declare an event in the events object within the Parse view, it will recur over itself if the view wasn't re-initialized or destroyed and recreated properly.
So what happened with me was the submit function that I declared in the events object kept recuring over itself and making duplicate calls to Parse.com. My view was static, it wasn't destroyed properly, re-initialized, or reloaded. You will see what I did below:
Originally I had this:
events: {
'click .submit' : 'submit',
},
& this
submit : function (e) {
e.preventDefault();
var message = new App.Models.Message({
name: $('.nameVal').val(),
email: $('.emailVal').val(),
subject: $('.subVal').val(),
message:$('.messVal').val(),
});
message.save(null, {
success:function() {
console.log("Success");
},
error:function(e) {
alert('There was an error in sending the message');
}
});
} /*end of submit*/
Now I have I completely removed the events object that I had and declared a sendMessage function:
initialize : function () {
this.render();
},
render : function () {
this.$el.html(this.template);
this.sendMessage();
},
sendMessage : function () {
$('.submit').on('click', function(){
var message = new App.Models.Message({
name: $('.nameVal').val(),
email: $('.emailVal').val(),
subject: $('.subVal').val(),
message:$('.messVal').val(),
});
message.save(null, {
success:function() {
console.log("Success");
},
error:function() {
alert('There was an error in sending the message');
}
});
}); /*end of jquery submit*/
}/*end of send message function*/,
And now it works perfectly fine. Credit is due Hector Ramos who is a Parse.com Developer and who helped me realize that the problem was the actual event. If you guys have any easy way of stoping an event from making several duplicate calls to the back or from reoccurring several times, then please let me know.
I have a search bar docked onto my tree panel. When I write something and press enter an Ajax request fires off and returns the folder ids required to expand the tree up to the point of the folder requested. Inside the success config of the ajax.request I call the expand function of each node via getNodeById using a loop. However after the first expansion ExtJS fires itself an ajax request from the proxy to fetch the folder data (since it hasn't been loaded yet). Since AJAX is asynchronous the loop is faster than the server response and it tries to call the .expand() function of the node before the node itself has been loaded and gives an undefined error. How should I tackle this? I know that generally with AJAX you have to use callback functions for everything you want to run AFTER the request has been processed but I'm not really sure how to do this in this case...
Ext.define('treeStore',
{
extend : 'Ext.data.TreeStore',
alias: 'widget.treeStore',
autoLoad : false,
model : 'treeModel',
root : {
id: 0,
name : 'Root',
expanded : true,
loaded: true
},
proxy : {
type : 'ajax',
url : 'MyServlet',
reader : {
type : 'json',
root : 'children'
}
},
folderSort: true
});
Ext.define('Ext.tree.Panel',{
.
.
.
//Stuff about the tree panel etc.
dockedItems: {
xtype: 'textfield',
name: 'Search',
allowBlank: true,
enableKeys: true,
listeners: {
specialkey: function (txtField, e) {
if (e.getKey() == e.ENTER){
var searchValue = txtField.getValue();
Ext.Ajax.request({
url: 'MyServlet',
params: {
caseType: 'search',
value: searchValue
},
success: function(response) { //ATTENTION: When calling the .expand() the AJAX hasn't finished and cannot find the node.
response = Ext.decode(response.responseText);
var panel = txtField.up();
response.IDs.forEach(function(entry){
panel.getStore().getNodeById(entry.folderId).expand(); <-problem here
});
}
});
}
}
}
}
Often when writing my Ext apps, I find that even though things should fire in order, there are times where calling things immediately after an AJAX call is sometimes just too fast. Maybe the tree nodes have not rendered properly yet, or some other issue.
Try wrapping a delayed task around that code:
new Ext.util.DelayedTask(function()
{
response = Ext.decode(response.responseText);
var panel = txtField.up();
response.IDs.forEach(function(entry){
panel.getStore().getNodeById(entry.folderId).expand(); <-problem here
});
}, this).delay(100);
You'll have to work around those scope issues though. The "this" just before the delay function is your scope.
Im new to meteor and have been trying to learn the framework via the discover meteor book. Im having a few issue understanding what exactly is going on in my application (found here https://github.com/Themitchell/Sound-wav.es).
Essentially, my understanding is that on my server side I allow publications for certain collections which take arguments from my client side subscribe calls. For this part on my server i have this in my server/publications.js file:
Meteor.publish('studios', function (options) {
return Studios.find({
userId: this.userId
}, options);
});
Meteor.publish('studio', function (id) {
return id && Studios.find({
userId: this.userId,
_id: id
});
});
Next we would need a controller to handle the routing and deal with waiting for any subscriptions required, then, once the subscriptions are ready (hence the waitOn) go and render the template providing the data function as a reactive data source for the templates.
So I then set up my 2 routes for indexing studios and showing one studio using iron router and 'Controllers' as follows:
StudiosIndexController = RouteController.extend({
template: 'studiosIndex',
increment: 20,
limit: function () {
return parseInt(this.params.studiosLimit) || this.increment;
},
findOptions: function () {
return {
sort: this.sort,
limit: this.limit()
};
},
waitOn: function () {
return Meteor.subscribe('studios', this.findOptions());
},
studios: function () {
return Studios.find({}, this.findOptions());
},
data: function () {
return {
studios: this.studios()
};
}
});
ShowStudioController = RouteController.extend({
template: 'showStudio',
waitOn: function () {
return Meteor.subscribe('studio', this.params._id);
},
studio: function () {
return Studios.findOne(this.params._id);
},
data: function () {
return {
studio: this.studio()
};
}
});
Router.map(function () {
this.route('studiosIndex', {
path: '/',
controller: StudiosIndexController
});
this.route('showStudio', {
path: '/studios/:_id',
controller: ShowStudioController
});
});
Now this is great and works fine when displaying my index page. I get a list of collections which is reactive and the as i introduce new studios to the collection i see them get created on the server and on the client respectively. However in my show view when the view is rendered the data always seems to be empty. On dropping into my show controller's data function with a debugger I tried querying the Studios and this always returns undefined even when i try to fetch everything possible. Oddly I know that my publications are logging the correct id for a studio (using console.log). It seems that i get all the correct data up until the routing on the client side. The parameter ids are all correct but a find() call on studios always returns nothing. Am I missing something obvious here.
Its also worth noting i deleted my helpers for 'studios' and 'studio' in views/studios/index.js and views/studios/show.js respectively as my understanding is that this is what im doing with studios and studio in the controller. These helpers are now defined at the controller level and passsed to the reactive 'data' function. IS this correct?
TL;DR
With the code above my index action works however my show action fails where the data function always returns undefined and in fact on the show page i cannot get access to any of my studio information (Studios.find({}).count() always returns 0). I'm unsure how the 2 routes differ. Can anyone spot the issue?
Edit: Its also worth noting having looked through some of the iron router issues on github i have tried using this.ready(). The first time the route is run i hit data and this is false but then even wrapping my data helpers to wait for this.ready() gets an undefined return value when this.ready() returns true.
Extra Notes
Im running meteor 0.8.0 with latest 0.7.0 release of iron router and collection2 with simple schema, just in case you are interested / require this info.
EDIT: Possible solution
So having fiddled around it seems like my helpers are the issue. By using the 'studio' section and then calling this.studio() inside my data function this seems to break. If I change the code below:
ShowStudioController = RouteController.extend({
template: 'showStudio',
waitOn: function () {
return Meteor.subscribe('studio', this.params._id);
},
studio: function () {
return Studios.findOne(this.params._id);
},
data: function () {
return {
studio: this.studio()
};
}
});
to this
ShowStudioController = RouteController.extend({
template: 'showStudio',
waitOn: function () {
return Meteor.subscribe('studio', this.params._id);
},
data: function () {
return Studios.findOne(this.params._id);
}
});
My view renders correctly again. Im unsure where i saw this pattern however I had assumed the function assigned to 'studio' was essentially the same as doing
Template.showStudio.helpers({
studio: function () {
return Studios.findOne(this.params._id)
}
});
but it seems not!