How to test a PersistentMap item is correctly saved to storage? - nearprotocol

I have a function that takes a number of values, creates a new model, and then saves this in storage via a PersistentMap.
I would like to test that the item is successfully saved in storage. This is how I'm going about it:
it("saves a new item to storage", () => {
VMContext.setCurrent_account_id("test_account_id");
contract.createMyPersistantMapItem(
"value 1",
"value 2",
"value 3"
);
expect(storage.hasKey("myPersistantMap::test_account_id")).toBeTruthy();
});
However the test fails with the following:
[Actual]: false
[Expected]: Truthy
[Stack]: RuntimeError: unreachable
at node_modules/#as-pect/assembly/assembly/internal/assert/assert (wasm-function[53]:0xd71)
at start:src/simple/__tests__/index.unit.spec~anonymous|0~anonymous|0~anonymous|0 (wasm-function[130]:0x2a84)
at node_modules/#as-pect/assembly/assembly/internal/call/__call (wasm-function[134]:0x2aac)
Am I going about this the wrong way?
Also I would like to test the values in the item are correct. In the todos example the created todo is returned from the function that creates it, and then this returned value is tested. Is this the best way of doing things to make testing easier?
EDIT
This is the createMyPersistantMapItem function - edited a bit to make things clearer:
export function createMyPersistantMapItem(
blah1: string,
blah2: string,
blah3: string,
): void {
const accountId = context.sender;
assert(
!storage.hasKey("myPersistantMap::" + accountId),
"Item already exists"
);
const newPersistantMapItem = new PersistantMapItem(
blah1,
blah2,
blah3
);
myPersistantMap.set(accountId, newPersistantMapItem);
}

About the first question:
Does myPersistentMap use the "myPersistantMap" prefix when initialized? Does PersistantMapItem use the #nearBingden annotation on the class?
Also, in your test, I think you should use
VMContext.setSigner_account_id("test_account_id")
//instead of
VMContext.setCurrent_account_id("test_account_id")
Because you are using context.sender when you call createMyPersistantMapItem
About the second question:
In the todos example the created todo is returned from the function that creates it, and then this returned value is tested. Is this the best way of doing things to make testing easier?
This question is primarily opinion based, so I can only answer for myself. Testing the returned value is completely fine. In a smart contract however, I would probably test if the value is actually stored on the contract. And I think they are doing that in the TODO example. They just use the ID of the generated TODO to do a query on the smart contract.
const a = Todo.insert("Drink water");
// They use the id of the todo (a) to check if it was actually stored, and is in fact the same object. I think this is fine.
expect(getById(a.id)).toStrictEqual(a);

Related

For/in probem. What is the difference between object.variable and object[variable]?

Why can we use a code like this:
let student = {name:"John", surname:"Doe", index:386754};
let text = "";
let x;
for (x in student) {
text += student[x] + " "; }
And it would preview: John Doe 386754.
But when I formulated it like this:
let student = {name:"John", surname:"Doe", index:386754};
let text = "";
let x;
for (x in student) {
text += student.x + " "; }
, it returnes: undefined undefined undefined.
I suppose it's a pretty basic thing, but I had to ask because I can't find an appropriate answer.
Thank you ahead!
You should check out the data structures. You create a hash table using the variable student. So you can call inner variables (key-value pairs) by using brackets as you did student[name]. The second one student.name means you are calling a method of a class, which you don't have.
I recommend you to check what data structures exist, and how to use them.
The usage of object.something vs object[something] varies in different languages, and JavaScript is particularly loose in this aspect. The big difference here is that in object[something], something must reference a string corresponding to a key in object. So if you had something = 'myKey', and myKey was the name of a key in something (so object = {'myKey': 'value', ...}), you would get value. If you use object.something, you are asking JavaScript to look for a key in object with the name something. Even if you write something = 'myKey', using a dot means that you are looking within the scope of the object, making variables in your program effectively invisible.
So when you write student.x, you get undefined because there is no key 'x': 'value' in student for your program to find. Defining x as a key in your for loop does not change this. On the other hand, writing student[x] means that your program is finding the value x is referencing and plugging it in. When x is 'name', the program is actually looking for student['name'].
Hope that clarifies your issue. Good luck!

