Is there a shorter way to mock an object in jasmine? - unit-testing

I have an angular filter function that relies on a $window function that has a very big namespace:
.filter('dbNonUtcToDate', function ($window) { //for fields like birthdate in EmployeeData which are not UTC
return function (val, defaultVal) {
if (val !== null) {
var mdate = $window.moment($.jsonDateToDate(val)).format($window.Fr.Alpha.Rep.Web.context.dateFormat().toUpperCase());
var nullMDate = $window.moment([1, 0, 1]).format($window.Fr.Alpha.Rep.Web.context.dateFormat().toUpperCase());
if (mdate !== nullMDate) {
return mdate;
}
}
return defaultVal !== undefined ? defaultVal : '';
};
})
Is there a way to mock the $window.Fr.Alpha.Rep.Web.context.dateFormat() without doing something like:
beforeEach(module(function ($provide) {
var fakeWindow = {
Fr:
{
Alpha:
{
Rep:
{
Web:
{
context:
{
dateFormat: function () {
return ...;
}
}
}
}
}
}
}
$provide.value('$window', fakeWindow);
}));

Related

(Apollo client v3) useLazyQuery custom hook testing

I was struggling with a test issue for my custom useLazyQuery hook. My first test is passing but the second one is failing. What am doing wrong for the second test?
Here is the useLazyFetchCoin.tsx
export const useLazyFetchCoin = () => {
const [coins, setCoins] = useState<ICoin[]>([]);
useEffect(() => {
const coins = localStorage.getItem('coinsInfo');
if (coins) {
setCoins(JSON.parse(coins));
}
}, []);
const [getData, { loading, error }] = useLazyQuery(GET_COIN_PRICE_QUERY, {
fetchPolicy: 'network-only',
notifyOnNetworkStatusChange: true,
onCompleted: (data) => {
const hasSameCoin = coins.some((f) => f.id === data.markets[0]?.id);
if (data.markets.length && !hasSameCoin) {
const allCoins = [...coins, data.markets[0]];
setCoins(allCoins);
localStorage.setItem('coinsInfo', JSON.stringify(allCoins));
} else if (data.markets.length <= 0) {
alertNotification('Coin not found !', Notification.ERROR);
}
if (hasSameCoin) {
alertNotification('This coin already exists on your list !', Notification.WARNING);
}
}
});
return { coins, setCoins, getData, loading, error };
};
Here is the test file
describe('useLazyFetchCoin custom hook', () => {
const QueryMock = [
{
request: {
query: GET_COIN_PRICE_QUERY,
variables: { code: 'BNB' }
},
result: {
data: {
markets: [
{
id: 'binance_bnb_eur',
baseSymbol: 'BNB',
ticker: {
lastPrice: '414.90000000'
}
}
]
}
}
}
];
const QueryWrongCodeMock = [
{
request: {
query: GET_COIN_PRICE_QUERY,
variables: { code: 'asd' }
},
result: {
data: {
markets: []
}
}
}
];
function getHookWrapper(mocks: any, code: string) {
const wrapper = ({ children }: any) => (
<MockedProvider mocks={mocks} addTypename={false}>
{children}
</MockedProvider>
);
const { result, waitForNextUpdate } = renderHook(() => useLazyFetchCoin(), {
wrapper
});
expect(typeof result.current.coins).toBe('object');
expect(result.current.loading).toBeFalsy();
expect(result.current.error).toBeUndefined();
// call the lazy function
act(() => {
result.current.getData({
variables: { code }
});
});
return { result, waitForNextUpdate };
}
it('should return an array of coins', async () => {
// Working correctly
const { result, waitForNextUpdate } = getHookWrapper(QueryMock, 'BNB');
await waitForNextUpdate();
expect(result.current.loading).toBeFalsy();
expect(result.current.coins[0]).toEqual({
id: 'binance_bnb_eur',
baseSymbol: 'BNB',
ticker: {
lastPrice: '414.90000000'
}
});
});
it('should return an empty array when requesting a wrong code', async () => {
// Not working
const { result, waitForNextUpdate } = getHookWrapper(QueryWrongCodeMock, 'asd');
await waitForNextUpdate();
expect(result.current.loading).toBeFalsy();
expect(result.current.coins[0]).toEqual([]);
});
});
I got this error message for the second test.
Expected: []
Received: {"baseSymbol": "BNB", "id": "binance_bnb_eur", "ticker": {"lastPrice": "414.90000000"}}
I don't get it because I'm using different queries for each test.
Also, the second test should receive an empty array when you pass a wrong code such as 'asd'.
How can write a proper test for it?
I fixed the problem. When I was changing the order test, It worked correctly.
I added a clear mock function for it.
clear mock

I am attempting to upgrade from ember 1.7 to 1.13

