How to match some values of object using sinon stub - unit-testing

I've been writing test using sinon. During the same I wrote stub where some input parameters are passed and an object is returned. This object returns some values and a random date value generated by system at the time of execution. So need guidance on following.
How can I handle the same as the matching arguments are static in nature and I don't know the possible value of the date generated by actual code.
How can we skip certain key values of an object using sinon. i.e. say object has following values. const object = {name: "abc", employeeNumber : "123"} I only want to check if name is "abc" and don't need to match employeeNumber.

From the sinon.match docs:
Requires the value to be not null or undefined and have at least the same properties as expectation.
From the sinon.assert.match docs:
Uses sinon.match to test if the arguments can be considered a match.
Example:
test('partial object match', () => {
const object = { name: "abc", employeeNumber : "123" };
sinon.assert.match(object, { name: 'abc' }); // SUCCESS
})

Related

AWS CDK - StepFunction - Modify input before passing to the next step

I have a 3 step state machine for a step function.
InputStep -> ExecuteSparkJob -> OutputLambda
ExecuteSparkJob is a glue task. Since it cannot pass its output to the step function, it writes it output to an S3 bucket. OutputLambda reads it from there and passes it on to the step function.
The idea of InputStep is simply to define a common S3 URI that the following steps can use.
Below is the code I have for the Input Step.
const op1 = Data.stringAt("$.op1");
const op2 = Data.stringAt("$.op2");
const inputTask = new Pass(this, "Input Step", {
result: Result.fromString(this.getURI(op1, op2)),
resultPath: "$.s3path"
});
getURI(op1: string, op2: string): string {
return op1.concat("/").concat(op2).concat("/").concat("response");
}
However, the string manipulation that I am doing in getURI is not working. The values in inputTask.result are not being substituted by the value in Path.
This is the input and output to the Input Step
{
"op1": "test1",
"op2": "test2"
}
Output
{
"op1": "test1",
"op2": "test2"
"responsePath": "$.op1/$.op2/response"
}
Is it possible to do some string manipulations using parameters in the Path in Step Function definition? If yes, what am I missing?
Thanks for your help.
You can use one or more EvaluateExpression Tasks - it's still a bit clunky.
You can find examples here.
API doc here.
Use a Lambda function instead of a Pass state to build the string.
Step Functions doesn't currently support string concatenation with reference paths. The Result field of a Pass state doesn't allow reference paths either. It has to be static value.
The Pass state's Parameters field supports the intrinsic functions and substitutions you need to do this natively, without a Lambda task. The Result field doesn't.
Compose a string from the execution inputs with the Format intrinsic function:
const inputTask = new Pass(this, "Input Step", {
parameters: {
path: JsonPath.format(
"{}/{}/response",
JsonPath.stringAt("$.op1"),
JsonPath.stringAt("$.op2")
),
},
outputPath: "$.s3",
});
The resulting string value test1/test2/response will be output to $.s3.path.

object query and remove parentheses in dart, flutter

