/spec/aef/weekling/week_spec.rb

https://gitlab.com/weekling/weekling · Ruby · 612 lines · 508 code · 86 blank · 18 comment · 16 complexity · 6c3def34e7fc8d9997235a3e773b7fa8 MD5 · raw file

  1. # encoding: UTF-8
  2. =begin
  3. Copyright Alexander E. Fischer <aef@raxys.net>, 2012
  4. This file is part of Weekling.
  5. Permission to use, copy, modify, and/or distribute this software for any
  6. purpose with or without fee is hereby granted, provided that the above
  7. copyright notice and this permission notice appear in all copies.
  8. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
  9. REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  10. FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
  11. INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  12. LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  13. OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  14. PERFORMANCE OF THIS SOFTWARE.
  15. =end
  16. require 'spec_helper'
  17. require 'aef/weekling/week'
  18. require 'ostruct'
  19. describe Aef::Weekling::Week do
  20. [:today, :now].each do |method|
  21. context ".#{method}" do
  22. it "should find the current week" do
  23. week = described_class.method(method).call
  24. today = Date.today
  25. week.year.should eql Aef::Weekling::Year.new(today.year)
  26. week.index.should eql today.cweek
  27. end
  28. end
  29. end
  30. context ".parse" do
  31. it "should recognize an ancient week" do
  32. week = described_class.parse('-1503-W50')
  33. week.year.should eql Aef::Weekling::Year.new(-1503)
  34. week.index.should eql 50
  35. end
  36. it "should recognize a normal week" do
  37. week = described_class.parse('2011-W30')
  38. week.year.should eql Aef::Weekling::Year.new(2011)
  39. week.index.should eql 30
  40. end
  41. it "should recognize a post apocalyptic week" do
  42. week = described_class.parse('50023-W03')
  43. week.year.should eql Aef::Weekling::Year.new(50023)
  44. week.index.should eql 3
  45. end
  46. it "should report being unable to parse the given String" do
  47. lambda{
  48. described_class.parse('no week!')
  49. }.should raise_error(ArgumentError, 'No week found for parsing')
  50. end
  51. end
  52. context ".new" do
  53. it "should complain about a param of invalid type" do
  54. lambda {
  55. described_class.new(123)
  56. }.should raise_error(ArgumentError, 'A single argument must either respond to #year and #index or to #to_date')
  57. end
  58. it "should complain about less than one argument" do
  59. lambda {
  60. described_class.new
  61. }.should raise_error(ArgumentError, 'wrong number of arguments (0 for 1..2)')
  62. end
  63. it "should complain about more than two arguments" do
  64. lambda {
  65. described_class.new(123, 456, 789)
  66. }.should raise_error(ArgumentError, 'wrong number of arguments (3 for 1..2)')
  67. end
  68. it "should be able to initialize an ancient week by year and index" do
  69. week = described_class.new(-1691, 11)
  70. week.year.should eql Aef::Weekling::Year.new(-1691)
  71. week.index.should eql 11
  72. end
  73. it "should be able to initialize a normal week by year and index" do
  74. week = described_class.new(2012, 40)
  75. week.year.should eql Aef::Weekling::Year.new(2012)
  76. week.index.should eql 40
  77. end
  78. it "should be able to initialize a post apocalyptic week by year and index" do
  79. week = described_class.new(23017, 29)
  80. week.year.should eql Aef::Weekling::Year.new(23017)
  81. week.index.should eql 29
  82. end
  83. it "should be able to initialize a week by a given Week object" do
  84. old_week = described_class.new(2011, 30)
  85. week = described_class.new(old_week)
  86. week.year.should eql old_week.year
  87. week.index.should eql old_week.index
  88. end
  89. it "should be able to initialize a week by a given Date object" do
  90. date = Date.today
  91. week = described_class.new(date)
  92. week.year.should eql Aef::Weekling::Year.new(date.year)
  93. week.index.should eql date.cweek
  94. end
  95. it "should be able to initialize the last week of a year by a given Date object which is already in the following year" do
  96. date = Date.new(1802, 1, 1)
  97. week = described_class.new(date)
  98. week.year.should eql Aef::Weekling::Year.new(1801)
  99. week.index.should eql 53
  100. end
  101. it "should be able to initialize the first week of a year by a given Date object which is still in the previous year" do
  102. date = Date.new(2008, 12, 30)
  103. week = described_class.new(date)
  104. week.year.should eql Aef::Weekling::Year.new(2009)
  105. week.index.should eql 1
  106. end
  107. it "should be able to initialize a week by a given DateTime object" do
  108. date = DateTime.now
  109. week = described_class.new(date)
  110. week.year.should eql Aef::Weekling::Year.new(date.year)
  111. week.index.should eql date.cweek
  112. end
  113. it "should be able to initialize a week by a given Time object" do
  114. time = Time.now
  115. week = described_class.new(time)
  116. date = time.to_date
  117. week.year.should eql Aef::Weekling::Year.new(date.year)
  118. week.index.should eql date.cweek
  119. end
  120. it "should accept week 53 for year in which one exists" do
  121. lambda{
  122. described_class.new(2015, 53)
  123. }.should_not raise_error
  124. end
  125. it "should report week 53 doesn't exist in the given year" do
  126. lambda{
  127. described_class.new(2011, 53)
  128. }.should raise_error(ArgumentError, /Index .* is invalid. Year .* has only 52 weeks/)
  129. end
  130. it "should always report if weeks below index 1 are given" do
  131. lambda{
  132. described_class.new(2011, 0)
  133. }.should raise_error(ArgumentError, /Index .* is invalid. Index can never be lower than 1 or higher than 53/)
  134. end
  135. it "should always report if weeks above index 53 are given" do
  136. lambda{
  137. described_class.new(2011, 54)
  138. }.should raise_error(ArgumentError, /Index .* is invalid. Index can never be lower than 1 or higher than 53/)
  139. end
  140. end
  141. context "#== (type independent equality)" do
  142. it "should be true if year and index match" do
  143. week = described_class.new(2012, 1)
  144. other = described_class.new(2012, 1)
  145. week.should == other
  146. end
  147. it "should be true if year and index match, independent of the other object's type" do
  148. week = described_class.new(2012, 1)
  149. other = OpenStruct.new
  150. other.year = Aef::Weekling::Year.new(2012)
  151. other.index = 1
  152. week.should == other
  153. end
  154. it "should be false if year matches but not index" do
  155. week = described_class.new(2012, 1)
  156. other = described_class.new(2012, 13)
  157. week.should_not == other
  158. end
  159. it "should be false if year matches but not index, independent of the other object's type" do
  160. week = described_class.new(2012, 1)
  161. other = OpenStruct.new
  162. other.year = Aef::Weekling::Year.new(2012)
  163. other.index = 13
  164. week.should_not == other
  165. end
  166. it "should be false if index matches but not year" do
  167. week = described_class.new(2012, 1)
  168. other = described_class.new(2005, 1)
  169. week.should_not == other
  170. end
  171. it "should be false if index matches but not year, independent of the other object's type" do
  172. week = described_class.new(2012, 1)
  173. other = OpenStruct.new
  174. other.year = Aef::Weekling::Year.new(2005)
  175. other.index = 1
  176. week.should_not == other
  177. end
  178. it "should be false if both index and year do not match" do
  179. week = described_class.new(2012, 1)
  180. other = described_class.new(2005, 13)
  181. week.should_not == other
  182. end
  183. it "should be false if both index and year do not match, independent of the other object's type" do
  184. week = described_class.new(2012, 1)
  185. other = OpenStruct.new
  186. other.year = Aef::Weekling::Year.new(2005)
  187. other.index = 13
  188. week.should_not == other
  189. end
  190. end
  191. context "#eql? (type dependant equality)" do
  192. it "should be true if year and index and type matches and of same class" do
  193. week = described_class.new(2012, 1)
  194. other = described_class.new(2012, 1)
  195. week.should eql other
  196. end
  197. it "should be true if year and index and type matches and of inheriting class" do
  198. week = described_class.new(2012, 1)
  199. inheriting_class = Class.new(described_class)
  200. other = inheriting_class.new(2012, 1)
  201. week.should eql other
  202. end
  203. it "should be false if year and index match but type differs" do
  204. week = described_class.new(2012, 1)
  205. other = OpenStruct.new
  206. other.year = Aef::Weekling::Year.new(2012)
  207. other.index = 1
  208. week.should_not eql other
  209. end
  210. it "should be false if year matches but not index" do
  211. week = described_class.new(2012, 1)
  212. other = described_class.new(2012, 13)
  213. week.should_not eql other
  214. end
  215. it "should be false if index matches but not year" do
  216. week = described_class.new(2012, 1)
  217. other = described_class.new(2005, 1)
  218. week.should_not eql other
  219. end
  220. it "should be false if both index and year do not match" do
  221. week = described_class.new(2012, 1)
  222. other = described_class.new(2005, 13)
  223. week.should_not eql other
  224. end
  225. end
  226. context "#hash" do
  227. it "should return Integers" do
  228. a_week = described_class.new(2012, 5)
  229. another_week = described_class.new(2012, 6)
  230. a_week.hash.should be_a(Integer)
  231. another_week.hash.should be_a(Integer)
  232. end
  233. it "should discriminate a week from another one" do
  234. a_week = described_class.new(2012, 5)
  235. another_week = described_class.new(2012, 6)
  236. a_week.hash.should_not == another_week.hash
  237. end
  238. end
  239. context "#<=>" do
  240. it "should correctly determine the order of weeks based on year" do
  241. lower_week = described_class.new(2011, 14)
  242. higher_week = described_class.new(2012, 14)
  243. lower_week.should < higher_week
  244. end
  245. it "should correctly determine the order of weeks based on year, independent of type" do
  246. lower_week = described_class.new(2011, 14)
  247. higher_week = OpenStruct.new
  248. higher_week.year = Aef::Weekling::Year.new(2012)
  249. higher_week.index = 14
  250. lower_week.should < higher_week
  251. end
  252. it "should correctly determine the order of weeks based on index" do
  253. lower_week = described_class.new(2011, 14)
  254. higher_week = described_class.new(2011, 15)
  255. lower_week.should < higher_week
  256. end
  257. it "should correctly determine the order of weeks based on index, independent of type" do
  258. lower_week = described_class.new(2011, 14)
  259. higher_week = OpenStruct.new
  260. higher_week.year = Aef::Weekling::Year.new(2011)
  261. higher_week.index = 15
  262. lower_week.should < higher_week
  263. end
  264. it "should prioritize the order years when determining the order of weeks" do
  265. lower_week = described_class.new(2011, 14)
  266. higher_week = described_class.new(2012, 13)
  267. lower_week.should < higher_week
  268. end
  269. it "should prioritize the order years when determining the order of weeks, independent of type" do
  270. lower_week = described_class.new(2011, 14)
  271. higher_week = OpenStruct.new
  272. higher_week.year = Aef::Weekling::Year.new(2012)
  273. higher_week.index = 13
  274. lower_week.should < higher_week
  275. end
  276. end
  277. context "#to_s" do
  278. it "should be able to display an ancient week" do
  279. week = described_class.new(-1503, 50)
  280. week.to_s.should eql '-1503-W50'
  281. end
  282. it "should be able to display a normal week" do
  283. week = described_class.new(2011, 30)
  284. week.to_s.should eql '2011-W30'
  285. end
  286. it "should be able to display a post apocalyptic week" do
  287. week = described_class.new(50023, 3)
  288. week.to_s.should eql '50023-W03'
  289. end
  290. end
  291. context "#inspect" do
  292. it "should be able to display an ancient week" do
  293. week = described_class.new(-1503, 50)
  294. week.inspect.should eql '#<Aef::Weekling::Week: -1503-W50>'
  295. end
  296. it "should be able to display a normal week" do
  297. week = described_class.new(2011, 30)
  298. week.inspect.should eql '#<Aef::Weekling::Week: 2011-W30>'
  299. end
  300. it "should be able to display a post apocalyptic week" do
  301. week = described_class.new(50023, 3)
  302. week.inspect.should eql '#<Aef::Weekling::Week: 50023-W03>'
  303. end
  304. end
  305. context "#to_week" do
  306. it "should return itself" do
  307. week = described_class.new(2011, 30)
  308. week.to_week.should equal(week)
  309. end
  310. end
  311. [:next, :succ].each do |method|
  312. context "##{method}" do
  313. it "should return the next week" do
  314. described_class.new(2011, 19).method(method).call.should eql described_class.new(2011, 20)
  315. end
  316. it "should return the next week at the end of a year" do
  317. described_class.new(2011, 52).method(method).call.should eql described_class.new(2012, 1)
  318. end
  319. it "should return the next week one week before the end of a year with 53 weeks" do
  320. described_class.new(2015, 52).method(method).call.should eql described_class.new(2015, 53)
  321. end
  322. it "should return the next week at the end of a year with 53 weeks" do
  323. described_class.new(2015, 53).method(method).call.should eql described_class.new(2016, 1)
  324. end
  325. end
  326. end
  327. [:previous, :pred].each do |method|
  328. context "##{method}" do
  329. it "should return the previous week" do
  330. described_class.new(2011, 20).method(method).call.should eql described_class.new(2011, 19)
  331. end
  332. it "should return the previous week at the beginning of a year" do
  333. described_class.new(2012, 1).method(method).call.should eql described_class.new(2011, 52)
  334. end
  335. it "should return the previous week at the beginning of a year after one with 53 weeks" do
  336. described_class.new(2016, 1).method(method).call.should eql described_class.new(2015, 53)
  337. end
  338. it "should return the previous week at the end of a year with 53 weeks" do
  339. described_class.new(2015, 53).method(method).call.should eql described_class.new(2015, 52)
  340. end
  341. end
  342. end
  343. context "#+" do
  344. it "should be able to add a positive amount of weeks" do
  345. (described_class.new(1998, 10) + 15).should eql described_class.new(1998, 25)
  346. end
  347. it "should be able to add a positive amount of weeks so that the result isn't in the year anymore" do
  348. (described_class.new(1996, 48) + 8).should eql described_class.new(1997, 4)
  349. end
  350. it "should be able to add a positive amount of weeks so that the result isn't in the year with 53 weeks anymore" do
  351. (described_class.new(2004, 48) + 8).should eql described_class.new(2005, 3)
  352. end
  353. it "should be able to add a negative amount of weeks" do
  354. (described_class.new(1998, 20) + -15).should eql described_class.new(1998, 5)
  355. end
  356. it "should be able to add a negative amount of weeks so that the result isn't in the year anymore" do
  357. (described_class.new(1998, 10) + -12).should eql described_class.new(1997, 50)
  358. end
  359. it "should be able to add a negative amount of weeks so that the result is in the previous year which has 53 weeks" do
  360. (described_class.new(2005, 23) + -25).should eql described_class.new(2004, 51)
  361. end
  362. end
  363. context "#-" do
  364. it "should be able to subtract a positive amount of weeks" do
  365. (described_class.new(1998, 37) - 15).should eql described_class.new(1998, 22)
  366. end
  367. it "should be able to subtract a positive amount of weeks so that the result isn't in the year anymore" do
  368. (described_class.new(1998, 48) - 53).should eql described_class.new(1997, 47)
  369. end
  370. it "should be able to subtract a positive amount of weeks so that the result is in the previous year which has 53 weeks" do
  371. (described_class.new(2005, 16) - 32).should eql described_class.new(2004, 37)
  372. end
  373. it "should be able to subtract a negative amount of weeks" do
  374. (described_class.new(1998, 20) - -15).should eql described_class.new(1998, 35)
  375. end
  376. it "should be able to subtract a negative amount of weeks so that the result isn't in the year anymore" do
  377. (described_class.new(1996, 40) - -23).should eql described_class.new(1997, 11)
  378. end
  379. it "should be able to subtract a negative amount of weeks so that the result isn't in the year with 53 weeks anymore" do
  380. (described_class.new(2004, 49) - -31).should eql described_class.new(2005, 27)
  381. end
  382. end
  383. context "#until_index" do
  384. it "should return a range ending in the current year if the given index is greater to the weeks index" do
  385. week = described_class.new(2011, 13)
  386. week.until_index(46).should eql (week .. described_class.new(2011, 46))
  387. end
  388. it "should return a range ending in the next year if the given index is equal to the weeks index" do
  389. week = described_class.new(2011, 13)
  390. week.until_index(13).should eql (week .. described_class.new(2012, 13))
  391. end
  392. it "should return a range ending in the next year if the given index is equal to the weeks index" do
  393. week = described_class.new(2011, 13)
  394. week.until_index(3).should eql (week .. described_class.new(2012, 3))
  395. end
  396. end
  397. context "#even?" do
  398. it "should be true if the index is even" do
  399. described_class.new(420, 6).should be_even
  400. described_class.new(2011, 42).should be_even
  401. described_class.new(25043, 28).should be_even
  402. end
  403. it "should be false if the index is odd" do
  404. described_class.new(420, 7).should_not be_even
  405. described_class.new(2011, 43).should_not be_even
  406. described_class.new(25043, 29).should_not be_even
  407. end
  408. end
  409. context "#odd?" do
  410. it "should be true if the index is odd" do
  411. described_class.new(420, 7).should be_odd
  412. described_class.new(2011, 43).should be_odd
  413. described_class.new(25043, 29).should be_odd
  414. end
  415. it "should be false if the index is even" do
  416. described_class.new(420, 6).should_not be_odd
  417. described_class.new(2011, 42).should_not be_odd
  418. described_class.new(25043, 28).should_not be_odd
  419. end
  420. end
  421. context "#days" do
  422. it "should return a range of the weeks days" do
  423. described_class.new(2011, 15).days.should eql(
  424. (Aef::Weekling::WeekDay.new(2011, 15, 1)..Aef::Weekling::WeekDay.new(2011, 15, 7)))
  425. end
  426. end
  427. context "#day" do
  428. it "should return a day by index" do
  429. described_class.new(2011, 15).day(1).should eql Aef::Weekling::WeekDay.new(2011, 15, 1)
  430. end
  431. it "should return a day by symbol" do
  432. described_class.new(2011, 15).day(:friday).should eql Aef::Weekling::WeekDay.new(2011, 15, 5)
  433. end
  434. end
  435. context "weekday methods" do
  436. before(:all) do
  437. @week = described_class.new(2011, 17)
  438. end
  439. it "should deliver monday" do
  440. @week.monday.should eql Aef::Weekling::WeekDay.new(@week, 1)
  441. end
  442. it "should deliver tuesday" do
  443. @week.tuesday.should eql Aef::Weekling::WeekDay.new(@week, 2)
  444. end
  445. it "should deliver wednesday" do
  446. @week.wednesday.should eql Aef::Weekling::WeekDay.new(@week, 3)
  447. end
  448. it "should deliver thursday" do
  449. @week.thursday.should eql Aef::Weekling::WeekDay.new(@week, 4)
  450. end
  451. it "should deliver friday" do
  452. @week.friday.should eql Aef::Weekling::WeekDay.new(@week, 5)
  453. end
  454. it "should deliver saturday" do
  455. @week.saturday.should eql Aef::Weekling::WeekDay.new(@week, 6)
  456. end
  457. it "should deliver sunday" do
  458. @week.sunday.should eql Aef::Weekling::WeekDay.new(@week, 7)
  459. end
  460. it "should deliver the weekend" do
  461. @week.weekend.should eql [Aef::Weekling::WeekDay.new(@week, 6), Aef::Weekling::WeekDay.new(@week, 7)]
  462. end
  463. end
  464. end