diff --git a/lib/account.rb b/lib/account.rb index e69de29b..191207fa 100644 --- a/lib/account.rb +++ b/lib/account.rb @@ -0,0 +1,47 @@ +require 'csv' +require 'time' + +module Bank + class Account + attr_reader :id, :balance, :date + def initialize(id, balance, date="nil") + @id = id + @balance = balance + @date = date + raise ArgumentError.new("balance must be >= 0") if balance < 0 + end + + def self.find(id1) + @accounts_array.each do |line| + return line if line.id == id1 + raise ArgumentError.new("no valid id") if line.id != id1 + end + end + + def self.all + @accounts_array = [] + #I had to use this whole branch because it was the only way it worked + #Wierd! + #A little out the line of good style. Sorry + CSV.open("/Users/laurams/ada/homework/BankAccounts/support/accounts.csv").each do |line| + @accounts_array << self.new(line[0].to_i, line[1].to_i, Time.parse(line[2])) + end + @accounts_array + end + + def withdraw(withdraw_amount) + raise ArgumentError.new("Unvalid amount!") if withdraw_amount < 0 + if (@balance - withdraw_amount) <0 + print "warning! Your balance is #{@balance}" + return @balance + end + + return @balance if (@balance -= withdraw_amount) >= 0 + end + + def deposit(amount) + raise ArgumentError.new("Can't deposit negative money") if amount < 0 + @balance += amount + end + end +end diff --git a/lib/checking_account.rb b/lib/checking_account.rb new file mode 100644 index 00000000..c1190b3c --- /dev/null +++ b/lib/checking_account.rb @@ -0,0 +1,38 @@ +require_relative 'account' + +module Bank + class CheckingAccount < Account + def initialize (id, balance) + super(id, balance) + @checks = 0 + end + + def withdraw(withdraw_amount) + fee = 1 + if @balance < withdraw_amount + puts "You dont have enough funds!" + return @balance + end + @balance -= (withdraw_amount + fee) + end + + def withdraw_using_check(amount) + raise ArgumentError.new("unvalid amount!") if amount < 0 + + if (@balance - amount) < -10 + print "warning! Your balance would go under -$10" + return @balance + end + raise ArgumentError.new("No enough funds") if (@balance - amount) < -10 + + @checks += 1 + fee = 2.0 + return @balance -= (amount + fee) if @checks > 3 + @balance -= amount + end + + def reset_checks + @checks = 0 + end + end +end diff --git a/lib/savings_account.rb b/lib/savings_account.rb new file mode 100644 index 00000000..6269607b --- /dev/null +++ b/lib/savings_account.rb @@ -0,0 +1,29 @@ +require_relative 'account' + +module Bank + class SavingsAccount < Account + def initialize(id, balance) + super(id, balance) + raise ArgumentError.new("balance must be >= 10") if balance < 10 + end + + def withdraw(withdraw_amount) + fee = 2 + raise ArgumentError.new("Unvalid amount!") if withdraw_amount < 0 + if (@balance - (withdraw_amount + fee)) < 10 + print "warning! Your balance is less than 10 after fee applied" + return @balance + end + + return @balance if (@balance -= (withdraw_amount + fee)) >= 10 + end + + def add_interest(rate) + raise ArgumentError.new("rate must be positive") if rate < 0 + + interest = @balance * rate + @balance += interest + end + + end +end diff --git a/specs/account_spec.rb b/specs/account_spec.rb index 6c399139..affccb99 100644 --- a/specs/account_spec.rb +++ b/specs/account_spec.rb @@ -2,6 +2,8 @@ require 'minitest/reporters' require 'minitest/skip_dsl' require_relative '../lib/account' +require 'csv' +require 'date' describe "Wave 1" do describe "Account#initialize" do @@ -18,10 +20,6 @@ end it "Raises an ArgumentError when created with a negative balance" do - # Note: we haven't talked about procs yet. You can think - # of them like blocks that sit by themselves. - # This code checks that, when the proc is executed, it - # raises an ArgumentError. proc { Bank::Account.new(1337, -100.0) }.must_raise ArgumentError @@ -61,13 +59,9 @@ withdrawal_amount = 200.0 account = Bank::Account.new(1337, start_balance) - # Another proc! This test expects something to be printed - # to the terminal, using 'must_output'. /.+/ is a regular - # expression matching one or more characters - as long as - # anything at all is printed out the test will pass. proc { account.withdraw(withdrawal_amount) - }.must_output /.+/ + }.must_output (/.+/) end it "Doesn't modify the balance if the account would go negative" do @@ -136,36 +130,51 @@ end end -# TODO: change 'xdescribe' to 'describe' to run these tests -xdescribe "Wave 2" do +describe "Wave 2" do describe "Account.all" do it "Returns an array of all accounts" do - # TODO: Your test code here! - # Useful checks might include: - # - Account.all returns an array - # - Everything in the array is an Account - # - The number of accounts is correct - # - The ID and balance of the first and last - # accounts match what's in the CSV file - # Feel free to split this into multiple tests if needed + Bank::Account.all.must_be_instance_of Array end + + it "Returns the right numbers of accounts" do + num = 0 + CSV.read("/Users/laurams/ada/homework/BankAccounts/support/accounts.csv").each do |line| + num +=1 + end + Bank::Account.all.length.must_equal num + end + + # TODO: Your test code here! + # Useful checks might include: + # - Account.all returns an array listo!!! + # - Everything in the array is an Account + # - The number of accounts is correct listo!!!! + # - The ID and balance of the first and last + # accounts match what's in the CSV file + # Feel free to split this into multiple tests if needed + end describe "Account.find" do - it "Returns an account that exists" do - # TODO: Your test code here! + #I am having trouble with this test sometimes. + #I think it's because the way I defined my @accounts_array. + #But the majority of times it passes. Wierd! + it "Returns an account that exits" do + Bank::Account.find(1212) end it "Can find the first account from the CSV" do - # TODO: Your test code here! + Bank::Account.all[0].id.must_equal 1212 end it "Can find the last account from the CSV" do - # TODO: Your test code here! + Bank::Account.all[-1].id.must_equal 15156 end it "Raises an error for an account that doesn't exist" do - # TODO: Your test code here! + proc { + Bank::Account.find(0) + }.must_raise ArgumentError end end end diff --git a/specs/checking_account_spec.rb b/specs/checking_account_spec.rb index 7f95339e..d2d57785 100644 --- a/specs/checking_account_spec.rb +++ b/specs/checking_account_spec.rb @@ -1,19 +1,10 @@ require 'minitest/autorun' require 'minitest/reporters' require 'minitest/skip_dsl' +require_relative '../lib/checking_account' -# TODO: uncomment the next line once you start wave 3 and add lib/checking_account.rb -# require_relative '../lib/checking_account' - -# Because a CheckingAccount is a kind -# of Account, and we've already tested a bunch of functionality -# on Account, we effectively get all that testing for free! -# Here we'll only test things that are different. - -# TODO: change 'xdescribe' to 'describe' to run these tests -xdescribe "CheckingAccount" do +describe "CheckingAccount" do describe "#initialize" do - # Check that a CheckingAccount is in fact a kind of account it "Is a kind of Account" do account = Bank::CheckingAccount.new(12345, 100.0) account.must_be_kind_of Bank::Account @@ -22,59 +13,113 @@ describe "#withdraw" do it "Applies a $1 fee each time" do - # TODO: Your test code here! + start_balance = 100.0 + withdrawal_amount = 25.0 + fee = 1.0 + account = Bank::CheckingAccount.new(1212, start_balance) + + account.withdraw(withdrawal_amount) + + expected_balance = start_balance - withdrawal_amount - fee + account.balance.must_equal expected_balance end it "Doesn't modify the balance if the fee would put it negative" do - # TODO: Your test code here! + start_balance = 100 + withdraw_amount = 101 + account = Bank::CheckingAccount.new(1212, start_balance) + x = account.withdraw(withdraw_amount) + + x.must_equal start_balance end end describe "#withdraw_using_check" do it "Reduces the balance" do - # TODO: Your test code here! + start_balance = 876 + amount = 76 + account = Bank::CheckingAccount.new(17682, start_balance) + balance1 = start_balance - amount + account.withdraw_using_check(amount).must_be_same_as balance1 end it "Returns the modified balance" do - # TODO: Your test code here! + start_balance = 100 + amount = 70 + account = Bank::CheckingAccount.new(17682, start_balance) + updated_balance = start_balance - amount + + updated_balance.must_equal account.withdraw_using_check(amount) end it "Allows the balance to go down to -$10" do - # TODO: Your test code here! + start_balance = 1000 + withdrawal_amount = 1010 + account = Bank::CheckingAccount.new(1879, start_balance) + account.withdraw_using_check(withdrawal_amount) end it "Outputs a warning if the account would go below -$10" do - # TODO: Your test code here! - end - - it "Doesn't modify the balance if the account would go below -$10" do - # TODO: Your test code here! + start_balance = 1000 + a = 2909 + proc { + Bank::CheckingAccount.new(1879, start_balance).withdraw_using_check(a) + }.must_output (/.+/) end it "Requires a positive withdrawal amount" do - # TODO: Your test code here! + start_balance = 1000 + a = -56 + proc { + Bank::CheckingAccount.new(1879, start_balance).withdraw_using_check(a) + }.must_raise ArgumentError end it "Allows 3 free uses" do - # TODO: Your test code here! + balance = 100 + amount = 10 + account = Bank::CheckingAccount.new(17682, balance) + 3.times {balance = balance - amount} + final_balance = 0 + 3.times {final_balance = account.withdraw_using_check(amount)} + + final_balance.must_be_same_as balance end it "Applies a $2 fee after the third use" do - # TODO: Your test code here! + balance = 100 + amount = 10 + fee = 2 + account = Bank::CheckingAccount.new(17682, balance) + + 4.times {balance = balance - amount} + balance -= fee + final_balance = nil + 4.times {final_balance = account.withdraw_using_check(amount)} + + final_balance.must_equal balance end end describe "#reset_checks" do it "Can be called without error" do - # TODO: Your test code here! + Bank::CheckingAccount.new(1819, 100).reset_checks end it "Makes the next three checks free if less than 3 checks had been used" do - # TODO: Your test code here! + account = Bank::CheckingAccount.new(8282, 100) + 2.times {account.withdraw_using_check(10)} + account.reset_checks + 3.times {account.withdraw_using_check(10)} + account.balance.must_equal 50 end it "Makes the next three checks free if more than 3 checks had been used" do - # TODO: Your test code here! + account = Bank::CheckingAccount.new(8282, 100) + 4.times {account.withdraw_using_check(10)} + account.reset_checks + 3.times {account.withdraw_using_check(10)} + account.balance.must_equal 28 end end end diff --git a/specs/savings_account_spec.rb b/specs/savings_account_spec.rb index 3f4d1e4a..171de00a 100644 --- a/specs/savings_account_spec.rb +++ b/specs/savings_account_spec.rb @@ -1,17 +1,9 @@ require 'minitest/autorun' require 'minitest/reporters' require 'minitest/skip_dsl' +require_relative '../lib/savings_account' -# TODO: uncomment the next line once you start wave 3 and add lib/savings_account.rb -# require_relative '../lib/savings_account' - -# Because a SavingsAccount is a kind -# of Account, and we've already tested a bunch of functionality -# on Account, we effectively get all that testing for free! -# Here we'll only test things that are different. - -# TODO: change 'xdescribe' to 'describe' to run these tests -xdescribe "SavingsAccount" do +describe "SavingsAccount" do describe "#initialize" do it "Is a kind of Account" do # Check that a SavingsAccount is in fact a kind of account @@ -20,39 +12,82 @@ end it "Requires an initial balance of at least $10" do - # TODO: Your test code here! + proc { + Bank::SavingsAccount.new(1337, 9) + }.must_raise ArgumentError end end describe "#withdraw" do it "Applies a $2 fee each time" do - # TODO: Your test code here! + start_balance = 100.0 + withdrawal_amount = 25.0 + fee = 2.0 + account = Bank::SavingsAccount.new(1212, start_balance) + + account.withdraw(withdrawal_amount) + + expected_balance = start_balance - withdrawal_amount - fee + account.balance.must_equal expected_balance end it "Outputs a warning if the balance would go below $10" do - # TODO: Your test code here! + start_balance = 100.0 + withdrawal_amount = 99.0 + account = Bank::SavingsAccount.new(1337, start_balance) + + proc { + account.withdraw(withdrawal_amount) + }.must_output (/.+/) end it "Doesn't modify the balance if it would go below $10" do - # TODO: Your test code here! + start_balance = 100.0 + withdrawal_amount = 92.0 + account = Bank::SavingsAccount.new(1920, start_balance) + + updated_balance = account.withdraw(withdrawal_amount) + + updated_balance.must_equal start_balance + # account.balance.must_equal start_balance end it "Doesn't modify the balance if the fee would put it below $10" do - # TODO: Your test code here! + start_balance = 100.0 + withdrawal_amount = 89.0 + account = Bank::SavingsAccount.new(1920, start_balance) + + updated_balance = account.withdraw(withdrawal_amount) + + updated_balance.must_equal start_balance end end describe "#add_interest" do it "Returns the interest calculated" do - # TODO: Your test code here! + start_balance = 983879.0 + rate = 0.025 + + account = Bank::SavingsAccount.new(1920, start_balance) + updated_balance = account.add_interest(rate) + + interest = updated_balance - start_balance + interest.must_be_within_epsilon (start_balance*rate) end it "Updates the balance with calculated interest" do - # TODO: Your test code here! + start_balance = 200 + rate = 0.011 + account = Bank::SavingsAccount.new(1676, start_balance) + + updated_balance = start_balance + (start_balance * rate) + account.add_interest(rate).must_equal updated_balance end it "Requires a positive rate" do - # TODO: Your test code here! + proc { + Bank::SavingsAccount.new(1878, 100).add_interest(-10) + }.must_raise ArgumentError end end end