Can I get the textarea caret position in unit test with Jasmine? - unit-testing

I am trying to implement '# Users Feature' with angularjs, I almost finish the feature except writing an unit test. I have a Caret module which can help me get the caret position in textarea.
I think the most important thing is to get the caret position but I dont know how to do it in jasmine.
Mydirective
.directive('atUser', function (Caret) {
return {
restrict: 'A',
link: function (scope, element) {
element.bind('focus click keydown', function () {
scope.caretPos = Caret.getPos(element);
});
scope.$watch(function () {
return scope.caretPos;
}, function (nowCaretPos) {
/* do something here */
})
}
}
})
Html
<textarea ng-model="message" at-user></textarea>
Jasmine
describe('test at user', function () {
/* some init code */
it('should get caret postion', function () {
textarea = element.find('textarea');
textarea.triggerHandler('focus');
except(textarea.scope().caretPos).toEqual(0);
/*
* then i want to simulate keydown event and type something
* and get the caret postion
* but i dont know how to do it
* /
})
})
One more thing is I dont want to use jquery.
Can anyone help me?
thanks a lot!

I just asked a similar question where I needed to set the caret position of a textarea in a Jasmine test, and I got an answer that worked (using selectionStart on programmatically-created inputs), so here is a potential solution that you can implement with Jasmine:
describe('test at user', function () {
/* some init code */
it('should get caret postion', function () {
textarea = element.find('textarea');
textarea.triggerHandler('focus');
expect(textarea.scope().caretPos).toEqual(0);
/*
* then i want to simulate keydown event and type something
* and get the caret postion
* but i dont know how to do it
*/
document.body.appendChild(textarea[0]); // I discovered this to be the key to using the .selectionStart property successfully
textarea.val('some text');
textarea[0].selectionStart = 9; // you need to move the caret manually when doing things programmatically
textarea.triggerHandler('focus');
expect(textarea.scope().caretPos).toEqual(9);
})
})

Related

Is Qml able to receive a list of models and let listview to choose which one to use?

I have got one listview in qml now known as listview1. For each element in listview1, it contains another listview used to show some of its variables. Now I want to make it possible for all such sub-listviews able to add items to them. And also adding item to one of them will not affect all the other listviews in other elements of listview1.
What is the best way to solve such problem? Thanks
Adapted from https://stackoverflow.com/a/55604525/1493608 (same thing but with a GridView instead of a ListView) :
Give each sub-ListView a UUID.
Connect each sub-ListView to a listview1 signal that you will use to broadcast to sub-ListView delegates what you will want to do.
In this signal, put your UUID.
In sub-ListView receivers, put a filter on the UUID and do what you want to do only if it is the right one.
ListView {
id: listview1
signal broadcaster(string uuid, var other_args)
delegate: ListView {
// Provided like this or as a role from the corresponding list element
property string uuid: ""
signal sendToOtherLV(string uuid, var other_args)
function lv_receiver(broadcasted_uuid, other_args) {
if (this.uuid === broadcasted_uuid) {
// Do what you have to do with other_args.
}
}
Component.onCompleted: {
/*
* Custom way to generate the UUID and store it so
* the other ListViews will be able to retrieve it.
*/
this.uuid = generateAndStoreUUID()
// Connecting the sub-ListView to your "sub-ListView LAN".
this.sendToOtherLV.connect(listview1.broadcaster)
listview1.broadcaster.connect(this.lv_receiver)
}
Component.onDestruction: {
// Disconnecting the sub-ListView from your "sub-ListView LAN".
this.sendToOtherLV.disconnect(listview1.broadcaster)
listview1.broadcaster.disconnect(this.lv_receiver)
}
// Here is an example of what you might have to do
function foo() {
// ...
var otherlv_receiver_uuid
var signal_args
// Retreive the UUID of the ListView that you want to send something to.
// Set the other arguments you want to send through the signal.
this.sendToOtherLV(otherlv_receiver_uuid, signal_args)
// ...
}
// Other sub-ListView-related stuff
}
// Other listview1-related stuff
}

ionic 2 timer causes crash in app class

I am in an ionic 2 MyApp class, and I want to show one screen for 3 seconds then switch to another.
I get a this.nav.parent is null error.
I am trying two types of timers and neither work.
I am using tabs, and want it to go to the first tab page by the way.
gotoFirstPage()
{
//these two lines work fine
//this.nav.setRoot( TabsPage );
//this.nav.parent.select(1); //this.nav.parent is not null here
setTimeout((function()
{
this.nav.setRoot( TabsPage );
this.nav.parent.select(1); //this.nav.parent is null
}.bind(this)),3000);
let timer = Observable.timer(3000, 86400000);
timer.subscribe(t => {
this.nav.setRoot( TabsPage );
this.nav.parent.select(1); //this.nav.parent is null
});
}
I recommend to use a fat-arrow =>instead of binding this:
setTimeout(() =>
{
this.nav.setRoot( TabsPage );
this.nav.parent.select(1); //this.nav.parent is null
},3000);
If that doesn't work, then your nav object in this is null, so the problem is not the timer.
I have no idea why this.nav.parent is null but I found a better way to switch tab pages:
this.nav.setRoot( TabsPage, { tabIndex: 1 } );

Angular2 unit test Click() with keypress

I am trying to test a sorting function for a table. The table enables sorting on a primaray and secondary value. The secondary sorting value is set by holding down the shift key.
Code for setting the sort order:
private sortClick(event: any, column: DataGridColumn): void {
if (!column.sortable) {
return;
}
if (event.shiftKey) { // When the shift key is pressed, secondary sorting is being set.
if (column.headerText === this.primarySorting.headerText) {
return;
}
this.secondarySortingColumn.setSortingProperty(column.headerText, column.name);
} else {
this.primarySorting.setSortingProperty(column.headerText, column.name);
this.secondarySortingColumn.clear();
}
this.sortData(this);
}
Now I'm writing the unit testst for the function.
The primary sorting is done using the following:
let firstColumn: NodeListOf<HTMLElement> = <NodeListOf<HTMLElement>>compiled.querySelectorAll("#header0");
firstColumn.item(0).click();
How can I call the .click() function with shift key pressed in the unit test
You can use the dispaatchEvent method to invoke the click event and supply other event information as follows:
var event = new MouseEvent('click', {
'view': window,
'bubbles': true,
'shiftKey': true
});
let firstColumn: NodeListOf<HTMLElement> = <NodeListOf<HTMLElement>>compiled.querySelectorAll("#header0");
firstColumn.item(0).dispatchEvent(event);
Note the shiftKey member is set to true in the mouseEventInit dictionary parameter to the MouseEvent constructor which allows us to specify that the shiftKey is pressed.

unable to call external typescript function from phaser events in Ionic2

I am working on Ionic2 + Phaserjs.
I have created the Phaser canvas and load sprite in it. Now I want to add drag event on sprite and call a typescript function in that drag event. But my problem is that Phaser reserve the 'this' keyword for its own scope so I cant call the external typescript function like this.sayHello().
create() { // this is Phaser.create function
//console.log(vv)
this.counter = 0;
this.game.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL;
this.game.stage.backgroundColor = "#4488AA";
console.log("hellow");
this.logo = this.game.add.sprite(this.game.world.centerX, this.game.world.centerY, 'logo');
this.logo.anchor.setTo(0.5, 0.5);
this.logo.scale.setTo(.5);
this.logo.inputEnabled = true;
this.logo.input.enableDrag();
// this.logo.events.onDragStart.add(this.openHyperlink(), this);
}
this.openHyperlink = function(){
console.log(this.mainApp)
}
When you declare your typescript function use the arrow notation
example :
sayHello = () => { console.log('Hi');
this.something(); //here this is the original this object
};
As the arrow notation with TypeScript keeps the original this object

Passing parameters in Ember's Custom Events (that bubble through the View hierarchy)?

I couldn't find a way to pass arguments when using Ember's Custom Events which I found here.
I prefer avoiding solutions which target "parent" views specifically, such as this one since we lose the "bubbling".
My Usage is as following
plugins.js
Em.Object.reopen({
triggerEvent: function (eventName) {
this.$().trigger(eventName, this);
}
});
MyView.js
click: function () {
this.triggerEvent('stepClicked');
}
The code in Ember (0.96+) shows that passing an additional params is considered a manager, which isn't passed on
rootElement.delegate('.ember-view', event + '.ember', function(evt, triggeringManager) {
...
if (manager && manager !== triggeringManager) {
result = self._dispatchEvent(manager, evt, eventName, view);
} else if (view) {
result = self._bubbleEvent(view,evt,eventName);
}
Super thanks in advance,
Oren Rubin
You can pass an event object which will tell you what element is being clicked on:
click: function(event){
// will be called when when an instance's
// rendered element is clicked
console.log("element clicked: " + this.get('elementId') );
return false; // return true if you want the click event to bubble up to parent view (default it true)
}
I think an even better way would be to use {{action}} in your template. Take a look at this answer for an example.