Is it okay to have multiple states in Redux store, handled separatly by combine reducers?

I am reviewing some code in React-Redux app and came across to find out that there are three states in the Redux store and the changes to each state is handled by different reducers(combine reducers). Similar to the following:
src/models
--model1
--model2
--model3
src/reducers/index.js
const rootReducer = combineReducers({
model1Reducer,
model2Reduce,
model3Reducer
})
src/reducers/model1Reducer
// import model1 here
const model1Reducer = (state = model1, action) { }
Similarly, the model2Reducer and model3Reducer imports model2 and model3, respectively and act on it.
Is this method of defining three different state trees okay in Redux? One of the principles of Redux is single source of truth. Then how is this okay?
What you have described here is the correct way of using redux and is the same as we use it in my organization.
The meaning behind the principle "Single Source of Truth" is for
make it easy to create universal apps, as the state from your server can be serialized
and hydrated into the client with no extra coding effort.
We use combinedReducers to separate part of our app by logic and to avoid a situation where a reducer becomes complex in terms of updating the store. It doesn't mean doing that will separate the store into unrelated states. Each of them is manage independent parts of your store. It "just" make our code more readable, and modular in terms of maintenance.
Here is the part of the Redux docs that explains the concept of combinedReducers
As your app grows more complex, you'll want to split your reducing
function into separate functions, each managing independent parts of
the state.
The combineReducers helper function turns an object whose values are
different reducing functions into a single reducing function you can
pass to createStore.
The resulting reducer calls every child reducer, and gathers their
results into a single state object.
Here are the rules for reducers:
Must return any value besides 'undefined'.
Produces 'state' or data to be used inside of your app using only previous state and the action.
Must not reach outside of itself to decide what value to return.
Must not mutate its input state argument.
Your combineReducers will look like this:
export default combineReducers({
property1: model1Reducer,
property2: model2Reduce,
property3: model3Reducer
}
Your specific reducer will look like this:
export default () => {
return 123;
}
Now, what I did not show above is the ES2015 syntax (selectedSong = null) where you do something like this:
const selectedSongReducer = (selectedSong = null, action) => {
if (action.type === 'SELECTED_SONG') {
return action.payload;
}
return selectedSong;
}
This follows rule 1 where we must return any value besides undefined, because if we don't we will get undefined when the application boots up, so we implement the Default Argument Values from ES6/ES2015.
It does not have to be defaulted to null, it could be an empty array, a string or object, depending on the context of your reducer.
The second time your reducer gets called it will no longer be undefined, the first argument will be whatever it returned the last time it was ran.
The only thing that changes when the reducer gets called is the actions object.

creating lettable rxjs "string.split" operator

I am attempting to do some string manipulation in rjxs, and while I can accomplish it with the built in behaviors on the string class and the array class in Javascript, I'm wanting to use this as an exercise to learn even more about rxjs and understand a fluent code-flow better.
To that end, it's imperative to me that I discover a way to do it that can fit in a fluent solution, instead of a series of variable assignments like I see in most rxjs examples.
Essentially, here's the situation; I've got a string of text;
const example = `
key || value
key || value
key || value
value
value
value
key || key[key1] = value | key[key2] = value
key || value
`;
The first thing that I need to do is use string.split('\n') to create an array of strings, so that I can through each line and perform further operation.
example.string.split('\n') does give the desired results, but trying to send this into rxjs begins to get rather mixed yield. With the pipe method, I know that I send the results into rxjs as an Observable, but I'm having a really troubling time grasping how to truly treat it from there without excessive nesting into the map operator.
For example, if I do ...
of(example.string.split('\n')).pipe(
map(results => results.toString().split('||')),
map(results => ... ),
...
).subscribe();
I can start to get a semblance of what I'm looking for, but what I'd really like to do is ...
of(example).pipe(
split('\n'),
split('||'),
concatMap(results => ...)
).subscribe();
Reading the documentation on lettable operators, seen here, it looks like this should be a pretty easy thing to create. In theory, it should look like this in my mind;
const split = (separator: string) => <T>(source: Observable<T>) =>
new Observable(observer => {
source.subscribe({
next(x) { observer.next(x.toString().split(separator)); },
error(err) { observer.error(err); },
complete() { observer.complete(); }
})
});
So that should make the whole code obvious enough;
of(example).pipe(
split('\n')
).subscribe(result => console.log(`[n]::${result}`));
But this doesn't give me what I really expect. I expected to get an array of the lines, but if I output it, I get ...
[n]::, key || value, key || value, key || value, ,
value, value, , value, key || key[key1] = value |
key[key2] = value, key || value,
I'm really unclear what I'm doing wrong, here. Since it's hard to demonstrate rxjs in most of the code playgrounds like plunkr or jsfiddle, at least to my knowledge, I've prepared a playground environment to demonstrate my work on stackblitz, if it helps.
You'll find all of the pertinent code in the playground/index.ts file. I've done the best I can to abstract away the need to have any knowledge of angular, as I've painstakingly earmarked the sections that should be left alone to make it continue showing output on the right side. If you do not know angular, but can help with rxjs, you should be able to work without ever disturbing that setup.
STACKBLITZ PLAYGROUND
Your code is working fine, just the es6 template string ${} flattened your array into a string. If you console.dir or log the result, you will see a correct array retrieved.

How to do a prophecy for current testing class in PHPUnit?

I have this case that I want to run PHPUnit test and check behaviour of current testing class as follows:
public function it_allows_to_add_items()
{
// Create prophesies
$managerProphecy = $this->getProphet(ListingManager::class);
$listingItemProphecy = $this->getProphet(ListingItemInterface::class);
$listing = factory(\App\Misc\Listings\Listing::class)->create();
$manager = new ListingManager($listing);
$item = factory(\App\Misc\Listings\ListingItem::class)->make(['listing_id' => null]);
$item2 = factory(\App\Misc\Listings\ListingItem::class)->make(['listing_id' => null]);
$manager->addItem($item);
$managerProphecy->validate($listingItemProphecy)->shouldBeCalledTimes(2);
$manager->addItem($item2);
$this->assertTrue(true);
}
is that even possible ?
Of course I'm getting
1) GenericListingManagerTest::it_allows_to_add_items
Some predictions failed:
Double\App\Misc\Listings\ListingManager\P2:
Expected exactly 2 calls that match:
Double\App\Misc\Listings\ListingManager\P2->validate(exact(Double\ListingItemInterface\P1:00000000058d2b7a00007feda4ff3b5f Object (
'objectProphecy' => Prophecy\Prophecy\ObjectProphecy Object (*Prophecy*)
)))
but none were made.
I think your way to approach this test is a bit off. If I understand correctly you want to verify that addItem(object $item) works properly, i.e. the manager contains the item and the item is the same you added. For this you should not need prophecies and in fact your test does not actually use the prophecies you created. Depending on what your Manager looks like you could write something like this:
function test_manager_add_items_stores_item_and_increases_count()
{
$manager = new ListingManager(); // (2)
$item = new ListingIem(); // (3)
$initialCount = $manager->countItems(); // (1)
$manager->addItem($item);
$this->assertEquals($initialCount + 1, $manager->countItems());
// Assuming offset equals (item count - 1) just like in a numeric array
$this->assertSame($item, $manager->getItemAtOffset($initialCount));
}
(1) Assuming your manager has a count()-method you can check before and after whether the count increased by the number of added items.
(2) We want to test the real manager - that's why we don't need a mock created by prophecy here - and we can use a real item because it's just a value.
(3) I'm not sure why you have a ListingItemInterface. Are there really different implementations of ListingItem and if so, do you really want a generic ListingManager that possibly contains all of them or do you need a more specific one to make sure that each Manager contains only it's specific kind of item? This really depends on your use case, but it looks like you might violate the I (Interface Segregation Principle) or L (Liskov Substitution Principle) in SOLID.
Depending on your use case you might want to add real items, e.g. 2 different types to make clear that it's intended that you can put 2 different implementations of the interface in there or you can do it like above and just add a ListingItem and verify that each item in the manager implements the interface - I leave finding the assertion for that to you ;). Of course you can use your factory to create the item as well. The important thing is that we test with assertSame() whether the managed object and the one we created initially are the same, meaning reference the exact same object.
You could add additional tests if you want to ensure additional behaviour, such as restricting the kind of items you can put in the manager or how it behaves when you put an invalid object in there.
The important thing is, that you want to test the actual behaviour of the Manager and that's why you don't want to use a mock for it. You could use a mock for the ListingItemInterface should you really require it. In that case the test should probably look something like this:
function test_manager_add_items_stores_item_and_increases_count()
{
$manager = new ListingManager();
$dummyItem = $this->prophecy(ListingIemInterface::class);
$initialCount = $manager->countItems();
$manager->addItem($dummyItem->reveal());
$this->assertEquals($initialCount + 1, $manager->countItems());
$this->assertSame($dummyItem, $manager->getItemAtOffset($initialCount));
}
edit: If addItem checks the validation which you want to skip, e.g. because the empty item you provide is not valid and you don't care. You can use PHPUnit's own mock framework to partially mock the manager like this:
$item = new ListingItem();
$managerMock = $this->getMockBuilder(ListManager::class)
->setMethods(['validate'])
->getMock();
$managerMock
->expects($this->exactly(2))
->method('validate')
->with($this-> identicalTo($item))
->willReturn(true);
$managerMock->addItem($item);
$managerMock->addItem($item);
You don't have to assert anything at the end, because expects() is already asserting something. Your Manager will work normally, except for validate(), meaning you will run the code in addItem() and if in there validate is called (once per item) the test will pass.

