Testing a ReactiveVar in Meteor - testing

I am trying to test a event in a Template. Within the click event, there is a Reactive Var that gets set.
The test is blocked by the Reactive Var.
Any ideas on how I stub or mock a reactive var in a template? I tried adding it to the template (template.reactiveVar = "whatever"), but no go, as I don't think it's writeable.
The ?? indicate where I am wondering what to put.
it('sets a reactive var when a button is clicked', function(){
Template.button.fireEvent('click ', {
context: { some: 'values'},
event: {'target': {'text': 'randomText' } },
templateInstance:new Template('upload', function(e) {
this.reactiveVar = new ReactiveVar("not clicked)
})
});
chai.assert.equal(Template.reactiveVar, "clicked")});
// The actual template is below..
Template.button.events{(
'click button': function(evt, template){
var text = evt.target.text
template.reactiveVar.set(text)
}
});
The result is...
TypeError: Cannot read property 'set' of undefined
Any ideas?

I suspect the event is actually firing and getting through to your event handler before the callback that creates the reactive var has run.
You should create the reactive var when you first create the template independent of your test:
Template.button.onCreated(function(){
this.reactiveVar = new ReactiveVar("not clicked");
});

Related

vuejs2-ace-editor: accessing editor instance

I am using this Vue2 component for ACE editor:
https://github.com/chairuosen/vue2-ace-editor
This is how I add the component to my app
var app = new Vue({
el: '#vue_app',
data: {
message: 'Hello Vue!',
editor_content: 'somecontent'
},
methods:{
editorInit:function (el) {
require('brace/mode/json');
require('brace/theme/tomorrow');
}
},
components: {
editor:require('vue2-ace-editor')
}
});
And when I put this into my HTML everything works correctly:
<editor v-model="editor_content" #init="editorInit();" lang="json" theme="tomorrow" width="500" height="100"></editor>
However the editor renders with a gutter which I don't need, so I want to access the editor instance to tweak some properties.
The source code for this component says it emits an event on mount:
mounted: function () {
var vm = this;
var lang = this.lang||'text';
var theme = this.theme||'chrome';
require('brace/ext/emmet');
var editor = vm.editor = ace.edit(this.$el);
this.$emit('init',editor);
editor.$blockScrolling = Infinity;
editor.setOption("enableEmmet", true);
editor.getSession().setMode('ace/mode/'+lang);
editor.setTheme('ace/theme/'+theme);
editor.setValue(this.value,1);
editor.on('change',function () {
var content = editor.getValue();
vm.$emit('input',content);
vm.contentBackup = content;
});
}
How and where do I catch this event and access the editor object?
You are already listening to the init event and calling the editorInit method. However, you need to pass the data being emitted by the <editor> component.
You can either do that explicitly by using $event:
<editor v-model="editor_content" #init="editorInit($event)" ...></editor>
Or implicitly by simply providing the method name as the event handler:
<editor v-model="editor_content" #init="editorInit" ...></editor>
Then, in your editorInit method, the param being passed in will be the instance of the editor. And I believe you can specify to not render the gutter like so:
editorInit:function (editor) {
editor.renderer.setShowGutter(false)
require('brace/mode/json');
require('brace/theme/tomorrow');
}

Dojo enable button by event handler

I am working with IBM Content Navigator 2.0.3, that uses DOJO 1.8 for the GUI development. I am new in dojo, and I have to enhance one of the forms: add an event handler to the dataGrid so when the row of the grid is selected one of the buttons become enabled.
I've managed to add event handler as was advised in this issue: dojo datagrid event attach issue
but I still can't enable the button. Here is html of the form:
Add
Remove
<div class="selectedGridContainer" data-dojo-attach-point="_selectedDataGridContainer">
<div class="selectedGrid" data-dojo-attach-point="_selectedDataGrid" ></div>
</div>
The attached image describes how it looksenter image description here.enter image description here
And the js file code of postCreate function is following:
postCreate: function() {
this.inherited(arguments);
this.textDir = has("text-direction");
domClass.add(this._selectedDataGridContainer, "hasSorting");
this._renderSelectedGrid();
this.own(aspect.after(this.addUsersButton, "onClick", lang.hitch(this, function() {
var selectUserGroupDialog = new SelectUserGroupDialog({queryMode:"users", hasSorting:true, callback:lang.hitch(this, function (user) {
this._onComplete(user);
this._markDirty();
})});
selectUserGroupDialog.show(this.repository);
})));
this.own(aspect.after(this.removeUsersButton, "onClick", lang.hitch(this, function() {
if (this._selectedGrid != null) {
var selectedItems = this._selectedGrid.selection.getSelected();
if (selectedItems.length > 0) {
array.forEach(selectedItems, lang.hitch(this, function(item) {
this._selectedGrid.store.deleteItem(item);
}));
}
this._selectedGrid.selection.clear();
this._selectedGrid.update();
}
this._markDirty();
})));
// the following handler was added by me
dojo.connect(this.myGrid, 'onclick', dojo.hitch(this, function(){
console.log(" before ");
this.removeUsersButton.set('disabled', true);
console.log(" after ");
}));
},
so this.own(aspect.after(this.removeUsersButton..... works fine and worked before my interference. So it somehow accesses this.removeUsersButton and processes the event. But my handler dojo.connect(this.myGrid.... only prints console.log() before and after without enabling the Remove button. The Button has no Id, only data-dojo-attach-point. How do I enable the Remove button when the daaGrid is selected?
With this.removeUsersButton.set('disabled', true); you are setting the button to be disabled. If you want to enable it you need to set it to false.
this.removeUsersButton.set('disabled', false);

trying to derive from a dijit Button: "TypeError: this._attachEvents is undefined"

I am trying to derive an "extended" Button from dijit/Form/Button. (I want to pass extra arguments to the constructor, and I want to encapsulate these preparations in my derived class. Button is just an example, I want to use this later with grids and trees.)
Unfortunately the code below fails with "TypeError: this._attachEvents is undefined" in the firefox javascript console. Some idea, what is wrong? The same code, including minimal HTML, is ready to run at http://jsfiddle.net/x9dLs8gz/1/
require(["dojo/_base/declare", "dijit/form/Button", "dojo/dom", "dojo/json", "dojo/domReady!"],
function (declare, Button, dom, json) {
declare("MyButton", Button, {
"-chains-": {
constructor: "manual"
},
constructor: function () {
//extra calculation will go here...
this.inherited(arguments);
}
});
new MyButton({
label: "Click Me!",
onClick: function () {
dom.byId("result").innerHTML += "Success";
}
}, "button").startup();
});
Cheers,
Dominic
If the "-chains-" value for the constructor method is either not set or set to "after", then the postscript method will be called after all of the inherited constructors have been fired. On the other hand, when specifying "manual", postscript is fired after the first constructor (in this case MyButton#constructor) is executed. As a result, _AttachMixins#buildRendering is fired before this._attachEvents has been set in _AttachMixins#constructor, causing the error you see.
Since specifying "manual" means that no chaining is assumed whatsoever, mixin contructors will never be called, even if this.inherited is correctly called up the chain. This makes sense, as the underlying C3MRO is thrown out the window.
If you need to continue using the "manual" setting in spite of this, you will need to 1) recreate any missing data yourself, 2) manually call the mixin constructors (e.g., _AttachMixin.prototype.constructor.call(this)), or 3) convert MyButton to a factory for Button:
var createButton = (function () {
var myButtonDefaults = { ... };
return function (kwArgs, id) {
var buttonId = id || 'button';
return new Button(lang.mixin({}, myButtonDefaults, kwArgs), buttonId);
};
})();
var myButton = createButton();
myButton.startup();
console.log(myButton instanceof Button); // true
You need to assign the declared class to a variable or declare in a different file and added it to the list of object in the require. Also dont use variable names which are keywords like "constructor". below is the fixed version of your example.
require(["dojo/_base/declare", "dijit/form/Button", "dojo/dom", "dojo/json", "dojo/domReady!"],
function(declare, Button, dom, json) {
var MyButton = declare("MyButton", Button, {
"-chains-": {
constructorType: "manual"
},
constructor: function() {
//extra calculation will go here...
this.inherited(arguments);
}
});
new MyButton({
label: "Click Me!",
onClick: function() {
dom.byId("result1").innerHTML += "Success";
}
}, "button").startup();
});
<div id="button"></div>
<div id="result1"></div>

Adding a custom widget on call back method

i have a call back method which is called by other class when some event occurs, which send some objects as parameters
loadingIsDone : function(evt)
{
console.log(evt);
for(var i=0; i<evt.layers.length;i++)
{
var row = new _LayerRow(evt.layers[i].layer);
domConstruct.place(row.domNode,this.containerDiv,"last");
}
}
for each object which is received i need to create a Custom widget called _LayerRow, which is having one Checkbox and a Label
When i debug this code the pointer is not coming to the 2nd line of the loop.
and no error in the console..
but when i call the same in different file as below for testing purpose
var obj = new Object();
obj.id = "124";
obj.name = "Chiru";
var lay = new _LayerRow(obj);
domConstruct.place(lay.domNode,win.body(),1);
The _LayerRow widget is working fine
_LayerRow.js
define([
"dojo/_base/declare",
"dijit/_WidgetBase",
"dijit/_OnDijitClickMixin",
"dijit/_TemplatedMixin",
"dojo/text!../templates/_layerrow.html"
], function (declare, _WidgetBase, _OnDijitClickMixin,_TemplatedMixin, template) {
return declare([_WidgetBase,_OnDijitClickMixin, _TemplatedMixin], {
templateString: template,
layer : null,
constructor : function( layerObj)
{
this.id = layerObj.id;
this.layer = layerObj;
},
postCreate : function()
{
this.inherited(arguments);
this.layerName.innerHTML = this.layer.name;
}
});
});
and templates/_layerrow.html
<div>
<input type="checkbox" id="${id}">
<label for="${id}" data-dojo-attach-point="layerName"></label>
</div>
Any idea why its not working.. how can i find the issue in this
Most common reason for callbacks to fail is incorrect scope.
Because in asynchronous callbacks such as above, the context that the code is executing in has changed. It will no longer refer to the object that originally provided it, but its context will now refer to the enclosing object, the callback. To get around this, you can use hitch() to force the function to retain its original context
I see a reference to this in your callback, use hitch to correct the scope.
More info: http://dojotoolkit.org/reference-guide/1.9/dojo/_base/lang.html#hitch

Dojo Exception on hiding a dijit.Dialog

I have a Dialog with a form inside. The following code is just an example of what I'm trying to do. When you close a dijit.Dialog, if you dont't destroy recursively his children, you just can't reopen it (with the same id).
If you don't want to destroy your widget you can do something like that :
var createDialog = function(){
try{
// try to show the hidden dialog
var dlg = dijit.byId('yourDialogId');
dlg.show();
} catch (err) {
// create the dialog
var btnClose = new dijit.form.Button({
label:'Close',
onClick: function(){
dialog.hide();
}
}, document.createElement("button"));
var dialog = new dijit.Dialog({
id:'yourDialogId',
title:'yourTitle',
content:btnClose
});
dialog.show();
}
}
I hope this can help but with this code the error thrown is :
exception in animation handler for: onEnd (_base/fx.js:153)
Type Error: Cannot call method 'callback' of undefined (_base/fx.js:154)
I have to say I'm a little lost with this one ! It is driving me crazy ^^
PS : sorry for my "French" English ^^
I'll introduce you to your new best friend: dojo.hitch()
This allows you to bind your onClick function to the context in which it was created. Chances are, when you push the button in your code, it is calling your .show() .hide() form the context of the global window. var dlg was bound to your createDialog function, so it's insides are not visible to the global window, so the global window sees this as undefined.
Here's an example of what I changed to your code:
var createDialog = function(){
// try to show the hidden dialog
var dlg = dijit.byId('yourDialogId');
dlg.show();
// create the dialog
var btnClose = new dijit.form.Button({
label:'Close',
onClick: function(){
dojo.hitch(this, dlg.hide());
}
}, document.createElement("button"));
dlg.domNode.appendChild(btnClose.domNode);
var btnShow = new dijit.form.Button({
label : 'Open',
onClick : function() {
dojo.hitch(this, dlg.show());
}
}, document.createElement("Button"));
dojo.body().appendChild(btnShow.domNode);
};
dojo.ready(function() {
createDialog();
});
Note the use of dojo.hitch() to bind any future calls or clicks of the various buttons to the context in which the dlg was created, forever granting the button's onclick method access to the inside of the createDialog function, where var dlg exists.
hi if i understand correctly, you didn't need to destroy dijit.Dialog every time. E.g.:
HTML: define simple button:
<button id="buttonTwo" dojotype="dijit.form.Button" onclick="showDialog();" type="button">
Show me!
</button>
Javascript:
// required 'namespaces'
dojo.require("dijit.form.Button");
dojo.require("dijit.Dialog");
// creating dialog
var secondDlg;
dojo.addOnLoad(function () {
// define dialog content
var content = new dijit.form.Button({
label: 'close',
onClick: function () {
dijit.byId('formDialog').hide();
}
});
// create the dialog:
secondDlg = new dijit.Dialog({
id: 'formDialog',
title: "Programatic Dialog Creation",
style: "width: 300px",
content: content
});
});
function showDialog() {
secondDlg.show();
}
See Example and reed about dijit.dialog