Given When then scenario for automatic email notification - bdd

How would you write a Given when then construct for a email notification scenario where a notification has to be sent 1 business day after a particular state change?
Does this look right?
Given that I'm the system
and the user of a particular type T
and the state is S
When it is 1 business day after the date state was changed to x
then send an email notification with xxx content.
The reason I have a doubt is that my understanding is that Given section us for preconditions which in this cases is A. particular type of user, B. state is S and C. it is 1 day past a the date the state changed.
If all these preconditions are in Given section, what will be in the when section? My understanding was that 'when' section is for the event trigger. There's no action other than running the notification job. So would this be correct?
Given the user of a particular type T
and the state is S
and it is 1 business day after the date state was changed to x
When the email notification process triggered
then send an email notification to all users of type T with xxx content.
I'd appreciate your thoughts

You are on the right track!
So as you said before When is a trigger, so lets look into this deeper.
Gherkin is used for Behavior Driven Development (BDD) in that you are trying to simulate behavior.
Given - Input - Prerequisites
These are things that need are expected before the action or trigger occurs. They set up your tests for the action that will occur.
When - Trigger - Action
These are the users behavior that triggers the result. This is the B in BDD
Then - Output - Result
This is the end result, what should the user expect when the behavior completes.
Where You Stand
So you are in an interesting situation because as you pointed out, there is no behavior. So heres the tricky part, while having a Given-When-Then format is nice, its totally valid to have a Given-Then or a When-Then format as well in cases where there is no solid user behavior. So in that case:
Given it is 1 business day after the date state was changed to x
and
When it is 1 business day after the date state was changed to x
Are both equally as valid.
In regards to your second code block, the question you need to ask yourself is the email notification process triggered a trigger or a result? Personally I would say it is a result of the Inputs. If you do think you need it then I think you should write your test like this:
Given there is a user of type T
And the state is S
And it is 1 business day after the date state was changed to x
Then the email notification process should have triggered
And send an email notification to all users of type T with xxx content.
Bonus -- How to word your test and avoid implementation language
Not that you asked, but there is actually a way to improve your tests wording. You want to decouple your test from the actual implementation. What this means is avoid words like Send, Click, or Type and focus on behavior and result. Taking your test I would reword it like this:
Given there is a user of type T
And the state is S
And it is 1 business day after the date state was changed to x
Then all users of type T should be notified of xxx
I removed the email notification step because that can be inferred from the last step. I also decoupled the last step from implementation language. Whats important here isn't that the user gets sent an email, its that they are notified of the content. Your Given steps should also be changed in my opinion depending on your business logic as they are currently very coupled to your implementation.

Related

How to find recurrence exceptions through Microsoft Outlook Calendar Graph API

I'm currently using the Microsoft Graph API to sync calendar events to my local application. On my end, I don't care to save each individual occurrence in a series, but prefer instead to just save the series master and then extrapolate out the instances of the series myself. For this reason, I am using the /me/events call rather than the /me/calendarView call.
My problem is when editing a single occurrence in a series. After editing the single occurrence, I make the /me/events call and I can see the newly added "Exception" type -- which is great. However, I don't see how to relate that new event back to which occurrence was changed to cause the exception.
For example, if I have a weekly meeting on Monday at noon, and I change today's meeting from noon to 2:00, it's pretty easy to tell that today's meeting is the one that changed. But if I change today's meeting to Friday, how can I tell that it was today's meeting that changed and not next week's? Keep in mind that I am only storing the master, and not every single calendarView occurrence.
Another example is if I delete an occurrence. In this case, the /me/calendarView call will simply not return that occurrence anymore. No exception type is generated. And the series master returned from the /me/events call doesn't change at all to indicate that a date is missing.
The format that I'm used to is something like the iCal/vCal format, where there is a start date, end date, and then a list of exception dates. Using that format, I can easily tell from the series master which dates to skip, without needing to "render" the entire occurrence and skip the exceptions. And if an occurrence is deleted, it is added to the EXDATE list and then it is never considered on rendering. Does the Microsoft Graph API not have an easy way to see these changed/deleted occurrences?
I was having a similar issue, but I think I've now realized that Microsoft does not allow recurring events to move later than the next instance, or earlier than the preceding one (at least while using Outlook calendar in the browser). So you can always assume that the 3rd event is 3rd in the series, the 4th is 4th, etc.
So as long as you know the series number, you can locate it by getting all of the instances with /me/events/[event_id]/instances?startDateTime=[start_date_time]&endDateTime=[end_date_time].
The error in Outlook Calendar when I do this isn't very clear, so maybe something else is up, but I am able to move the exception events otherwise. Unfortunately, I'm not sure if there's a definite way to know what end_date_time to use, as events can be moved indefinitely later.
Based on the response object from the event marked as an exception, you can use the seriesMasterId to relate the exception to its parent recurrence.

Microsoft graph API: getting 5 next instances of recurring meeting

is there a way to query for next 5 instances of given series? I am querying using time-frame:
1. ask for all the meetings for next 7 days for all user events
2. Go over each event fetched and check if event has masterSerieId
3. Return matching instances.
This feels (and is) a bit painful.
Can i request next X instances of master series right away? I can't just simply or 'simply' get them based on recurrence rule, as some might have expired.
I could image I could ask for a year ahead and pass as a query parameter masterSeriesId and limit output with $top. Is that right approach?
Based on this document, you could call /events//instances – given a start time, returns all instances in the requested time frame of the meeting specified by the provided series master ID

How to add Data to Firebase?