I am trying to upgrade from an ancient version of ember 1.7 to the still ancient 1.13 and I am getting .js errors. I am not well versed with ember, to begin with, so all the help I can get will be appreciated.
I changed all instances of the code where it was using Ember.View.extend to Ember.Controller.extend
and since then, I am getting an error
Cannot read property 'noSignedUpAppts' of undefined.
Appt.Ember.js
function initEmberApp() {
Ember.Handlebars.registerBoundHelper('stringFormat', function (g11nString, str) {
return new Handlebars.SafeString(stringUtil.format(g11nString, str));
});
ApptApp = Ember.Application.create({
rootElement: "#appointmentWrapper"
});
ApptApp.Router.map(function () {
this.route("main", { path: '/' });
this.route("mainParam", { path: "/:val" });
this.route('mainId', { path: '/mainId/:appt_id' });
this.route('mainDirect', { path: '/mainDirect/:appt_id' });
this.route("schedule");
this.resource('userSchedule', { path: '/schedule/:user_id' });
this.route('scheduleId', { path: '/scheduleId/:appt_id' });
this.route('userScheduleId', { path: '/userScheduleId/:ids' });
this.route('scheduleSpecific');
this.route('scheduleSpecificId',{path: '/scheduleSpecificId/:appt_id'});
this.route('scheduleDate', { path: '/scheduleDate/:date' });
this.route('scheduleResource', { path: '/scheduleResource/:resource_id' });
this.route("settings");
this.route("campus");
this.route("noAccess");
});
ApptApp.history = {name:'',view:'',param:null, isSchedule:false}
initViews();
}
function initViews() {
initMain(ApptApp);
initSchedule(ApptApp);
initSettings(ApptApp);
initCampus(ApptApp);
initNoAccess(ApptApp);
}
ApptMain.js
function initMain(ApptApp) {
ApptApp.MainController = Ember.Controller.extend({
g11n: apptPortlet.g11n,
ableToEdit: apptPortlet.ableToEdit,
canManageSettings: apptPortlet.canManageSettings,
canAdmin: apptPortlet.canAdmin,
defaultDate: '',
showMySchedule: false,
apptId: '',
isDirect: false
});
ApptApp.MainParamRoute = Ember.Route.extend({
model: function (param) {
var date = moment(param.val.replace(/-/g, '/'));
return { defaultDate: (date.isValid() ? date.format('MM/DD/YYYY') : ''), showMySchedule: (param.val == 'myS') };
},
setupController: function (controller, model) {
this.controllerFor('main').set('defaultDate', model.defaultDate).set('showMySchedule', model.showMySchedule).set('apptId', '').set('isDirect',false);
},
renderTemplate: function () {
this.render('main');
}
});
ApptApp.MainIdRoute = Ember.Route.extend({
model: function (param) {
var items = param.appt_id.split('|');
var date = moment(items[1].replace(/-/g, '/'));
return { apptId: items[0], defaultDate: (date.isValid() ? date.format('MM/DD/YYYY') : '') };
},
setupController: function (controller, model) {
this.controllerFor('main').set('defaultDate', model.defaultDate).set('showMySchedule', false).set('apptId', model.apptId.toLowerCase()).set('isDirect', false);
},
renderTemplate: function () {
this.render('main');
}
});
ApptApp.MainDirectRoute = Ember.Route.extend({
model: function (param) {
var items = param.appt_id.split('|');
var date = moment(items[1].replace(/-/g, '/'));
return { apptId: items[0], defaultDate: (date.isValid() ? date.format('MM/DD/YYYY') : '') };
},
setupController: function (controller, model) {
this.controllerFor('main').set('defaultDate', model.defaultDate).set('showMySchedule', apptPortlet.apptSetting != 0).set('apptId', model.apptId.toLowerCase()).set('isDirect', true);
},
renderTemplate: function () {
this.render('main');
}
});
ApptApp.MainView = Ember.Component.extend({
didInsertElement: function() {
var controller = this.get('controller');
if (this.processRedirect(controller))
return;
this.renderView(controller);
},
renderView: function (controller, isRerender) {
if (isRerender) {
apptFullCal.destroy();
}
var g11n = controller.g11n;
apptFullCal.init({
data: {},
defaultDate: controller.defaultDate,
showMonth: true,
showWeekNav: true,
allowEditing: false,
calElem: $("#myCalendar"),
showWknd: apptPortlet.showWeekends,
updateWknd: apptPortlet.updateSettings,
g11n: controller.g11n,
listViewPageSize: apptPortlet.listViewPageSize,
noApptMesg: controller.g11n.noSignedUpAppts,
rerender: function () {
apptFullCal.reload();
$("#myNotifications").apptNotification('render');
},
editEvent: function(appt, isClick, revertFunc, rerenderAction) {
var resource = {};
if (appt.resourceId != '' && appt.resourceEdit)
resource = apptPortlet.getResource(appt.resourceId);
$.apptDetails({ controller: controller, appointment: appt, g11n: controller.g11n, resource: resource, canAddAttendees: apptPortlet.canAddAttendees, rerender: function () { rerenderAction(); $("#myNotifications").apptNotification('render'); } });
},
readonlySources: function (viewName) { return viewName == 'month' ? [{ url: 'rpc/appointmentsinfo/getcalendaraggregate' }] : [{ url: 'api/calendarevents?fullCalendar=true&filter=conflictable' }]; },
postApptRender: function (appt, elem, view) {
if (appt.isReadOnly) return;
var item = elem.find('.fc-content');
item.html(appt.isOwner ? appt.attendeeInfo : (appt.resourceId != '' ? appt.resourceName : appt.owner));
if (view.name != 'month') {
item.append($("<span class='fc-cus-event-info'>").html(appt.title));
}
if (appt.id == controller.apptId) {
controller.apptId = '';
apptFullCal.triggerClick(appt);
}
if (appt.newCommentCount > 0) {
var ctr = view.name == 'list' ? elem : item;
var comTxt = $("<span class='fc-comment'>").append($("<i class='fa fa-comment'/>")).append(view.name == 'list' ? stringUtil.format((appt.newCommentCount == 1 ? controller.g11n.newComment : controller.g11n.newComments), appt.newCommentCount) : '');
ctr.prepend(comTxt);
}
},
changeView: function(viewName) {
if (viewName == 'list')
$(".apptKeyInfo.otherEvents").hide();
else
$(".apptKeyInfo.otherEvents").show();
if (viewName == 'month')
$(".apptKeyInfo.otherEvents").removeClass("inactiveItem");
else
$(".apptKeyInfo.otherEvents").addClass("inactiveItem");
bindHelpText(g11n, viewName == 'list' ? '2' : (viewName == 'month' ? 0 : 1));
}
}, 'month');
bindHelpText(g11n, 0);
$("#myNotifications").apptNotification({
g11n: apptPortlet.g11n,
baseUrl: apptPortlet.baseUrl,
renderFullTxt: true,
callback: function(apptInfo) {
var date = moment(apptInfo.start);
if ((date.weekday() == 0 || date.weekday() == 6) && apptPortlet.showWeekends == false)
apptFullCal.showWeekends($("#myCalendar"), true, date);
controller.set('apptId', apptInfo.id);
apptFullCal.gotToDate('agendaDay', date);
}
});
$("#peopleChooser").peopleChooser({
peopleSource: 'rpc/appointmentsInfo/GetUserSearch',
watermark: controller.g11n.watermark,
onSelect: function(person) {
if (person.isResource)
controller.transitionTo('scheduleResource', person.id);
else
controller.transitionTo('userSchedule', { id: person.id, imgUrl: person.imgUrl, name: { full: person.fullName } });
}
});
if (controller.canManageSettings || controller.canAdmin)
$(".permissionAction").click(function() { ApptApp.history = { name: '', view: 'main', isSchedule: false }; });
var schLinkAction = this.bindScheduleLink;
$(".permHosts").hide();
if (apptPortlet.canManageSettings && (apptPortlet.apptSetting == 2 || (apptPortlet.apptSetting == 3 && apptPortlet.resourceId.length > 0))) {
var resource = apptPortlet.apptSetting == 2 ? null : apptPortlet.getResource(apptPortlet.resourceId);
if (apptPortlet.apptSetting == 2 || (resource != null && resource.canEdit)) {
$(".permHosts").show().find('a').html("<i class='fa fa-group'></i>" + (apptPortlet.apptSetting == 2 ? g11n.apptHosts : g11n.managersAndHosts))
.unbind('click').click(function(e) {
e.preventDefault();
$.apptManageHosts({
g11n: controller.g11n,
resource: resource,
isResource: resource != null,
portletId: apptPortlet.portletId,
onSave: function(res) {
if (apptPortlet.apptSetting == 2) {
apptPortlet.hosts = res;
schLinkAction(controller);
} else {
apptPortlet.hosts = res.hosts;
}
}});
});
}
}
if (controller.showMySchedule) {
$(".mySchedule").hide();
this.bindResourceInfo(controller);
} else {
$(".mySchedule").show();
}
this.bindSidebar(controller);
},
bindSidebar: function(controller) {
var campus = $(".campusWrapper").hide();
var myfac = $(".myFacWrapper").hide();
$.get('rpc/appointmentsinfo/getsidebarinfo/', function (sidebarInfo) {
if (sidebarInfo == null) return;
if (sidebarInfo.campusResources != null) {
var ul = campus.find('#campusResources').empty();
for (var key in sidebarInfo.campusResources) {
ul.append($("<li>").append($("<a href='#' class='activeItem apptStrong'>").data('id', key).html(sidebarInfo.campusResources[key]).click(function (e) { e.preventDefault(); controller.transitionTo('scheduleResource', $(this).data('id')); })));
}
if (ul.find('li').length > 0)
campus.show();
}
if (sidebarInfo.currentFaculty != null && sidebarInfo.currentFaculty.length > 0) {
myfac.show();
var container = myfac.find(".myFacUsers").empty();
$.each(sidebarInfo.currentFaculty, function (i, fac) {
var div = $("<div class='myFac'>");
div.append($("<a class='activeItem apptStrong'>").html(fac.name).click(function (e) { e.preventDefault(); controller.transitionTo('userSchedule', { id: fac.id, imgUrl: fac.imgUrl, name: { full: fac.name } }); }));
if (!fac.hasAvailAppts)
div.append($("<span class='pc-details'>").html(controller.g11n.noAppt));
$.each(fac.sections, function (j, sec) {
div.append($("<div class='inactiveItem itemInfo'>").html(sec));
});
container.append(div);
});
}
});
},
processRedirect: function (controller) {
if (apptPortlet.name == null) {
controller.transitionTo("noAccess");
return true;
}
if (controller.isDirect) return false;
var date = controller.defaultDate != null && controller.defaultDate != '' ? moment(controller.defaultDate).format('MM-DD-YYYY') : null;
if ((apptPortlet.resourceId != '' || apptPortlet.apptSetting == 2) && !controller.showMySchedule) {
var url = apptPortlet.apptSetting == 2 ? 'scheduleSpecific' : 'schedule';
if (controller.apptId != '' || date != null) {
controller.transitionTo(url + "Id", (controller.apptId + '|' + date));
}
else
controller.transitionTo(url);
return true;
}
else if (apptPortlet.apptSetting == 1 && !controller.showMySchedule && apptPortlet.hosts != null && apptPortlet.hosts.length > 0) {
var host = apptPortlet.hosts[0];
if (controller.apptId != '' || date != null) {
controller.transitionTo('userScheduleId', host.id + '_' + ((controller.apptId == '' ? ' ' : controller.apptId) + '|' + date));
}
else
controller.transitionTo('userSchedule', { id: host.id, imgUrl: host.imgUrl, name: { full: host.name } });
return true;
}
return false;
},
bindScheduleLink: function (controller) {
var showLink = false;
if (apptPortlet.resourceId != '') {
var resource = apptPortlet.getResource(apptPortlet.resourceId);
$(".scheduleLink").html(stringUtil.format(controller.g11n.bckToSchedule, resource.name)).unbind('click').click(function (e) { e.preventDefault(); controller.transitionTo('schedule'); });
showLink = true;
}
else if (apptPortlet.apptSetting == 1) {
var host = apptPortlet.hosts[0];
$(".scheduleLink").html(stringUtil.format(controller.g11n.bckToSchedule, host.name)).unbind('click').click(function (e) { e.preventDefault(); controller.transitionTo('userSchedule', { id: host.id, imgUrl: host.imgUrl, name: { full: host.name } }); });
showLink = true;
}
else if (apptPortlet.apptSetting == 2) {
var names = '';
var userCount = apptPortlet.hosts.length;
for (var i = 0; i < userCount; i++) {
names += " " + apptPortlet.hosts[i].name;
if (userCount > 1 && (userCount - i != 1)) {
names += userCount - i == 2 ? ", " + controller.g11n.and : ",";
}
}
$(".scheduleLink").html(stringUtil.format(controller.g11n.bckToSchedule, names)).unbind('click').click(function (e) { e.preventDefault(); controller.transitionTo('scheduleSpecific'); });
showLink = true;
}
if(showLink)
$(".bckToSchedule").show();
else
$(".bckToSchedule").hide();
},
bindResourceInfo: function (controller) {
this.bindScheduleLink(controller);
var ul = $("#userSchedules").empty();
if (apptPortlet.ableToEdit) {
ul.append($("<li>").append($("<a href='#' class='activeItem apptStrong'>").html(apptPortlet.name.full).click(function (e) { e.preventDefault(); controller.transitionTo('userSchedule', apptPortlet.id); })));
$(".rg-sidebar").show();
}
$.get('rpc/appointmentsInfo/GetMySchedules/', function (schedules) {
if (schedules == null) return;
for (var key in schedules) {
ul.append($("<li>").append($("<a href='#' class='activeItem apptStrong'>").data('id',key).html(schedules[key]).click(function (e) { e.preventDefault(); controller.transitionTo('scheduleResource', $(this).data('id')); })));
}
if (schedules.length > 0)
$(".rg-sidebar").show();
});
}
});
function bindHelpText(g11n, screen) {
$(".apptHelpWrapper").appointmentHelp({ g11n: g11n, isHost: apptPortlet.ableToEdit, portletId:apptPortlet.portletId, screen: screen });
}
}
I briefly used Ember 1.7 but only ever with ember-cli. Anyway, I can point out a couple of things I am pretty sure that you aren't doing correctly. First off:
I changed all instances of the code where it was using
Ember.View.extend to Ember.Controller.extend
This does not make any sense. These are not comparable. If you meant Ember.Component that would make more sense but there's still not a 1:1 similarity. I would recommend studying the Ember.View docs from 1.7 as well as that for components and controllers. You should also give a the Ember.View deprecation guide a read through. The recommended upgrade path is to convert views to components, but components are isolated contexts unlike Ember.View. I think you will have to pass the controller to the Ember.Component instance (would be better to pass the properties needed). Since Ember.Component extends Ember.View, you might not be able to pass via the controller property directly (I don't know if this would be problematic but I would probably avoid).
Accessing data via {{view.someProp}} or {{controller.thisThing}} can nearly always be replaced by proper use of data passing and block params. See the guide on differences in yielded blocks for a complete example of using block params over the {{view}} keyword.
I would recommend going all the way through the deprecations guide to understand what needs to change.

