From 3e20bba1c5d6cccd9da1ab21572ed32ac1f5c03a Mon Sep 17 00:00:00 2001 From: jordanmarkham Date: Wed, 29 Jun 2022 19:49:31 +0200 Subject: [PATCH] Completed final challenge --- .rspec | 1 + Gemfile | 7 + Gemfile.lock | 26 +++ diary_design.md | 355 +++++++++++++++++++++++++++++++++++++++ lib/diary.rb | 44 +++++ lib/diary_entry.rb | 36 ++++ lib/todo.rb | 22 +++ lib/todo_list.rb | 28 +++ spec/diary_spec.rb | 78 +++++++++ spec/integration_spec.rb | 112 ++++++++++++ spec/spec_helper.rb | 98 +++++++++++ spec/todo_spec.rb | 41 +++++ 12 files changed, 848 insertions(+) create mode 100644 .rspec create mode 100644 Gemfile create mode 100644 Gemfile.lock create mode 100644 diary_design.md create mode 100644 lib/diary.rb create mode 100644 lib/diary_entry.rb create mode 100644 lib/todo.rb create mode 100644 lib/todo_list.rb create mode 100644 spec/diary_spec.rb create mode 100644 spec/integration_spec.rb create mode 100644 spec/spec_helper.rb create mode 100644 spec/todo_spec.rb diff --git a/.rspec b/.rspec new file mode 100644 index 0000000..c99d2e7 --- /dev/null +++ b/.rspec @@ -0,0 +1 @@ +--require spec_helper diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..cb7e0f7 --- /dev/null +++ b/Gemfile @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +source "https://rubygems.org" + +# gem "rails" + +gem "rspec", "~> 3.11" diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..2e6d410 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,26 @@ +GEM + remote: https://rubygems.org/ + specs: + diff-lcs (1.5.0) + rspec (3.11.0) + rspec-core (~> 3.11.0) + rspec-expectations (~> 3.11.0) + rspec-mocks (~> 3.11.0) + rspec-core (3.11.0) + rspec-support (~> 3.11.0) + rspec-expectations (3.11.0) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.11.0) + rspec-mocks (3.11.1) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.11.0) + rspec-support (3.11.0) + +PLATFORMS + arm64-darwin-21 + +DEPENDENCIES + rspec (~> 3.11) + +BUNDLED WITH + 2.3.16 diff --git a/diary_design.md b/diary_design.md new file mode 100644 index 0000000..adee2cc --- /dev/null +++ b/diary_design.md @@ -0,0 +1,355 @@ +PROBLEM + + +1. As a user +So that I can record my experiences +I want to keep a regular diary + + +Diary should accept entries - title and contents - +based on user input. + + +2. As a user +So that I can reflect on my experiences +I want to read my past diary entries + + +User should be able to access both specific and all entries. + + +3. As a user +So that I can reflect on my experiences in my busy day +I want to select diary entries to read based on how much time I have and my reading speed + + +Diary should be able to count words, and then use the result - along with a user's +inputted wpm and number of minutes available - to return the most appropriate entry +for the time provided. + +If they do not wish to read the entry provided, they should be able to view all +readable entries depending on the given wpm and available minutes. + + +4. As a user +So that I can keep track of my tasks +I want to keep a todo list along with my diary + + +TODO list should accept a string (task), and initially mark it as "incomplete". +The user should then be able to access all incomplete, completed and specific tasks. +They should also be able to mark tasks as complete. + +If all tasks are complete, the user should be able to mark all tasks at the same time. + + +5. As a user +So that I can keep track of my contacts +I want to see a list of all of the mobile phone numbers in all my diary entries + + +Diary should have a method which searches through all entries and returns any series of +UK phone numbers which are 11 characters long and begin with '0'. Must be unique. + + +CLASS SYSTEM + + +```ruby + +class Diary + def initialize #no args + #returns nothing, creates new Array and sets total_words to 0 + end + def add(entry) #instance of DiaryEntry class + #returns nothing, adds entry to all_entries array + end + def all #no args + #returns string (all titles + contents) + end + def count_words #no args + #returns integer (total words) + end + def reading_time(wpm) #integer + #returns integer (.ceil) total reading time + end + def find_best_entry_for_reading_time(wpm, minutes) #integers + #returns string (entry title and contents) + end + def all_readable_entries(wpm, minutes) #integers + #returns string (readable entries with word count) + end + def phone_numbers #no args + #returns array (with unique phone numbers in each element) + end +end + +class DiaryEntry + def initialize(title, contents) #strings + #returns nothing, creates instance variables + end + def title #no args + #returns string (title) + end + def contents #no args + #returns string (contents) + end + def count_words #no args + #returns integer (num of words) + end + def reading_time(wpm) #integer + #returns integer (.ceil) - reading time in minutes + end + def reading_chunk(wpm, minutes) #integers + #returns string (chunk of text) + end +end + +class TodoList + def initialize #no args + #returns nothing, creates new array + end + def add(todo) #instance of Todo class + #returns nothing + end + def incomplete #no args + #returns array of incomplete todos + end + def complete #no args + #returns array of complete todos + end + def give_up! #no args + #marks TODOs as complete + end +end + +class Todo + def initialize(task) #string + #returns nothing, creates instance variable with + #task details and completion status + end + def task #no args + #returns string (details of task) + end + def mark_done! #no args + #returns nothing + end + def done? #no args + #return true or false + end +end + +``` + + +INTEGRATION TESTS + + +```ruby + +#lib/integration_spec.rb + +#todolist + +"Adds + outputs only incomplete items" + todolist = TodoList.new + todo = Todo.new("I need to do this") + todolist.add(todo) + expect(todolist.incomplete).to eq ["I need to do this"] + +"Adds + outputs only completed items" + todolist = TodoList.new + todo = Todo.new("I need to do this") + todo_2 = Todo.new("I haven't done this yet.") + todo_3 = Todo.new("But I HAVE done this!") + todolist.add(todo) + todolist.add(todo_2) + todolist.add(todo_3) + todo.mark_done! + todo_3.mark_done! + expect(todolist.complete).to eq ["I need to do this", "But I HAVE done this!"] + +"Marks all tasks as completed" + todolist = TodoList.new + todo = Todo.new("I need to do this") + todo_2 = Todo.new("I haven't done this yet.") + todo_3 = Todo.new("But I WILL do this!") + todolist.add(todo) + todolist.add(todo_2) + todolist.add(todo_3) + todolist.give_up! + expect(todolist.complete).to eq ["I need to do this", "I haven't done this yet.", "But I WILL do this!"] + +#diary + +"Returns all diary entries" + diary = Diary.new + entry = DiaryEntry.new("Welcome", "Hello there! Welcome to this new Diary Entry.") + diary.add(entry) + expect(diary.all).to eq "Welcome: Hello there! Welcome to this new Diary Entry." + +"Returns number of words in all diary entries" + diary = Diary.new + entry = DiaryEntry.new("Welcome", "Hello there! Welcome to this new Diary Entry.") + diary.add(entry) + expect(diary.count_words).to eq 8 + +"Returns number of words in multiple diary entries" + diary = Diary.new + entry = DiaryEntry.new("Welcome", "Hello there! Welcome to this new Diary Entry.") + entryTwo = DiaryEntry.new("Second Entry", "It was a tough day today... hard work indeed!") + diary.add(entry) + diary.add(entryTwo) + expect(diary.count_words).to eq 17 + +"Returns correct reading time for all diary entries" + diary = Diary.new + entry = DiaryEntry.new("Welcome", "Hello there! Welcome to this new Diary Entry.") + entryTwo = DiaryEntry.new("Second Entry", "It was a tough day today... hard work indeed!") + entryThree = DiaryEntry.new("Third Entry", "Three! " * 300) + diary.add(entry) + diary.add(entryTwo) + diary.add(entryThree) + expect(diary.reading_time(2)).to eq 159 + +"Returns suitable entries for given reading time" + diary = Diary.new + entry = DiaryEntry.new("Welcome", "Hello there! Welcome to this new Diary Entry.") + entryTwo = DiaryEntry.new("Second Entry", "It was a tough day today... hard work indeed!") + entryThree = DiaryEntry.new("Third Entry", "Three! " * 300) + diary.add(entry) + diary.add(entryTwo) + diary.add(entryThree) + expect(diary.all_readable_entries(1, 8)).to eq "Welcome (8 words)" + +"Finds most suitable entry for given reading time" + diary = Diary.new + entry = DiaryEntry.new("Welcome", "Hello there! Welcome to this new Diary Entry.") + entryTwo = DiaryEntry.new("Second Entry", "It was a tough day today... hard work indeed!") + entryThree = DiaryEntry.new("Third Entry", "Three! " * 300) + diary.add(entry) + diary.add(entryTwo) + diary.add(entryThree) + expect(diary.find_best_entry_for_reading_time(1, 9)).to eq "Second Entry: It was a tough day today... hard work indeed!" + +"Outputs all phone numbers" + diary = Diary.new + entry = DiaryEntry.new("Welcome", "Hello 01980683829 and a good 07000232141 to you too!") + diary.add(entry) + expect(diary.phone_numbers).to eq ["01980683829", "07000232141"] + +"Outputs phone numbers from multiple diary entries (all unique)" + diary = Diary.new + entry = DiaryEntry.new("Welcome", "Hello 01980683829 and a good 07000232141 to you too!") + entryTwo = DiaryEntry.new("Second Entry", "My phone number is 02011323232, and my best friend's number is 07232848949. Note these down! As I said: 02011323232 and 07232848949 - don't forget!") + diary.add(entry) + diary.add(entryTwo) + expect(diary.phone_numbers).to eq ["01980683829", "07000232141", "02011323232", "07232848949"] + +``` + + +UNIT TESTS + + +```ruby + +#lib/todo_spec.rb + +#todolist + +"Outputs no completed items when none given" + todolist = TodoList.new + expect(todolist.complete).to eq [] + +"Outputs no incomplete items when none given" + todolist = TodoList.new + expect(todolist.incomplete).to eq [] + +"Marks nothing as complete if no tasks given" + todolist = TodoList.new + expect{ todolist.give_up! }.to raise_error "No tasks available!" + +#todo + +"Raises error if no task is provided" + expect{ Todo.new() }.to raise_error "No task provided!" + +"Returns task details to user" + todo = Todo.new("Run a marathon") + expect(todo.task).to eq "Run a marathon" + +"Returns task status - complete" + todo = Todo.new("Run a marathon") + todo.mark_done! + expect(todo.done?).to eq true + +"Returns task status - incomplete" + todo = Todo.new("Run a marathon") + expect(todo.done?).to eq false + +#lib/diary_spec.rb + +#diaryentry + +"Returns an error when no title or contents are provided" + expect{ DiaryEntry.new() }.to raise_error "Please provide a title and contents!" + +"Returns title of diary entry" + entry = DiaryEntry.new("title", "contents") + expect(entry.title).to eq "title" + +"Returns contents of diary entry" + entry = DiaryEntry.new("title", "contents") + expect(entry.contents).to eq "contents" + +"Returns number of words in diary entry" + entry = DiaryEntry.new("title", "contents contents contents") + expect(entry.count_words).to eq 3 + +"Returns reading time for a diary entry" + entry = DiaryEntry.new("title", "anything " * 300) + expect(entry.reading_time(150)).to eq 2 + +"Returns contents depending on wpm and time to read" + entry = DiaryEntry.new("title", "anything " * 100) + expect(entry.reading_chunk(20, 4)).to eq "anything " * 79 + "anything" + +"Returns contents incrementally when method runs multiple times" + entry = DiaryEntry.new("title", "hello there my name is jordan markham") + entry.reading_chunk(1, 1) + entry.reading_chunk(1, 1) + entry.reading_chunk(1, 3) + expect(entry.reading_chunk(1, 2)).to eq "jordan markham" + +#diary + +"Returns error if WPM is not provided when calculating reading_time" + diary = Diary.new + expect{diary.reading_time()}.to raise_error "Please provide WPM (int)!" + +"Returns error if string is provided instead of integer when calling reading_time" + diary = Diary.new + expect{diary.reading_time("hello")}.to raise_error "Please provide WPM (int)!" + +"Returns error if float is provided when calculating reading_time" + diary = Diary.new + expect{diary.reading_time(2.4)}.to raise_error "Please provide WPM (int)!" + +"Returns error if wrong/no value is provided in find_best_entry_for_reading_time" + diary = Diary.new + expect{diary.find_best_entry_for_reading_time()}.to raise_error "Please provide WPM and number of minutes available (int)!" + +"Returns error if no value is provided as one of the arguments for find_best_entry_for_reading_time" + diary = Diary.new + expect{diary.find_best_entry_for_reading_time(24)}.to raise_error "Please provide WPM and number of minutes available (int)!" + +"Returns error if an invalid value is provided as one of the arguments for find_best_entry_for_reading_time" + diary = Diary.new + expect{diary.find_best_entry_for_reading_time(24, "hello")}.to raise_error "Please provide WPM and number of minutes available (int)!" + +"Returns error if no entry is provided when executing .add" + diary = Diary.new + expect{diary.add()}.to raise_error "No entry provided!" + +``` \ No newline at end of file diff --git a/lib/diary.rb b/lib/diary.rb new file mode 100644 index 0000000..28465a3 --- /dev/null +++ b/lib/diary.rb @@ -0,0 +1,44 @@ +require 'diary_entry' + +class Diary + def initialize + @all_entries = Array.new + @total_words = 0 + end + + def add(entry = nil) + fail "No entry provided!" if entry == nil + @all_entries << entry + end + + def all + @all_entries.each { |element| return "#{element.title}: #{element.contents}"} + end + + def count_words + @total_words = 0 + @all_entries.each { |element| @total_words += element.count_words.to_i } + return @total_words + end + + def reading_time(wpm = nil) + fail "Please provide WPM (int)!" if wpm == nil || wpm.is_a?(String) || wpm.is_a?(Float) + return (count_words / wpm.to_f).ceil + end + + def find_best_entry_for_reading_time(wpm = nil, minutes = nil) + fail "Please provide WPM and number of minutes available (int)!" if wpm == nil || wpm.is_a?(String) || wpm.is_a?(Float) || minutes == nil || minutes.is_a?(String) || minutes.is_a?(Float) + readable_entry = @all_entries.filter { |elem| elem.reading_time(wpm) <= minutes }.max_by(&:count_words) + return "#{readable_entry.title}: #{readable_entry.contents}" + end + + def all_readable_entries(wpm = nil, minutes = nil) + fail "Please provide WPM and number of minutes available (int)!" if wpm == nil || wpm.is_a?(String) || wpm.is_a?(Float) || minutes == nil || minutes.is_a?(String) || minutes.is_a?(Float) + readable_list = @all_entries.filter { |elem| elem.reading_time(wpm) <= minutes } + readable_list.each { |element| return "#{element.title} (#{element.count_words} words)"} + end + + def phone_numbers + return @all_entries.map { |element| element.contents.scan(/0[0-9]{10}/).uniq }.flatten + end +end \ No newline at end of file diff --git a/lib/diary_entry.rb b/lib/diary_entry.rb new file mode 100644 index 0000000..7c63eeb --- /dev/null +++ b/lib/diary_entry.rb @@ -0,0 +1,36 @@ +class DiaryEntry + def initialize(title = nil, contents = "") # title, contents are strings + fail "Please provide a title and contents!" if title == nil + @title = title + @content_string = contents + @num_words_read = 0 + end + + def title + return @title.to_s + end + + def contents + return @content_string.to_s + end + + def count_words + return @content_string.split.size + end + + def reading_time(wpm = nil) + fail "Please provide WPM!" if wpm == nil || wpm.is_a?(String) || wpm.is_a?(Float) + return (count_words / wpm.to_f).ceil + end + + def reading_chunk(wpm = nil, minutes = nil) + fail "Please provide WPM and number of minutes available!" if wpm == nil || wpm.is_a?(String) || wpm.is_a?(Float) || minutes == nil || minutes.is_a?(String) || minutes.is_a?(Float) + words_to_return = wpm * minutes + if(@num_words_read + words_to_return > @content_string.split.size) + words_to_return = @content_string.split.size - @num_words_read + end + currentText = @content_string.split[@num_words_read..@num_words_read + words_to_return - 1].join(' ') + @num_words_read += words_to_return + return currentText + end +end \ No newline at end of file diff --git a/lib/todo.rb b/lib/todo.rb new file mode 100644 index 0000000..e621f52 --- /dev/null +++ b/lib/todo.rb @@ -0,0 +1,22 @@ +class Todo + def initialize(task = nil) # task is a string + fail "No task provided!" if task == nil + @task = [task, 'incomplete'] + end + + def task + return @task[0] + end + + def mark_done! + @task[1] = 'complete' + # Marks the todo as done + # Returns nothing + end + + def done? + return @task[1] == 'complete' ? true : false + # Returns true if the task is done + # Otherwise, false + end +end \ No newline at end of file diff --git a/lib/todo_list.rb b/lib/todo_list.rb new file mode 100644 index 0000000..87c9cf9 --- /dev/null +++ b/lib/todo_list.rb @@ -0,0 +1,28 @@ +require 'todo' + +class TodoList + def initialize + @list = Array.new + end + + def add(todo) # todo is an instance of Todo + @list << todo + # Returns nothing + end + + def incomplete + return @list.select{ |item| item.done? == false }.map{ |item| item.task } + # Returns all non-done todos + end + + def complete + return @list.select{ |item| item.done? == true }.map{ |item| item.task } + # Returns all complete todos + end + + def give_up! + fail "No tasks available!" if @list.empty? == true + @list.each{ |item| item.mark_done! } + # Marks all todos as complete + end +end \ No newline at end of file diff --git a/spec/diary_spec.rb b/spec/diary_spec.rb new file mode 100644 index 0000000..3f20011 --- /dev/null +++ b/spec/diary_spec.rb @@ -0,0 +1,78 @@ +require 'diary_entry' +require 'diary' + +RSpec.describe DiaryEntry do + it "Returns an error when no title or contents are provided" do + expect{ DiaryEntry.new() }.to raise_error "Please provide a title and contents!" + end + + it "Returns title of diary entry" do + entry = DiaryEntry.new("title", "contents") + expect(entry.title).to eq "title" + end + + it "Returns contents of diary entry" do + entry = DiaryEntry.new("title", "contents") + expect(entry.contents).to eq "contents" + end + + it "Returns number of words in diary entry" do + entry = DiaryEntry.new("title", "contents contents contents") + expect(entry.count_words).to eq 3 + end + + it "Returns reading time for a diary entry" do + entry = DiaryEntry.new("title", "anything " * 300) + expect(entry.reading_time(150)).to eq 2 + end + + it "Returns contents depending on wpm and time to read" do + entry = DiaryEntry.new("title", "anything " * 100) + expect(entry.reading_chunk(20, 4)).to eq "anything " * 79 + "anything" + end + + it "Returns contents incrementally when method runs multiple times" do + entry = DiaryEntry.new("title", "hello there my name is jordan markham") + entry.reading_chunk(1, 1) + entry.reading_chunk(1, 1) + entry.reading_chunk(1, 3) + expect(entry.reading_chunk(1, 2)).to eq "jordan markham" + end +end + +RSpec.describe Diary do + it "Returns error if WPM is not provided when calculating reading_time" do + diary = Diary.new + expect{diary.reading_time()}.to raise_error "Please provide WPM (int)!" + end + + it "Returns error if string is provided instead of integer when calling reading_time" do + diary = Diary.new + expect{diary.reading_time("hello")}.to raise_error "Please provide WPM (int)!" + end + + it "Returns error if float is provided when calculating reading_time" do + diary = Diary.new + expect{diary.reading_time(2.4)}.to raise_error "Please provide WPM (int)!" + end + + it "Returns error if wrong/no value is provided in find_best_entry_for_reading_time" do + diary = Diary.new + expect{diary.find_best_entry_for_reading_time()}.to raise_error "Please provide WPM and number of minutes available (int)!" + end + + it "Returns error if no value is provided as one of the arguments for find_best_entry_for_reading_time" do + diary = Diary.new + expect{diary.find_best_entry_for_reading_time(24)}.to raise_error "Please provide WPM and number of minutes available (int)!" + end + + it "Returns error if an invalid value is provided as one of the arguments for find_best_entry_for_reading_time" do + diary = Diary.new + expect{diary.find_best_entry_for_reading_time(24, "hello")}.to raise_error "Please provide WPM and number of minutes available (int)!" + end + + it "Returns error if no entry is provided when executing .add" do + diary = Diary.new + expect{diary.add()}.to raise_error "No entry provided!" + end +end \ No newline at end of file diff --git a/spec/integration_spec.rb b/spec/integration_spec.rb new file mode 100644 index 0000000..f2aa2d9 --- /dev/null +++ b/spec/integration_spec.rb @@ -0,0 +1,112 @@ +require "todo" +require "todo_list" +require "diary_entry" +require "diary" + +RSpec.describe TodoList do + it "Adds + outputs only incomplete items" do + todolist = TodoList.new + todo = Todo.new("I need to do this") + todolist.add(todo) + expect(todolist.incomplete).to eq ["I need to do this"] + end + + it "Adds + outputs only completed items" do + todolist = TodoList.new + todo = Todo.new("I need to do this") + todo_2 = Todo.new("I haven't done this yet.") + todo_3 = Todo.new("But I HAVE done this!") + todolist.add(todo) + todolist.add(todo_2) + todolist.add(todo_3) + todo.mark_done! + todo_3.mark_done! + expect(todolist.complete).to eq ["I need to do this", "But I HAVE done this!"] + end + + it "Marks all tasks as completed" do + todolist = TodoList.new + todo = Todo.new("I need to do this") + todo_2 = Todo.new("I haven't done this yet.") + todo_3 = Todo.new("But I WILL do this!") + todolist.add(todo) + todolist.add(todo_2) + todolist.add(todo_3) + todolist.give_up! + expect(todolist.complete).to eq ["I need to do this", "I haven't done this yet.", "But I WILL do this!"] + end +end + +RSpec.describe Diary do + it "Returns all diary entries" do + diary = Diary.new + entry = DiaryEntry.new("Welcome", "Hello there! Welcome to this new Diary Entry.") + diary.add(entry) + expect(diary.all).to eq "Welcome: Hello there! Welcome to this new Diary Entry." + end + + it "Returns number of words in all diary entries" do + diary = Diary.new + entry = DiaryEntry.new("Welcome", "Hello there! Welcome to this new Diary Entry.") + diary.add(entry) + expect(diary.count_words).to eq 8 + end + + it "Returns number of words in multiple diary entries" do + diary = Diary.new + entry = DiaryEntry.new("Welcome", "Hello there! Welcome to this new Diary Entry.") + entryTwo = DiaryEntry.new("Second Entry", "It was a tough day today... hard work indeed!") + diary.add(entry) + diary.add(entryTwo) + expect(diary.count_words).to eq 17 + end + + it "Returns correct reading time for all diary entries" do + diary = Diary.new + entry = DiaryEntry.new("Welcome", "Hello there! Welcome to this new Diary Entry.") + entryTwo = DiaryEntry.new("Second Entry", "It was a tough day today... hard work indeed!") + entryThree = DiaryEntry.new("Third Entry", "Three! " * 300) + diary.add(entry) + diary.add(entryTwo) + diary.add(entryThree) + expect(diary.reading_time(2)).to eq 159 + end + + it "Returns suitable entries for given reading time" do + diary = Diary.new + entry = DiaryEntry.new("Welcome", "Hello there! Welcome to this new Diary Entry.") + entryTwo = DiaryEntry.new("Second Entry", "It was a tough day today... hard work indeed!") + entryThree = DiaryEntry.new("Third Entry", "Three! " * 300) + diary.add(entry) + diary.add(entryTwo) + diary.add(entryThree) + expect(diary.all_readable_entries(1, 8)).to eq "Welcome (8 words)" + end + + it "Finds most suitable entry for given reading time" do + diary = Diary.new + entry = DiaryEntry.new("Welcome", "Hello there! Welcome to this new Diary Entry.") + entryTwo = DiaryEntry.new("Second Entry", "It was a tough day today... hard work indeed!") + entryThree = DiaryEntry.new("Third Entry", "Three! " * 300) + diary.add(entry) + diary.add(entryTwo) + diary.add(entryThree) + expect(diary.find_best_entry_for_reading_time(1, 9)).to eq "Second Entry: It was a tough day today... hard work indeed!" + end + + it "Outputs all phone numbers" do + diary = Diary.new + entry = DiaryEntry.new("Welcome", "Hello 01980683829 and a good 07000232141 to you too!") + diary.add(entry) + expect(diary.phone_numbers).to eq ["01980683829", "07000232141"] + end + + it "Outputs phone numbers from multiple diary entries (all unique)" do + diary = Diary.new + entry = DiaryEntry.new("Welcome", "Hello 01980683829 and a good 07000232141 to you too!") + entryTwo = DiaryEntry.new("Second Entry", "My phone number is 02011323232, and my best friend's number is 07232848949. Note these down! As I said: 02011323232 and 07232848949 - don't forget!") + diary.add(entry) + diary.add(entryTwo) + expect(diary.phone_numbers).to eq ["01980683829", "07000232141", "02011323232", "07232848949"] + end +end \ No newline at end of file diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 0000000..5ae5b69 --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,98 @@ +# This file was generated by the `rspec --init` command. Conventionally, all +# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. +# The generated `.rspec` file contains `--require spec_helper` which will cause +# this file to always be loaded, without a need to explicitly require it in any +# files. +# +# Given that it is always loaded, you are encouraged to keep this file as +# light-weight as possible. Requiring heavyweight dependencies from this file +# will add to the boot time of your test suite on EVERY test run, even for an +# individual file that may not need all of that loaded. Instead, consider making +# a separate helper file that requires the additional dependencies and performs +# the additional setup, and require it from the spec files that actually need +# it. +# +# See https://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration +RSpec.configure do |config| + # rspec-expectations config goes here. You can use an alternate + # assertion/expectation library such as wrong or the stdlib/minitest + # assertions if you prefer. + config.expect_with :rspec do |expectations| + # This option will default to `true` in RSpec 4. It makes the `description` + # and `failure_message` of custom matchers include text for helper methods + # defined using `chain`, e.g.: + # be_bigger_than(2).and_smaller_than(4).description + # # => "be bigger than 2 and smaller than 4" + # ...rather than: + # # => "be bigger than 2" + expectations.include_chain_clauses_in_custom_matcher_descriptions = true + end + + # rspec-mocks config goes here. You can use an alternate test double + # library (such as bogus or mocha) by changing the `mock_with` option here. + config.mock_with :rspec do |mocks| + # Prevents you from mocking or stubbing a method that does not exist on + # a real object. This is generally recommended, and will default to + # `true` in RSpec 4. + mocks.verify_partial_doubles = true + end + + # This option will default to `:apply_to_host_groups` in RSpec 4 (and will + # have no way to turn it off -- the option exists only for backwards + # compatibility in RSpec 3). It causes shared context metadata to be + # inherited by the metadata hash of host groups and examples, rather than + # triggering implicit auto-inclusion in groups with matching metadata. + config.shared_context_metadata_behavior = :apply_to_host_groups + +# The settings below are suggested to provide a good initial experience +# with RSpec, but feel free to customize to your heart's content. +=begin + # This allows you to limit a spec run to individual examples or groups + # you care about by tagging them with `:focus` metadata. When nothing + # is tagged with `:focus`, all examples get run. RSpec also provides + # aliases for `it`, `describe`, and `context` that include `:focus` + # metadata: `fit`, `fdescribe` and `fcontext`, respectively. + config.filter_run_when_matching :focus + + # Allows RSpec to persist some state between runs in order to support + # the `--only-failures` and `--next-failure` CLI options. We recommend + # you configure your source control system to ignore this file. + config.example_status_persistence_file_path = "spec/examples.txt" + + # Limits the available syntax to the non-monkey patched syntax that is + # recommended. For more details, see: + # https://relishapp.com/rspec/rspec-core/docs/configuration/zero-monkey-patching-mode + config.disable_monkey_patching! + + # This setting enables warnings. It's recommended, but in some cases may + # be too noisy due to issues in dependencies. + config.warnings = true + + # Many RSpec users commonly either run the entire suite or an individual + # file, and it's useful to allow more verbose output when running an + # individual spec file. + if config.files_to_run.one? + # Use the documentation formatter for detailed output, + # unless a formatter has already been configured + # (e.g. via a command-line flag). + config.default_formatter = "doc" + end + + # Print the 10 slowest examples and example groups at the + # end of the spec run, to help surface which specs are running + # particularly slow. + config.profile_examples = 10 + + # Run specs in random order to surface order dependencies. If you find an + # order dependency and want to debug it, you can fix the order by providing + # the seed, which is printed after each run. + # --seed 1234 + config.order = :random + + # Seed global randomization in this process using the `--seed` CLI option. + # Setting this allows you to use `--seed` to deterministically reproduce + # test failures related to randomization by passing the same `--seed` value + # as the one that triggered the failure. + Kernel.srand config.seed +=end +end diff --git a/spec/todo_spec.rb b/spec/todo_spec.rb new file mode 100644 index 0000000..cdd49f8 --- /dev/null +++ b/spec/todo_spec.rb @@ -0,0 +1,41 @@ +require 'todo' +require 'todo_list' + +RSpec.describe TodoList do + it "Outputs no completed items when none given" do + todolist = TodoList.new + expect(todolist.complete).to eq [] + end + + it "Outputs no incomplete items when none given" do + todolist = TodoList.new + expect(todolist.incomplete).to eq [] + end + + it "Marks nothing as complete if no tasks given" do + todolist = TodoList.new + expect{ todolist.give_up! }.to raise_error "No tasks available!" + end +end + +RSpec.describe Todo do + it "Raises error if no task is provided" do + expect{ Todo.new() }.to raise_error "No task provided!" + end + + it "Returns task details to user" do + todo = Todo.new("Run a marathon") + expect(todo.task).to eq "Run a marathon" + end + + it "Returns task status - complete" do + todo = Todo.new("Run a marathon") + todo.mark_done! + expect(todo.done?).to eq true + end + + it "Returns task status - incomplete" do + todo = Todo.new("Run a marathon") + expect(todo.done?).to eq false + end +end \ No newline at end of file