Prepping for working on a feature at $work that involves limiting documents by relative time, I hashed out the following steps. Posting here in case they prove useful for anyone.
I want to be able to specify an arbitrary time, in english, relative to the current time, in my Cucumber steps. For example,
Scenario: Only posts from the last two months are shown
Given the following posts:
| title | posted_at |
| recent post | 2 days ago |
| recent post 2 | yesterday |
| older post | 2 months ago |
| really old post | 2 months, 1 day ago |
| tomorrow's post | 1 day from now |
When I go to the posts page
Then I should see 3 postsThe desire, there, is to be able to specify a date relative to the current time, in plain english. The tricky bit is being able to chain them together, as in 1 year, 3 months, 2 days ago
I got this worked out by stringing a few regular expressions together in my step definition helper. It depends on the 2.days.ago type dsl in ActiveSupport.
Given /^the following posts?:?/ do |table| table.map_column!('posted_at'){|date| interpret_time(date) } table.hashes.each{|hash| Factory :post, hash} end
def interpret_time(time) return nil if time.blank? return time if time.kind_of?(Time) or time.kind_of?(Date) named_time(time) || time_by_regex(time) || Time.parse(time) end def named_time(time) case time.downcase when "today" : Date.today when "now" : Time.now # etc ... else nil end end def time_by_regex(time) directional_regex = /(ago|from now)/i time_regex = /(\d+) (minute|hour|day|week|month|year)s?/i direction = time.scan(directional_regex).flatten shifts = time.scan(time_regex) return nil if direction.empty? or shifts.empty? forward = direction.first == "from now" result = Time.now shifts.each do |count, unit| #depends on the 1.week type DSL for time measurements adjust = count.to_i.send(unit) # move time in correct direction result = forward ? (result + adjust) : (result - adjust) end result end
Man, I miss Ruby.