Ganache Cli private network, all ethers on the network go to 0 after a while

I create a ganache cli and initialize my accounts to have ethers using
ganache-cli -h "159.89.119.189" -a 3 -e "1000000000000000000000000000" --secure -u 0 -u 1 -u 2 -s 20
but after a couple of minutes, all accounts on the network are 0.
I'm not able to run any transactions or call contracts again.
A DApp i created connects to this private network
This is my app.js
App = {
web3Provider: null,
contracts: {},
account: 0x0,
coinbase: 0x0,
coinbase_amount: 0,
loading: false,
init: function () {
return App.initWeb3();
},
initWeb3: function () {
// initialize web3
if (typeof web3 !== 'undefined') {
//reuse the provider of the Web3 object injected by Metamask
App.web3Provider = web3.currentProvider;
} else {
//create a new provider and plug it directly into our local node
//App.web3Provider = new Web3.providers.HttpProvider('http://localhost:8545');
App.web3Provider = new Web3.providers.HttpProvider('http://159.89.119.189:8545');
}
web3 = new Web3(App.web3Provider);
App.getCoinbase();
return App.initContract();
},
hostname: function () {
return window.location.origin;
},
setAccount: function (address) {
App.account = address;
},
displayAccountInfo: function () {
// console.log(App);
if (App.account != 0) {
toastr.remove();
toastr.info('Getting Account Info', {timeOut: 300000});
$('#account').text(App.account);
App.getBalance();
}
},
getBalance: function() {
web3.eth.getBalance(App.account, function (err, balance) {
if (err === null) {
if(web3.fromWei(balance, "ether") == 0){
setTimeout(App.getBalance(), 60000);
} else {
console.log(web3.fromWei(balance, "ether"));
toastr.remove();
$('#accountBalance').text(web3.fromWei(balance, "ether") + " ETH");
}
}
})
},
getCoinbase: function () {
web3.eth.getCoinbase(function (err, account) {
if (err === null) {
App.coinbase = account;
// $('#account').text(account);
web3.eth.getBalance(account, function (err, balance) {
if (err === null) {
App.coinbase_amount = web3.fromWei(balance, "ether").toNumber();
console.log(App.coinbase, App.coinbase_amount)
}
})
}
});
},
transfer: function() {
web3.personal.unlockAccount(App.coinbase, "pass12345", 100000, function (err, result) {
console.log(result)
console.log(err)
web3.personal.unlockAccount(App.account, "pass#123", 100000, function (err, result) {
web3.eth.sendTransaction({
from: App.coinbase,
to: App.account,
value: web3.toWei(10, "ether")
}, function (err, result) {
if (err == null) {
console.log("sent money");
console.log(result)
console.log(err)
web3.eth.getBalance(App.account, function (err, balance) {
if (err === null) {
console.log(web3.fromWei(balance, "ether") + " ETH");
}
})
}
else {
console.log(err);
}
})
});
});
},
register: function () {
let email = $('#inputEmail');
let fname = $('#inputFname');
let lname = $('#inputLname');
let password = $('#inputPassword');
let btnRegister = $('#btnRegister');
if (email.val() == "" || fname.val() == "" || lname.val() == "" || password.val() == "") {
toastr.error('Please fill all fields');
return false;
}
btnRegister.attr("disabled", 'disabled');
web3.personal.newAccount("pass#123", function (err, data) {
let address = data;
if (err === null) {
let postData = {
email: email.val(),
fname: fname.val(),
lname: lname.val(),
password: password.val(),
address: data
}
$.ajax({
method: "POST",
url: App.hostname() + "/register",
data: postData,
success: function (data) {
console.log(data)
if (data.status == "success") {
web3.personal.unlockAccount(address, "pass#123", 1000, function (err, result) {
web3.eth.sendTransaction({
from: App.coinbase,
to: address,
value: web3.toWei(10, "ether")
}, function (err, result) {
if (err == null) {
console.log("sent money");
console.log(result)
web3.eth.getBalance(App.coinbase, function (err, balance) {
if (err === null) {
console.log("coinbase "+web3.fromWei(balance, "ether") + " ETH");
}
})
web3.eth.getBalance(address, function (err, balance) {
if (err === null) {
console.log(web3.fromWei(balance, "ether") + " ETH");
}
})
}
else {
console.log(err);
}
toastr.success("Success.");
window.location.href = App.hostname();
})
});
} else {
toastr.error(data.data);
}
btnRegister.attr("disabled", false);
},
error: function (err) {
toastr.error('Error Registering');
btnRegister.attr("disabled", false);
}
});
} else {
toastr.error('Error Registering');
btnRegister.attr("disabled", false);
return false;
}
})
},
login: function () {
let email = $('#inputEmail');
let password = $('#inputPassword');
let btnLogin = $('#btnLogin');
if (email.val() == "" || password.val() == "") {
toastr.error('Please fill all fields');
return false;
}
btnLogin.attr("disabled", 'disabled');
let postData = {
email: email.val(),
password: password.val(),
}
$.ajax({
method: "POST",
url: App.hostname() + "/login",
data: postData,
success: function (data) {
console.log(data)
if (data.status == "success") {
toastr.success("Success.");
window.location.href = App.hostname();
} else {
toastr.error(data.data);
}
btnLogin.attr("disabled", false);
},
error: function (err) {
toastr.error('Error Registering');
btnLogin.attr("disabled", false);
}
});
},
initContract: function () {
$.getJSON('Chainlist.json', function (chainListArtifact) {
// get the contract artifact file and use it to instantiate a truffle contract abstraction
App.contracts.ChainList = TruffleContract(chainListArtifact);
// set the provider for our contracts
App.contracts.ChainList.setProvider(App.web3Provider);
// listen to events
App.listenToEvents();
// retrieve the article from the contract
return App.reloadArticles();
});
},
reloadArticles: function () {
// avoid re-entry
if (App.loading) {
return
}
App.loading = true
// refresh account information because the balance might have changed
App.displayAccountInfo();
var chainListInstance;
App.contracts.ChainList.deployed().then(function (instance) {
chainListInstance = instance;
return chainListInstance.getArticlesForSale();
}).then(function (articleIds) {
$('#articlesRow').empty();
for (var i = 0; i < articleIds.length; i++) {
var articleID = articleIds[i];
chainListInstance.articles(articleID.toNumber())
.then(function (article) {
App.displayArticle(article[0], article[1], article[3], article[4], article[5], article[6])
});
}
App.loading = false;
}).catch(function (err) {
console.error(err.message);
App.loading = false;
});
},
sellArticle: function () {
// retrieve the detail of the article
var _article_name = $('#article_name').val();
var _description = $('#article_description').val();
var _price = web3.toWei(parseFloat($('#article_price').val() || 0), "ether");
const file = $('#article_image').prop('files')[0];
if ((_article_name.trim() == '') || (_price == 0)) {
// nothing to sell
return false;
}
const name = (+new Date()) + '-' + file.name;
const metadata = {
contentType: file.type
};
let ref = firebase.storage().ref();
const task = ref.child(name).put(file, metadata);
toastr.info('Processing.....', {timeOut: 30000});
task.then((snapshot) => {
const _image_url = snapshot.downloadURL;
console.log(_image_url);
web3.personal.unlockAccount(App.account, "pass#123", 1000, function (err, result) {
console.log(result);
console.log(err);
App.contracts.ChainList.deployed().then(function (instance) {
return instance.sellArticle(_article_name, _description, _price, _image_url, {
from: App.account,
gas: 500000
});
}).then(function (result) {
console.log(result);
$('#article_name').val("");
$('#article_description').val("");
$('#article_price').val("");
$('#article_image').val("");
}).catch(function (err) {
console.error(err);
});
});
}).catch((error) => {
console.error(error);
});
},
displayArticle: function (id, seller, name, description, price, image_url) {
var articlesRow = $('#articlesRow');
var etherPrice = web3.fromWei(price, "ether");
// retrieve the article template and fill it
var articleTemplate = $('#articleTemplate');
articleTemplate.find('.panel-title').text(name);
articleTemplate.find('.article-description').text(description);
articleTemplate.find('.article-price').text(etherPrice);
articleTemplate.find('.btn-image-url').attr('href', image_url);
articleTemplate.find('.btn-buy').attr('data-value', etherPrice);
articleTemplate.find('.btn-buy').attr('data-id', id);
if (seller == App.account) {
articleTemplate.find('.article-seller').text("You");
articleTemplate.find('.btn-buy').hide();
} else {
articleTemplate.find('.article-seller').text(seller);
articleTemplate.find('.btn-buy').show();
}
// buyer
// var buyer = article[1];
// if (buyer == App.account) {
// buyer = "You";
// } else if (buyer == 0x0){
// buyer = "None yet"
// }
// articleTemplate.find('.article-buyer').text(buyer);
// add this article
toastr.clear();
$('#articlesRow').append(articleTemplate.html());
},
// listen to events triggered by the contract
listenToEvents: function () {
App.contracts.ChainList.deployed().then(function (instance) {
instance.LogSellArticle({}, {}).watch(function (error, event) {
if (!error) {
$("#events").append('<li class="list-group-item">' + event.args._name + ' is now for sale</li>');
} else {
console.error(error);
}
App.reloadArticles();
});
instance.LogBuyArticle({}, {}).watch(function (error, event) {
if (!error) {
$('#sellBtn').attr("disabled", false);
$("#events").append('<li class="list-group-item">' + event.args._buyer + ' bought ' + event.args._name + '</li>');
} else {
console.error(error);
}
App.reloadArticles();
});
});
},
// retrieve article price from data-value and process buyArticle function
buyArticle: function () {
event.preventDefault();
// retrieve article Price
toastr.info('Processing.....', {timeOut: 30000});
$(event.target).attr("disabled", 'disabled');
$('#sellBtn').attr("disabled", 'disabled');
var price = parseFloat($(event.target).data('value'));
var articleID = parseFloat($(event.target).data('id'));
web3.personal.unlockAccount(App.account, "pass#123", 1000, function (err, result) {
console.log(result);
console.log(err);
App.contracts.ChainList.deployed().then(function (instance) {
return instance.buyArticle(articleID, {
from: App.account,
value: web3.toWei(price, "ether"),
gas: 500000
}).catch(function (error) {
console.error(error);
})
});
});
}
};
$(function() {
$(window).load(function() {
App.init();
// Initialize Firebase
var config = {
apiKey: "AIzaSyAQp34HzZS_3xckuxcVcsUWgCu8_p7UzxA",
authDomain: "comflo-1518513183870.firebaseapp.com",
databaseURL: "https://comflo-1518513183870.firebaseio.com",
projectId: "comflo-1518513183870",
storageBucket: "comflo-1518513183870.appspot.com",
messagingSenderId: "798445619042"
};
firebase.initializeApp(config);
});
});
Same thing happens when i run a geth private server.
I'm using a node app with express.