My goal is to add +1 every day to a global variable in Firebase to track how many days have passed. I'm building an app that give new facts every day, and at the 19:00 UTC time marker, I want the case statement number (the day global day variable) to increment by +1.
Some have suggested that I compare two dates and get the days that have passed that way. If I were to do that, I could hard code the initial time when I first want the app to start at 19:00 some day. Then when the function reached1900UTC() is called everyday thereafter, compare it to a Firebase timestamp of that current time which should be 19:00. In theory, it should show that 1 day or more day has passed.
This is the best solution so far, thanks to #DavidSeek and #Jay, but I would still like to figure it out with concurrent writes if anyone has a solution in that front. Until then, I'm marking David's answer as the correct one.
How would I make it so it can't increase more than +1 if multiple people call this? Because my fear is that, when say, 100 people calls this function, it increases by + 1 for every person that has called it.
My app works on a global time, and this function is called every day at 19:00 UTC. So when that function is called I want the day count to increase by one.
You should use transactions to handle concurrent writes:
https://firebase.google.com/docs/database/ios/read-and-write#save_data_as_transactions
You may know this but Firebase doesn't have a way to auto-increment a counter as there's no server side logic, so having a counter increment at 19:00 UTC isn't going to be possible without interaction from a client that happens to be logged on at that time.
That being said, it's fairly straightforward to have the first user that logs in increment that counter - then any other clients logging in after that would not increment it and would have access to that day's new content.
Take a look at Zapier.com - that's a service that can fire time based triggers for your app which may do the trick.
As of this writing, Zapier and Firebase don't play nice together, however, there are a number of other trigger options that Zapier can do with your app while continuing to use Firebase for storage.
One other thought...
Instead of dealing with counters and counting days, why not just have each day's content stored within a node for each day and when each user logs on, the app get's that days content:
2016-10-10
fact: "The Earth is an Oblate Spheroid"
2016-10-11
fact: "Milli Vanilli is neither a Milli or a Vanilli. Discuss."
2016-10-12
fact: "George Washington did not have a middle name"
This would eliminate a number of issues such as counters, updates, concurrent writing to Firebase, triggers etc.
It's also dynamic and expandable and a user could easily see that day's facts or the fact for any prior day(s)
I'm trying to split your question into different sections.
1) If you want to use a global variable to count the days from, let's say, today. Then I would set a timestamp hardcoded into the App that sets the NSDate.
Then In my App, when I need to know the days that have been passed by, I would call a function counting the days from the timestamp to NSDate().
2) If you have a function in your App that counts a +1 into a Firebase, then your fear is correct. It would count +1 for every person that uses the App.
3) If you want every User to have a variable count since when they use their App, then I would handle User registration. So I have a "UserID" and then I would set a Firebase tree like that:
UserID
------->
FirstOpen
-------> Date
That way you could handle each User's first open.
Then you are able to set a timestamp AND call +1 for every user independently. Because then you set the +1 for every user into their UserID .child

Ruby on Rails - Next Day creates a model

I want to create an application using Ruby,where a user can plan his next day, so when he is logged-in he should be able to plan the following day and at midnight the next day should be automatically created.
But I don't know how to do this.
Any suggestions?
Max
Start by drawing out your schema on some paper, with a pencil. Think about all the real life things you want to model, and how they relate to each other. You should understand the object-relational model before doing this. Your thought process will be something like
Ok, so the user wants to plan something. Let's call the "thing" an Event. So, draw a box for event. Now, what are the characteristics of an Event? It starts at a particular time, and it ends at a particular time, and it has a name. So, it will need to have start_time, end_time and name fields.*
We've also got users, so we'll need a User box. A user has_many events, so draw an arrow from Event to User to show that the Event belongs_to the user.
There's your basic schema. Note how you don't have a Day box. That's because you don't need a Day model. All an event has to do is store when it starts and ends. When you come to DISPLAY the data, you can organise it by days if you want, but that's just a view onto the data.
*when i say "Time" here, i mean an instance of the Time class, which holds the date and time of day: it's a specific point in time, not just a time of day like "3 o'clock" or something. So a time would be like "2016-02-15 16:19:09" for example (how it's stored in my database)

CRM 2011 Workflow not updating field

I have a simple workflow that runs on Create. If field X is yes, change Allow Email to Allow.
I have also created a personal view with criteria Fields X = Yes and Allow Email = Do No Allow. This is to give me list of contact that missing out.
Looking at last 7 days records, everyday this workflow runs on around 600 new contacts and updates fields as expected. But I also noticed that small number of Contacts (about 30ish per day) do not get their Allow Email field updated to Allow even when they meet the criteria of the if condition.
At this point I checked at the WF history and very strangely it shows that the field should have been modified. (see screen shot)
Workflow did fire off
This contacts are not modified by any process or individual since the workflow had run
Workflow shows the usual green tick indicating that it did meet the criteria
Same workflow also updates 'Preferred language' and that seems to have updated fine for these contacts.
I have also double checked the Update property to make sure it set correctly.
Has anyone else seen this? This makes WF not 100% reliable for me!
Your workflow runs on Create.
If the record is created with Field X to No the workflow doesn't change the Allow value.
If a user change the Field X value to Yes after the record is created, you have the situation with records Field X Yes and Do Not Allow.
You wrote:
This contacts are not modified by any process or individual since the
workflow had run
to confirm this, did you check that the ModifiedOn date equals CreatedOn date? I suggest to turn on audit for Field X.
My guess is that you didn't set your workflow to run also when the Field X value change (and it should)

Resources