How to update single key/value from dictionary in morph?

In a previous question I asked how I could show the contents of a Dictionary in a GUI. I started from this idea to build a GUI with a slightly better look and feel. It mainly consists of RectangleMorphs glued together in columns and rows (cfr. the accepted answer in my previous question).
The problem now is that I would like my table to be updated when elements are added/removed/edited in my dictionary. I managed to write some Morph that consists of columns of CellMorphs, which inherit from RectangleMorph and have model and message as instance variables with the following update message:
update
" update the contents of this cell "
| value |
self removeAllMorphs.
(model = nil or: message = nil)
ifTrue: [ value := '' ]
ifFalse: [ value := model perform: message ].
self addMorph: value asMorph.
As can be seen, the CellMorph is a container for a Morph containing the actual content of the cell. This works great for displaying the size of the dictionary for instance:
d := Dictionary new.
d at: 'foo' put: 100.
d at: 'bar' put: 200.
cell := CellMorph new
model: d;
message: #size;
color: Color white.
cell openInWorld.
d at: 'boo' put: 300. " cell will be updated "
but I don't seem to get something similar working for the contents of the dictionary, because I can't find a way to access single keys or values with a message. The only solution I can think of is to create new columns with new cells every time, but this is so expensive and I can't imagine that this is a good idea...
Therefore my question:
Is there a way to update my Morph displaying the dictionary without creating billions of my CellMorphs or should I forget about my idea and rather work with rows of CellMorphs for instance in order to group the entries in the dictionary?
for completeness: the model: message in CellMorph looks like:
model: newModel
"change the model behind this cell"
model ifNotNil: [ model removeDependent: self ].
newModel ifNotNil: [newModel addDependent: self].
model := newModel.
self update.
update: aParameter does nothing more than call update. and I also added self changed. in all messages of Dictionary that I want the interface to be notified of (at: put:, removeKey:, etc.).
In the instance variable named 'message' you could have a Message object, instead of having only the selector.
An instance of Message has the receiver, selector and arguments. So, you could configure it with the dictionary keys sorted asArray in the receiver, the selector #at: and an index, to get a specific key. Accessing the value would be getting the value at: that key in the dictionary.
I think that a Message is not executed with object perform: message, you should check. message perform should work because it already has the receiver.
In any case, this complexity may show that having only (one) model and (one) message is not enough to get the model in th granularity you want, and you can possibly specialize a bit more, using the knowledge that the model is a dictionary. For instance, having an instance variable for key or for keyIndex.
Some side notes about the code:
(model = nil or: message = nil)
has comparisons with nil, that can be replaced by #isNil message or, if you want to stick with equality, use the faster == to compare identity, since nil is unique.
#or: is used to get the benefits of partial evaluation (the argument is evaluated only if the receiver is false). But that only works if you have a block as argument, otherwise the expression is evaluated before, to get the argument for the message in the stack.

Resources