Using firebase in an ionic/ karma/ jasmine test - firebase

I'm trying to do a basic firebase set call in an ionic / jasmine/ karma/ test but my set never runs . .. I'm also including firebase and angularfire in my karma.conf file, can anyone offer any advice on this please!
beforeEach(function() {
module('avocado.controllers');
module("firebase");
});
describe('controller variables', function() {
it('should contain the AvoDB service', function() {
var AvoDB = new Firebase("https://devdev.firebaseio.com/somechild");
console.log('avodb', AvoDB);
AvoDB.set('123456');
expect(AvoDB).toBeDefined();
})

Related

ionic 3 sqlite - How to execute requests from files

I am currently developing a mobile app with ionic. On this application there is a local sqlite database.
I am looking to be able to execute queries from files for possible updates of the database.
For example, when you first install the application, the tables are created if they do not exist. If changes are made to these tables after installing the application, the changes are not taken into account.
I would like to create files which can be executed one by one according to PRAGMA user_version.
Something like :
// Get pragma user version, if it's undefined, it's set to 1.
// If user_version < 1, we execute the sql file, then we update the user_version
// to 1.
db.executeSql(`PRAGMA user_version;`, []).then((res)=> {
if(res.rows.item(0).user_version < 1) {
db.sqlBatch(`app/sqlFiles/1.sql`, []).then((res)=>{
console.log(res);
}, (err) => {
console.log("Error : " + JSON.stringify(err));
});
db.executeSql(`PRAGMA user_version = 1;`, []).then((res)=>{
console.log(res);
}, (err) => {
console.log("Error : " + JSON.stringify(err));
});
}
}, (err) => {
console.log("Error : " + JSON.stringify(err));
});
I thought about using a file reader but the file is not found during the execution of the function.
this.fileOpener.open('assets/SQLFile/1.sql', 'text/plain')
.then((file) => {
var reader = new FileReader();
reader.onloadend = function(evt) {
console.log("read success");
console.log(evt.target);
};
db.sqlBatch(reader.readAsText(file)).then((res)=>{
console.log(res);
}, (err) => {
console.log("Error : " + JSON.stringify(err));
});
console.log('File is opened');
})
.catch(e => console.log('Error opening file', e));
Will anyone have an idea for doing this kind of thing? (I am looking for a solution that respects good programming practices).
Please note that I am a beginner with ionic and sqlite
Thank you in advance !
But you're getting an error or what? Since the post seems to be valid but the implementation seems to be a little off.
After reading the file, storing the content into a variable, you should execute that "sql query" as usually.
Nevertheless it's not a secure way of do that.
When something in your app change due to an update or upgrade, wouldn't be easier and safer to specify that into the code instead of a single file containing all the database info and scheme?
Edited:
If you want to add custom files to deployment, check this out https://ionicframework.com/docs/developer-resources/app-scripts/

React / Jest: how to test store.dispatch is called

I am new in Redux and Jest and I am struggling on a problem. I want to write the test for this file:
eventListeners.js
import store from '#/store';
chrome.runtime.onMessage.addListener((request) => {
if (request.type === 'OAUTH_SESSION_RESTORED') {
store.dispatch(completeLogin());
}
});
I have this file:
eventListeners.test.js
it('dispatches completeLogin when OAUTH_SESSION_RESTORED received', () => {
// I have made a mock of `chrome.runtime.sendMessage` so the listener defined in eventListeners.js is called when doing that
chrome.runtime.sendMessage({ type: 'OAUTH_SESSION_RESTORED' });
// I want to test that store.dispatch got called
});
However I don't succeed to test that the dispatch method of the store is called.
What I have tried so far:
1) trying to mock directly the method dispatch of the store (eg. doing jest.spyOn(store, 'dispatch') , jest.mock('#/store')).
However nothing seems to work. I think it is because the store used in eventListeners.js is not the one in the specs. So, mocking it does not do anything
2) Using the redux-mock-store library, as described in https://redux.js.org/recipes/writing-tests .
Doing
const store = mockStore({})
chrome.runtime.sendMessage({ type: 'OAUTH_SESSION_RESTORED' });
expect(store.getActions()).toEqual([{ type: 'LOGIN_COMPLETE' }])
However, same issue (I guess): the store used in the spec is not the same as in the eventListeners.js . store.getActions() returns [].
Is there a good way to test that store.dispatch get called?
===================================
For now, what I do is that I subscribe to the store and I try to see if the store has change. As described in https://github.com/reduxjs/redux/issues/546
it('dispatches completeLogin when OAUTH_SESSION_RESTORED received', () => {
const storeChangedCallback = jest.fn()
store.subscribe(storeChangedCallback)
chrome.runtime.sendMessage({ type: 'OAUTH_SESSION_RESTORED' });
expect(storeChangedCallback).toHaveBeenCalled();
})
Is there a better way? Did I missed something?
Thank you for your answers.

"callback is not a function" with $bindToContext

In my angular-meteor app I'm using mdg:camera. I'm trying to update a field from the callback to show the image. Here's the code snippet:
this.addImageToPost = () => {
MeteorCamera.getPicture({
quality: 50
}, this.$bindToContext((err, data) => {
if (err) {
console.log(err);
return;
}
this.imgDataUrl = data;
}));
};
This has been working great. But now after I finished updating my app to use meteor 1.3 (with all the new updates to angular package and mdg:camera as well) this became broken with a "callback is not a function" error.
If I remove the "this.$bindToContext" part, I get a working code - only obviously it's not reactive.
Any idea what's going on? I wonder if the newest updates broke something...
Any help would be greatly appreciated!