Hello? I'm building an app using the flutter provider pattern. And I created a process to query the values ​​inside the object. I also have data in my model dart file.
Check the code below.
List<Device> _devices = [
Device(one: 'apple', two: 'iphone'),
Device(one: 'samsung', two: 'galaxy')
];
String Query(String value) {
return _media.where((medium) => medium.one == value)
.map((medium) => (medium.two)).toString();
Query("apple")
So, when I call that function, I expect iphone to be returned. But the results come in (iphne). Actually I know why. After all, the data returned is a List<Device> type. But what I want is to remove the parentheses by returning only the first value in the queried list(meaning only queried list, not the full list). In other words, I want to receive iphone, not (iphone). Currently, I am using substring removing the first and the final word, which seems to have some limitations. Is there any way to remove parentheses in that logic?
You have parentheses because you're calling .toString() on a list:
return _media.where((medium) => medium.one == value)
.map((medium) => (medium.two))
.toString();
To return just .two or the first found object, you just have to do:
return _media.firstWhere(
(medium) => medium.one == value, orElse: () => null)?.two;
That will return the value of .two of the first found object or null if nothing found.
Doc: Iterable.firstWhere()

Apollo Link State Default Resolver Not Working (#client query parameter variables)

Example here: https://codesandbox.io/s/j4mo8qpmrw
Docs here: https://www.apollographql.com/docs/link/links/state.html#default
TLDR: This is a todo list, the #client query parameters don't filter out the list.
This is the query, taking in $id as a parameter
const GET_TODOS = gql`
query todos($id: Int!) {
todos(id: $id) #client {
id
text
}
}
`;
The query passes the variable in there
<Query query={GET_TODOS} variables={{ id: 1 }}>
/* Code */
</Query>
But the default resolver doesn't use the parameter, you can see it in the codesandbox.io example above.
The docs say it should work, but I can't seem to figure what I'm missing. Thanks in advance!
For simple use cases, you can often rely on the default resolver to fetch the data you need. However, to implement something like filtering the data in the cache or manipulating it (like you do with mutations), you'll need to write your own resolver. To accomplish what you're trying to do, you could do something like this:
export const resolvers = {
Query: {
todos: (obj, args, ctx) => {
const query = gql`
query GetTodos {
todos #client {
id
text
}
}
`
const { todos } = ctx.cache.readQuery({ query })
return todos.filter(todo => todo.id === args.id)
},
},
Mutation: {},
}
EDIT: Every Type we define has a set of fields. When we return a particular Type (or List of Types), each field on that type will utilize the default resolver to try to resolve its own value (assuming that field was requested). The way the default resolver works is simple -- it looks at the parent (or "root") object's value and if it finds a property matching the field name, it returns the value of that property. If the property isn't found (or can't be coerced into whatever Scalar or Type the field is expecting) it returns null.
That means we can, for example, return an object representing a single Todo and we don't have to define a resolver for its id or text fields, as long as the object has id and text properties on it. Looking at it another way, if we wanted to create an arbitrary field on Todo called textWithFoo, we could leave the cache defaults as is, and create a resolver like
(obj, args, ctx) => obj.text + ' and FOO!'
In this case, a default resolver would do us no good because the objects stored in the cache don't have a textWithFoo property, so we write our own resolver.
What's important to keep in mind is that a query like todos is just a field too (in this case, it's a field on the Query Type). It behaves pretty much the same way any other field does (including the default resolver behavior). With apollo-link-state, though, the data structure you define under defaults becomes the parent or "root" value for your queries.
In your sample code, your defaults include a single property (todos). Because that's a property on the root object, we can fetch it with a query called todos and still get back the data even without a resolver. The default resolver for the todos field will look in the root object (in this case your cache), see a property called todos and return that.
On the flip side, a query like todo (singular) doesn't have a matching property in the root (cache). You need to write a resolver for it to have it return data. Similarly, if you want to manipulate the data before returning it in the query (with or without arguments), you need to include a resolver.

Jest expect().toEqual() not throwing error

I expected the following sample test to fail if I use toEqual(), but it passes:
it('sample test to check toEqual and toBe', () => {
const expectedAction = {test: '123', value: undefined};
const actualAction = {test: '123'};
expect(expectedAction).toEqual(actualAction);
})
The same test fails if I use .toBe(). However, if I fix the test case like this:
it('sample test to check toEqual and toBe', () => {
const expectedAction = {test: '123', value: '123'};
const actualAction = {test: '123', '123'};
expect(expectedAction).toBe(actualAction);
});
it again fails saying that "Compared values have no visual difference".
Is the behaviour correct? How to modify my test case so that it fails correctly.
If you really need it to be considered as different, one option would be to use Jest snapshot test, like:
expect(expectedAction).toMatchSnapshot();
The first time, it will create a snapshot file and print the javascript object to it, when you run the test again, it will compare it to the snapshot.
Most of the times, the snapshots are used to compare the component rendered tree, but you can use it for any javascript object.
The first one passes cause toEqual compares every element of your objects with each other, so in your case
expectedAction.test === actualAction.test
as both are '123'
but the same is true for
expectedAction.value === actualAction.value
as both are undefined
The second test fails cause toBe uses === to compare the two objects which will of cause fail as they are not the same instances. The only way that an object will passes toBe would be to use itself for comparison:
expect(expectedAction).toBe(expectedAction)

How to check the type of a field before checking the value in rethinkdb?

I have few tables in rethinkdb with very varied datasets. Mostly because over time, out of simple string properties complex objects were created to be more expressive.
When I run a query, I'm making sure that all fields exist, with the hasFields - function. But what if I want to run a RegExp query on my Message property, which can be of type string or object. Of course if it is an object, I don't care about the row, but instead of ignoring it, rethinkdb throws the error:
Unhandled rejection RqlRuntimeError: Expected type STRING but found OBJECT in...
Can I somehow use typeOf to first determine the type, before running the query?
Or what would be a good way to do this?
Your question is not 100% clear to me so I'm going to restate the problem to make sure my solution gets sense.
Problem
Get all documents where the message property is of type object or the message property is a string and matches a particular regular expression (using the match method).
Solution
You basically need an if statement. For that, you can use the r.branch to 'branch' your conditions depending on these things.
Here's a very long, but clear example on how to do this:
Let's say you have these documents and you want all documents where the message property is an object or a string that has the substring 'string'. The documents look like this:
{
"id": "a1a17705-e7b0-4c84-b9d5-8a51f4599eeb" ,
"message": "invalid"
}, {
"id": "efa3e26f-2083-4066-93ac-227697476f75" ,
"message": "this is a string"
}, {
"id": "80f55c96-1960-4c38-9810-a76aef60d678" ,
"not_messages": "hello"
}, {
"id": "d59d4e9b-f1dd-4d23-a3ef-f984c2361226" ,
"message": {
"exists": true ,
"text": "this is a string"
}
}
For that , you can use the following query:
r.table('messages')
.hasFields('message') // only get document with the `message` property
.filter(function (row) {
return r.branch( // Check if it's an object
row('message').typeOf().eq('OBJECT'), // return true if it's an object
true,
r.branch( // Check if it's a string
row('message').typeOf().eq('STRING'),
r.branch( // Only return true if the `message` property ...
row('message').match('string'), // has the substring `string`
true,
false // return `false` if it's a string but doesn't match our regex
),
false // return `false` if it's neither a string or an object
)
)
})
Again this query is long and could be written a lot more elegantly, but it explains the use of branch very clearly.
A shorter way of writing this query is this:
r.table('messages')
.hasFields('message')
.filter(function (row) {
return
row('message').typeOf().eq('OBJECT')
.or(
row('message').typeOf().eq('STRING').and(row('message').match('string'))
)
})
This basically uses the and and or methods instead of branch.
This query will return you all registers on table message that have the field message and the field is String.
Cheers.
r.db('test').table('message').hasFields('message')
.filter(function (row) {
return row('message').typeOf().eq('STRING')
})