How to define Handlebar.js templates in an external file

I am currently defining my Handlebars templates within the same HTML file in which they will be used.
Is it possible to define them as external templates, which can be called when the page is loaded?
For those that get here through Google search like I did, I finally found the perfect answer in this post, check it out :
http://berzniz.com/post/24743062344/handling-handlebarsjs-like-a-pro
Basically you need to implement a method, getTemplate :
Handlebars.getTemplate = function(name) {
if (Handlebars.templates === undefined || Handlebars.templates[name] === undefined) {
$.ajax({
url : 'templatesfolder/' + name + '.handlebars',
success : function(data) {
if (Handlebars.templates === undefined) {
Handlebars.templates = {};
}
Handlebars.templates[name] = Handlebars.compile(data);
},
async : false
});
}
return Handlebars.templates[name];
};
and then call your template with it :
var compiledTemplate = Handlebars.getTemplate('hello');
var html = compiledTemplate({ name : 'World' });
That way, if you precompiled the templates (great for production use) it will find it directly, otherwise it will fetch the template and compile it in the browser (that's how you work in development).
You can use AJX to load them.
Here's an example function which accepts a URL to a Handlebars template, and a callback function. The function loads the template, and calls the callback function with the compiled Handlebars template as a parameter:
function loadHandlebarsTemplate(url, callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
var raw = xhr.responseText;
var compiled = Handlebars.compile(raw);
callback(compiled);
}
};
xhr.send();
}
For example, assume you have a Handlebars template defined in a file named /templates/MyTemplate.html, such as:
<p>The current date is {{date}}</p>
You can then load that file, compile it and render it to the UI, like this:
var url = '/templates/MyTemplate.html';
loadHandlebarsTemplate(url, function(template) {
$('#container').html(template({date: new Date()}));
});
An even better solution, would be to pre-compile the templates which would speed up the time they take to load. More info on precompilation can be found here.
Edited solution from Jeremy Belolo for working more templates in directories, if i do not want to have all templates in templates directory.
Handlebars.getTemplate = function(name, dir) {
if (dir === undefined) //dir is optional
dir = "";
if (Handlebars.templates === undefined || Handlebars.templates[name] === undefined) {
$.ajax({
url : 'templates/' + dir+'/' + name, //Path, dir is optional
success : function(data) {
if (Handlebars.templates === undefined) {
Handlebars.templates = {};
}
if (Handlebars.templates[dir] === undefined) {
Handlebars.templates[dir] = {};
}
if (dir === undefined)
Handlebars.templates[name] = Handlebars.compile(data);
else
Handlebars.templates[dir][name] = Handlebars.compile(data);
},
async : false
});
}
if (dir === undefined)
return Handlebars.templates[name];
else
return Handlebars.templates[dir][name];
};
Using async: false; is far away from being the perfect solution. With jQuery in your toolbox, just make use of $.Deferred.
I came up with this solution:
;(function ($, Handlebars) {
'use strict';
var namespace = window,
pluginName = 'TemplateEngine';
var TemplateEngine = function TemplateEngine(options) {
if(!(this instanceof TemplateEngine)) {
return new TemplateEngine(options);
}
this.settings = $.extend({}, TemplateEngine.Defaults, options);
this._storage = {};
return this;
};
TemplateEngine.Defaults = {
templateDir: './tpl/',
templateExt: '.tpl'
};
TemplateEngine.prototype = {
constructor: TemplateEngine,
load: function(name, $deferred) {
var self = this;
$deferred = $deferred || $.Deferred();
if(self.isCached(name)) {
$deferred.resolve(self._storage[name]);
} else {
$.ajax(self.urlFor(name)).done(function(raw) {
self.store(name, raw);
self.load(name, $deferred);
});
}
return $deferred.promise();
},
fetch: function(name) {
var self = this;
$.ajax(self.urlFor(name)).done(function(raw) {
self.store(name, raw);
});
},
isCached: function(name) {
return !!this._storage[name];
},
store: function(name, raw) {
this._storage[name] = Handlebars.compile(raw);
},
urlFor: function(name) {
return (this.settings.templateDir + name + this.settings.templateExt);
}
};
window[pluginName] = TemplateEngine;
})(jQuery, Handlebars);

