I am writing test for my custom DS.RESTAdapter, which uses our own SDK as transporter instead of ajax calls. Now, I want to test the adapters find, findAll, findQuery ... functions which require me to pass an instance of store as a parameter.
For example:
findAll: function(store, type, sinceToken){...}
To be able to test this, i need to pass "store" param which is not available in moduleFor in ember-qunit (unlike in moduleForModel where you can access store via this.store within the test instance).
Is there another way to gain access to the current instance of store?
Thanks.
Edit:
I solved this by creating mocks for both, store and type.
You can create a store instance by:
var store = DS.Store.create({
adapter: #subject
})
And a mock for type, just as an ordinary object with required properties for the test.
You can mock this method (for instance, using Sinon plugin for QUnit). Another solution for accessing the store (but I'm not sure it will work in your case) which helped me to access store from the global namespace is using setup and teardown methods:
setup: function () {
Ember.run(App, App.advanceReadiness);
},
teardown: function () {
App.reset();
}
Related
For vue data, for every tutorials I have seen, it seems that data variables first defined as return value when creating vue instance like below:
app = createApp({
data() {
return {
someData: null,
}
},
}
I wonder if this practice is some way necessary or if it is just a convention, because I could simply define new data like this.someData2 in mounted or methods and it seems to work pretty much the same way.
I could simply define new data like this.someData2 in mounted or methods and it seems to work pretty much the same way ?
Answer is Yes, You can add a new property directly to this without including it in data. However, properties added this way will not be able to trigger reactive updates.
But we use the data option to declare reactive state of a component. The option value should be a function that returns an object. Vue will call the function when creating a new component instance, and wrap the returned object in its reactivity system.
Please do through this official documentation of Reactivity Fundamentals for better understanding.
the data option must be an function so every vue instance can maintain a separate copy of the return object,so it won't infect other instance
Mobx and Redux will normally not persist any data. They will maintain a temporary global state while the app is running.
I know there are redux-persist and mobx-persist packages within both communities. But unfortunately these persisting solutions do not seem good at all. They only stringify or serialize a global state tree and persist it using some sort of key-value storage. Right?
The problem:
When such an app is open again, the stringified store will be parsed and structured back to its original data structure (JSON, for instance) and then fully loaded into the RAM memory. Am I right?
If yes, this is a problem. It is not good to always have a full "database" aka "global state" loaded in-memory. It will probably never be faster to filter data within a long array in my global state... compared to querying a table on SQLite, right?
I have been looking for some repository-like solution for persisting global state for either redux or mobx. I am yarning for some solution for persisting and querying data on some well-known mobile database like SQLite or others.
Any answers will be very much appreciated.
Indeed you can use repository pattern.
On your repository, you may have a save method.
save(group: GroupLocalStorageModel): Promise<boolean> {
let created;
this._localStorage.write(() => {
created = this._localStorage.create<GroupLocalStorageModel>("Group", group);
});
return Promise.resolve(true);
}
This method will literally save your entity to some local storage you set. In the example above, we are saving a group object to a Group collection which are like tables. We are using realm which is no-sql.
Once you have your repository, if you are using either redux or mobx, you will probably call your save method on your action. Both redux and mobx work with actions, right?
export const GroupStoreModel = types
.model("GroupStore")
.props({
groups: types.optional(types.array(GroupModel), []),
})
.extend(withEnvironment)
.actions((self) => {
return ({
_addGroupToStore(group: GroupLocalStorageModel) {
self.groups.push(group)
},
_deleteAllFromStore() {
self.groups.clear()
},
_addGroupsToStoreBatch: (groups: GroupLocalStorageModel[]) => {
self.groups.concat(groups);
},
})
})
/* Async actions */
.actions((self) => {
let groupRepository = self.environment.groupRepository;
return ({
addGroup(group: GroupLocalStorageModel) {
groupRepository.save(group).then(result => self._addGroupToStore(group))
},
getAllGroupsPaginated(page: number) {
groupRepository.getAllPaginated(page).then(groups => self._addGroupsToStoreBatch(groups));
},
deleteAll() {
groupRepository.deleteAll();
self._deleteAllFromStore();
}
})
})
In this example, we are using mobx-state-tree. And this addGroup action will update firstly our database, and then update also the global state.
We still want to use our global state so our views will be re-rendered automatically according to either connect for redux or observable for mobx.
See more informations here on the repository:
https://github.com/Hadajung/poc-react-native-database-example
AFAIK, there are two options for using sqlite with redux persist.
redux-persist-sqlite-storage: By maintainer's own word
By default redux-persist uses AsyncStorage as storage engine in react-native. This is a drop-in replacemet of AsyncStorage.
The library is inspired by react-native-sqlite-storage.
Please, remember, to use this, you need to install an additional package installed react-native-sqlite-storage
redux-persist-sqlite: By maintainer's own word
A redux-persist storage adapter that writes to sqlite.
This is adapted from https://github.com/prsn/redux-persist-sqlite-storage, but uses Node.js sqlite3 rather than react-native.
Great for Electron apps that are backed by Redux.
UPDATE: react-native-mmkv : This is developed by WeChat. As it says in its about section
An extremely fast key/value storage library for React Native. ~30x faster than AsyncStorage!
I'm not really sure what you need but if I understood you correctly you need to persist large amounts of data, and also to load that same data, but only in batches.
I believe that this kind of problem can be solved with a repository pattern and SOLID design principles.
You will need:
store class (mobx store) that holds your business logic.
repository class which is responsible for retrieving and persisting data.
The store gets the repository injected into it via the constructor.
Then when you call the initialize method on your store, it talks to the repository and retrieves the initial data. Now, initial data can be only a subset of all the data that is persisted. And you can implement some kind of paging on the store and repository, to retrieve data in batches as needed. Later you can call other methods to load and save additional data as needed.
pseudo code:
class Repository(){
initialize()// load the first batch
load(next 10 models)
save(data)
}
class Store{
constructor(repository)
initialize(){
repository.initialize()
}
load(){
repository.load()
}
save(){
repository.save()
}
}
Now your application data shouldn't be one giant object, rather it should consist of multiple stores, where each store is responsible for a part of the data. For example, you would have one store and repository for handling todos and another pair that handles address book contacts etc.
Addendum:
The reason the repository is injected into the store is so you could easily swap it for some other implementation (the store doesn't care how the data is persisted and retrieved) and also, unit testing is very easy.
You could also have a root store that would hold all other stores, so in essence you have your complete state in one place. So if you call serialize on the root store, it serializes all stores and returns one big object.
I think the best solution would be bloc hydrated or cubit hydrated package from flutter_bloc.
https://pub.dev/packages/hydrated_bloc
In background it uses Hive DB, very performant DB, and only keys are stored in memmory so it should not add huge bloat to the app like SQLite.
If you could make all you APP logic in blocks/cubits, then extra DB calls would be irelevant.
I want to detect current selected language from a domain (like es.domain.com, de.domain.com) so I need to pass it to all non static route handlers and to all views.
To detect a language I need a request object. But global view context it is possible to update where request object is not accessible (in server.views({})). Also server.bind (to pass data to route handler) works only where request object is not accessible.
Hapi version: 11.1.2
You could try something like this:
server.ext('onPreResponse', function (request, reply) {
if (request.response.variety === 'view') {
request.response.source.context.lang = request.path;
}
reply.continue();
});
This will attach a lang data point to the context that is being sent into the view. You'll have to extract the lang from the url as request.path is probably not what you actually want.
Also, if you look here you'll see a few pieces of request data is made available to every view via reply.view() If the locale/language is available directly in one of those data points, or can be derived from them, you can skip the extension point approach entirely.
Again, this is assuming version 10+ of hapi. If you're using an older version, the extension point method is your best bet.
This weekend i tryed to test a package "A" from my meteor app.
This package depends on another package "B" that defines all collections. So the package "B" expose all required collections.
The package "A" expose a main object that have some methods that use the collections exposed in "B".
I want to replace some collections by a code like this :
myCol = {
"findOne": return {_id: 1, "name": ben}
}
But it fails. This code is ok from tinytest.add code, but in the methods of the package "A", it still uses the original Collection variables. I've seen in the build folder that everything is re-written by the build system, so i wonder what is the best way to test my code without depending on those Collection variables.
I have some ideas like storing those variables in a main object that has get/set methods. It might allow me to change everything when i do test.
Thanks for help
Here is the sample app : https://github.com/MeteorLyon/tutorial-package-dependancy-testing
Follow the README.md to run different test.
If you find a solution it's great.
If you are looking for stubs, I'd highly recommend using sinon. Specifically, have a look at the stubs and the sandbox portions of the docs. You can find atmosphere packages here. Here's a quick example:
Tinytest.add('my test', sinon.test(function(test) {
// this is sandboxed stub - we are writing to a global object
// but it will be restored at the end of the test
test.stub(Meteor, 'userId', function() {
return USER_ID;
});
// let's do the same thing with a collection
test.stub(Posts, 'findOne', function() {
return {_id: 1, name: 'ben'};
});
var post = Posts.findOne();
test.equal(post.name, 'ben');
}));
Keep in mind that tinytest is an integration test framework, so you may get better tests by fully utilizing both package's APIs. With respect to testing collection interactions, we've found its better to not stub very much and just insert and cleanup as needed. But that's pretty general advice - there may be some specific reason why this can't work in your particular use case.
I'm following this article to mock response in dojo.
My mocker is very similar to the one in the article except this:
registry.register(/\/testIntern/, function (url, options) {
return when({
value: "Hello World"
});
In my understanding, this should map to any request that contains "/testIntern" on the address.
My testcase is quite simple:
// similar to example
var testRest= new Rest("/testIntern", true);
testRest("").then(lang.hitch(this, function (data) {
assert.deepEqual("Hello World", data.value, "Expected 'Hello World', but got" + data.value);
}));
It really should be quite simple. But when I run this test, I got 404 Not Found. It looks like the REST call in the test doesn't try to use the mocking service. Why?
You are generally correct in your thought that registering a URL with dojo/request/registry should pass anything referencing that URL via dojo/request through your handler.
Unfortunately, dojo/store/JsonRest uses the dojo/_base/xhr module which uses dojo/request/xhr directly, not dojo/request. Any registrations created with dojo/request/registry (and any setting of defaultProvider) will unfortunately be lost on JsonRest.
You might want to have a look at dstore - its Rest store implements the same server requests as dojo/store/JsonRest but it uses dojo/request instead of being hard-coded to a specific provider. (dojo/request defaults to dojo/request/xhr in browsers anyway, but can be overridden via dojoConfig.requestProvider.) dstore contains adapters for translating between dstore's API and the dojo/store API, if you need to use it with widgets that operate with the latter.