Meteor/Iron-Router: how to define routes using data from settings.json

For the URL to which a route applies I have a part defined in settings.json, like this
baseUrl: '/private'
My settings are published and accessible through the collections 'Settings' (on the client). So I tried the following:
Meteor.subscribe('settings');
Deps.autorun(function () {
var settings = Settings.findOne():
if (settings) {
Router.map(function () {
this.route('project', {
path: settings.baseUrl + '/:projectId,
controller: 'ProjectController'
});
});
}
});
The problem is that during initialisation the data is not yet on the client available, so I have to wait until the data is present. So far this approach doesn't work (yet). But before spending many hours I was wondering if someone has done this before or can tell me if this is the right approach ?
Updated answer:
I published solution in repository : https://github.com/parhelium/meteor-so-inject-data-to-html
. Test it by opening url : localhost:3000/test
In this case FastRender package is useless as it injects collection data in the end of head tag -> line 63.
Inject-Initial package injects data in the beginning of head tag -> line 106.
Needed packages:
mrt add iron-router
mrt add inject-initial
Source code:
Settings = new Meteor.Collection("settings");
if (Meteor.isClient) {
var settings = Injected.obj('settings');
console.log(settings);
Router.map(function () {
this.route('postShow', {
path: '/'+settings.path,
action: function () {
console.log("dynamic route !");
}
});
});
}
if (Meteor.isServer){
if(Settings.find().count() == 0){
Settings.insert({path:"test",data:"null"});
}
Inject.obj('settings', Settings.findOne());
}
Read about security in the bottom of the page : https://github.com/gadicc/meteor-inject-initial/
OLD ANSWER :
Below solution won't work in this specific case as FastRender injects data in the end of head tag. Because of that Routes are being initialized before injected data is present.
It will work when data from Settings collection will be sent together with html.
You can do that using package FastRender.
Create file server/router.js :
FastRender.onAllRoutes(function(path) {
// don't subscribe if client is downloading resources
if(/(css|js|html|map)/.test(path)) {
return;
}
this.subscribe('settings');
});
Create also publish function:
Meteor.publish('settings', function () {
return Settings.find({});
});
The above code means that if user open any url of your app then client will subscribe to "settings" publication and data will be injected on the server into html and available for client immediately.
I use this approach to be able to connect many different domains to meteor app and accordingly sent proper data.

How can I implement a call to a package that doesn't use fibers from with Meteor?

I am trying to use twit in Meteor in order to communicate to the Twitter REST api.
It works fine in say a server.js file in the /server/ directory if I call it by itself. If I wrap or call it from within say an observe or even call a function that calls twit's functions from an observe I get errors.
For example this works perfectly fine within a /server/server.js.
T.post('statuses/update', { status: 'hello world!' }, function(err, reply) {
console.log('error: ' + JSON.stringify(err,0,4));
console.log('reply: ' + JSON.stringify(reply,0,4));
});
But, suppose I want to say call Twitter every time a record is inserted.
var query = Posts.find({}, {fields: {}});
var handle = query.observe({
added: function(post, before_index){
if(post.twitter_id_str === undefined || post.twitter_id_str === '' ||
post.twitter_id_str === null) {
T.post('statuses/update', { status: 'hello world!' }, function(err, reply) {
console.log('error: ' + JSON.stringify(err,0,4));
console.log('reply: ' + JSON.stringify(reply,0,4));
if(reply){
// TODO update record with twitter id_str
// BREAKS here - crash, restart
console.log('incoming twitter string: ' + reply.id_str);
Posts.update(
{_id: post._id},
{$set:{twitter_id_str:reply.id_str}}
);
}
});
} else {
console.log('remove me we have it: ' + post.twitter_id_str);
}
}
});
Which throws this error, server crashes and restarts but no code logic is run where I have commented the Break.
app/packages/mongo-livedata/collection.js:215
throw e;
^
Error: Meteor code must always run within a Fiber
at [object Object].get (app/packages/meteor/dynamics_nodejs.js:14:15)
at [object Object]._maybeBeginWrite (app/packages/mongo-livedata/mongo_driver.js:68:41)
at [object Object].update (app/packages/mongo-livedata/mongo_driver.js:191:20)
at [object Object].update (app/packages/mongo-livedata/collection.js:203:32)
at app/server/server.js:39:13
at /usr/lib/meteor/lib/node_modules/twit/lib/oarequest.js:85:16
at passBackControl (/usr/lib/meteor/lib/node_modules/twit/node_modules/oauth/lib/oauth.js:359:11)
at IncomingMessage.<anonymous> (/usr/lib/meteor/lib/node_modules/twit/node_modules/oauth/lib/oauth.js:378:9)
at IncomingMessage.emit (events.js:88:20)
at HTTPParser.onMessageComplete (http.js:137:23)
Exited with code: 1
In summary, the Twitter code runs fine on it's own but not when within the Meteor fibers stuff. I tried putting it in another function and calling that from within the observe etc... no avail.
Any recommendations or ideas?
You'll need to do the twit post API call in a fiber:
Fiber(function() { ... your twit API call ... }).run()
Have a look at this related question: "Meteor code must always run within a Fiber" when calling Collection.insert on server

Resources