How to filter a list in Sencha Touch 2?

I'm filtering a list of stocks by symbol, but it doesn't work. Maybe there's something wrong with the code? Something I have missed? Here are some of things I've tried:
function filterBySymbol: function(select, value) {
var ordersStore = this.getBrokerageOrderHistoryList().getStore();
ordersStore.clearFilter();
if (value !== '') {
ordersStore.data.filterBy(function (record, id) {
// log to make certain this gets called (and it is)
console.log(id, record.get('symbol') === value);
return record.get('symbol') === value;
});
// Other things I've tried (nothing worked):
// 1)
// var f = new Ext.util.Filter({
// filterFn: function(record) {
// return record.get('symbol') === value;
// }
// });
// ordersStore.filterBy(f);
// 2)
// ordersStore.filter(function (record) {
// return record.get('symbol') === value;
// });
// 3)
// this.getBrokerageOrderHistoryList().setStore(ordersStore);
// this.getBrokerageOrderHistoryList().refresh();
}
}
It turns out we had to disable remote filtering on the store, which is supposed to default to false, but it wasn't:
this.getOrderList().getStore().setRemoteFilter(false);
one of these should work
// 1
ordersStore.filter("symbol", value);
// 2
ordersStore.filter([
{ filterFn: function(item) { return item.get("symbol") === value; }}
]);
// 3
ordersStore.filterBy(function(item) {
return item.get("symbol") === value;
}
UPDATE: sample that works:
Ext.define('ST.store.Products', {
extend: 'Ext.data.Store',
config: {
fields: ["title", "category" ],
storeId: "Products",
data: [
{ title: 'Text1', category: 'cat1'},
{ title: 'Text2', category: 'cat2'},
{ title: 'Text3', category: 'cat3'},
]
}
});
console.log("before");
Ext.getStore("Products").each(function(item){
console.log(item.data.title);
});
Ext.getStore("Products").filterBy(function(item){
return item.get('title') == 'Text1';
});
console.log("after");
var store = Ext.getStore("Products").each(function(item){
console.log(item.data.title);
});
in my case I see the following in the developer console
before
Text1
Text2
Text3
after
Text1