money_tracking 0.99.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +16 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +8 -0
  5. data/Gemfile +10 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +61 -0
  8. data/Rakefile +2 -0
  9. data/bin/money +6 -0
  10. data/lib/money_tracking.rb +6 -0
  11. data/lib/money_tracking/cli.rb +88 -0
  12. data/lib/money_tracking/cli/commands.rb +7 -0
  13. data/lib/money_tracking/cli/create_command.rb +21 -0
  14. data/lib/money_tracking/cli/delete_command.rb +15 -0
  15. data/lib/money_tracking/cli/list_command.rb +16 -0
  16. data/lib/money_tracking/cli/runner.rb +54 -0
  17. data/lib/money_tracking/cli/update_command.rb +33 -0
  18. data/lib/money_tracking/cli/views.rb +15 -0
  19. data/lib/money_tracking/cli/views/empty.rb +11 -0
  20. data/lib/money_tracking/cli/views/expense_created.rb +11 -0
  21. data/lib/money_tracking/cli/views/expense_deleted.rb +15 -0
  22. data/lib/money_tracking/cli/views/expense_item.rb +34 -0
  23. data/lib/money_tracking/cli/views/expense_list.rb +11 -0
  24. data/lib/money_tracking/cli/views/expense_not_found.rb +15 -0
  25. data/lib/money_tracking/cli/views/expense_not_updated.rb +19 -0
  26. data/lib/money_tracking/cli/views/expense_updated.rb +15 -0
  27. data/lib/money_tracking/data_store/file_store.rb +81 -0
  28. data/lib/money_tracking/data_store/protocol.rb +20 -0
  29. data/lib/money_tracking/domain.rb +12 -0
  30. data/lib/money_tracking/domain/expense.rb +92 -0
  31. data/lib/money_tracking/domain/expense_factory.rb +15 -0
  32. data/lib/money_tracking/domain/expense_finder.rb +13 -0
  33. data/lib/money_tracking/version.rb +3 -0
  34. data/money_tracking.gemspec +25 -0
  35. data/spec/aruba_helper.rb +31 -0
  36. data/spec/integration/cli_spec.rb +129 -0
  37. data/spec/money_tracking/cli/create_command_spec.rb +38 -0
  38. data/spec/money_tracking/cli/delete_command_spec.rb +44 -0
  39. data/spec/money_tracking/cli/list_command_spec.rb +34 -0
  40. data/spec/money_tracking/cli/update_command_spec.rb +92 -0
  41. data/spec/money_tracking/cli/views/expense_item_spec.rb +60 -0
  42. data/spec/money_tracking/cli/views/expense_list_spec.rb +40 -0
  43. data/spec/money_tracking/data_store/acts_as_a_data_store.rb +144 -0
  44. data/spec/money_tracking/data_store/file_store_spec.rb +16 -0
  45. data/spec/money_tracking/domain/expense_factory_spec.rb +58 -0
  46. data/spec/money_tracking/domain/expense_finder_spec.rb +59 -0
  47. data/spec/money_tracking/domain/expense_spec.rb +125 -0
  48. data/spec/spec_helper.rb +32 -0
  49. metadata +148 -0
@@ -0,0 +1,16 @@
1
+ require "money_tracking/data_store/file_store"
2
+ require_relative "acts_as_a_data_store"
3
+
4
+ module MoneyTracking
5
+ module DataStore
6
+ TEMP_FOLDER = "./tmp/expenses/"
7
+
8
+ RSpec.describe FileStore do
9
+ include_context "acts as a DataStore", store_reset: -> {
10
+ `[ -d #{TEMP_FOLDER} ] && rm -r #{TEMP_FOLDER}`
11
+ }
12
+
13
+ subject(:store) { FileStore.new(TEMP_FOLDER) }
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,58 @@
1
+ module MoneyTracking
2
+ module Domain
3
+ RSpec.describe ExpenseFactory do
4
+ subject(:factory) { described_class.new(store) }
5
+
6
+ let(:store) { instance_double(DataStore::Protocol, create: nil) }
7
+
8
+ let(:raw_expense) { {
9
+ amount: 44.99,
10
+ currency: "euro",
11
+ tags: ["food", "other"],
12
+ } }
13
+
14
+ let(:create_expense) { subject.create(raw_expense) }
15
+ let(:build_expense) { subject.build(raw_expense) }
16
+ let(:build_expense_with_id) { subject.build(raw_expense, id) }
17
+
18
+ let(:id) { "mg7ai6a4" }
19
+
20
+ describe "#create" do
21
+ it "creates an Expense" do
22
+ expect(create_expense).to be_a(Expense)
23
+ end
24
+
25
+ it "delegates persistence to store" do
26
+ expect(store)
27
+ .to receive(:create)
28
+ .with(raw_expense)
29
+ create_expense
30
+ end
31
+ end
32
+
33
+ describe "#build" do
34
+ it "builds and Expense" do
35
+ expect(build_expense).to be_a(Expense)
36
+ end
37
+
38
+ it "does not touch store" do
39
+ expect(store).not_to receive(:create)
40
+ build_expense
41
+ end
42
+
43
+ it "builds an ExpenseNotFound if raw_expense is nil" do
44
+ expect(subject.build(nil)).to be_a(ExpenseNotFound)
45
+ end
46
+
47
+ it "builds expense with id if id is provided" do
48
+ an_expense = instance_double(Expense)
49
+ expect(Expense)
50
+ .to receive(:new)
51
+ .with(store, raw_expense.merge(id: id))
52
+ .and_return(an_expense)
53
+ expect(build_expense_with_id).to be(an_expense)
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,59 @@
1
+ module MoneyTracking
2
+ module Domain
3
+ RSpec.describe ExpenseFinder do
4
+ subject(:finder) { described_class.new(store, expense_factory) }
5
+
6
+ let(:store) { instance_double(DataStore::Protocol) }
7
+ let(:expense_factory) { instance_double(ExpenseFactory) }
8
+
9
+ let(:raw_expenses) { [raw_a, raw_b, raw_c] }
10
+
11
+ let(:raw_a) { double("raw a") }
12
+ let(:raw_b) { double("raw b") }
13
+ let(:raw_c) { double("raw c") }
14
+
15
+ let(:expense_a) { double("expense a") }
16
+ let(:expense_b) { double("expense b") }
17
+ let(:expense_c) { double("expense c") }
18
+
19
+ before do
20
+ allow(expense_factory).to receive(:build).with(raw_a).and_return(expense_a)
21
+ allow(expense_factory).to receive(:build).with(raw_b).and_return(expense_b)
22
+ allow(expense_factory).to receive(:build).with(raw_c).and_return(expense_c)
23
+ end
24
+
25
+ describe "#list" do
26
+ context "when store returns empty list" do
27
+ before { allow(store).to receive(:list).and_return([]) }
28
+
29
+ it "returns empty list too" do
30
+ expect(finder.list).to be_empty
31
+ end
32
+ end
33
+
34
+ context "when store returns some raw expenses" do
35
+ before { allow(store).to receive(:list).and_return(raw_expenses) }
36
+
37
+ it "returns a list of corresponding domain objects" do
38
+ expect(finder.list).to eq([expense_a, expense_b, expense_c])
39
+ end
40
+ end
41
+ end
42
+
43
+ describe "#read" do
44
+ let(:id) { "yvrz7h2r" }
45
+ let(:raw_expense) { double("raw expense") }
46
+ let(:expense) { instance_double(Expense) }
47
+
48
+ before do
49
+ allow(store).to receive(:read).with(id).and_return(raw_expense)
50
+ allow(expense_factory).to receive(:build).with(raw_expense, id).and_return(expense)
51
+ end
52
+
53
+ it "delegates to store.read and builds expense from result" do
54
+ expect(subject.read(id)).to be(expense)
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,125 @@
1
+ module MoneyTracking
2
+ module Domain
3
+ RSpec.describe Expense do
4
+ subject(:expense) { described_class.new(store, fields) }
5
+
6
+ let(:view_factory) { double("ViewFactory") }
7
+ let(:view) { double("View") }
8
+ let(:store) { instance_double(DataStore::Protocol, create: "7dt0ibnv") }
9
+ let(:fields) { {
10
+ amount: 39.99,
11
+ currency: "dollar",
12
+ tags: ["food", "burgers"],
13
+ } }
14
+
15
+ let(:raw_expense) { fields.merge(id: "7dt0ibnv") }
16
+
17
+ let(:fixed_time) { Time.now }
18
+
19
+ describe "#create" do
20
+ it "delegates to store with :created_at field = Time.now" do
21
+ Timecop.freeze(fixed_time) do
22
+ expect(store)
23
+ .to receive(:create)
24
+ .with(fields.merge(created_at: fixed_time))
25
+ expense.create
26
+ end
27
+ end
28
+
29
+ it "returns itself" do
30
+ expect(expense.create).to be(expense)
31
+ end
32
+ end
33
+
34
+ describe "#update" do
35
+ let(:fields) { super().merge(id: "qp5g0x0h") }
36
+ let(:new_fields) { {
37
+ id: "qp5g0x0h",
38
+ amount: 49.99,
39
+ currency: "euro",
40
+ tags: ["food", "dinner", "pricey"]
41
+ } }
42
+ let(:update_fields) { {
43
+ amount: 49.99,
44
+ currency: "euro",
45
+ add_tags: ["dinner", "pricey"],
46
+ rm_tags: ["burgers"],
47
+ } }
48
+
49
+ it "adjusts its fields and sends them to store" do
50
+ expect(store)
51
+ .to receive(:update)
52
+ .with("qp5g0x0h", new_fields)
53
+ expect(expense.update(update_fields)).to be(expense)
54
+ end
55
+ end
56
+
57
+ describe "#delete" do
58
+ let(:fields) { super().merge(id: "qp5g0x0h") }
59
+
60
+ it "asks store to delete the record" do
61
+ expect(store)
62
+ .to receive(:delete)
63
+ .with("qp5g0x0h")
64
+ expect(expense.delete).to be(expense)
65
+ end
66
+ end
67
+
68
+ describe "#build_view" do
69
+ context "when it is a new record" do
70
+ before do
71
+ allow(view_factory)
72
+ .to receive(:new)
73
+ .with(fields)
74
+ .and_return(view)
75
+ end
76
+
77
+ it "gives relevant data to a view factory" do
78
+ expect(view_factory)
79
+ .to receive(:new)
80
+ .with(fields)
81
+ expense.build_view(view_factory)
82
+ end
83
+
84
+ it "returns created view" do
85
+ expect(expense.build_view(view_factory)).to be(view)
86
+ end
87
+ end
88
+
89
+ context "when it is already saved record" do
90
+ before do
91
+ expense.create
92
+
93
+ allow(view_factory)
94
+ .to receive(:new)
95
+ .with(raw_expense)
96
+ .and_return(view)
97
+ end
98
+
99
+ it "gives relevant data with id to a view factory" do
100
+ expect(view_factory)
101
+ .to receive(:new)
102
+ .with(raw_expense)
103
+ expense.build_view(view_factory)
104
+ end
105
+
106
+ it "returns created view" do
107
+ expect(expense.build_view(view_factory)).to be(view)
108
+ end
109
+ end
110
+ end
111
+ end
112
+
113
+ RSpec.describe ExpenseNotFound do
114
+ describe "#build_view" do
115
+ let(:view_factory) { double("View factory", not_found: not_found_factory) }
116
+ let(:not_found_factory) { double("Not found factory", new: not_found_view) }
117
+ let(:not_found_view) { double("Not found view") }
118
+
119
+ it "builds not found view analogue" do
120
+ expect(subject.build_view(view_factory)).to be(not_found_view)
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,32 @@
1
+ require "timecop"
2
+ Timecop.safe_mode = true
3
+
4
+ require "money_tracking"
5
+ require "money_tracking/cli"
6
+
7
+ RSpec.configure do |config|
8
+ config.expect_with :rspec do |expectations|
9
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
10
+ end
11
+
12
+ config.mock_with :rspec do |mocks|
13
+ mocks.verify_partial_doubles = true
14
+ end
15
+
16
+ config.filter_run :focus
17
+ config.run_all_when_everything_filtered = true
18
+
19
+ config.disable_monkey_patching!
20
+
21
+ config.warnings = false
22
+
23
+ if config.files_to_run.one?
24
+ config.default_formatter = 'doc'
25
+ end
26
+
27
+ config.profile_examples = 10
28
+
29
+ config.order = :random
30
+
31
+ Kernel.srand config.seed
32
+ end
metadata ADDED
@@ -0,0 +1,148 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: money_tracking
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.99.0
5
+ platform: ruby
6
+ authors:
7
+ - Oleksii Fedorov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-04-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: thor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.7'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.7'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ description: CLI tool for tracking your expenses.
56
+ email:
57
+ - waterlink000@gmail.com
58
+ executables:
59
+ - money
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - ".gitignore"
64
+ - ".rspec"
65
+ - ".travis.yml"
66
+ - Gemfile
67
+ - LICENSE.txt
68
+ - README.md
69
+ - Rakefile
70
+ - bin/money
71
+ - lib/money_tracking.rb
72
+ - lib/money_tracking/cli.rb
73
+ - lib/money_tracking/cli/commands.rb
74
+ - lib/money_tracking/cli/create_command.rb
75
+ - lib/money_tracking/cli/delete_command.rb
76
+ - lib/money_tracking/cli/list_command.rb
77
+ - lib/money_tracking/cli/runner.rb
78
+ - lib/money_tracking/cli/update_command.rb
79
+ - lib/money_tracking/cli/views.rb
80
+ - lib/money_tracking/cli/views/empty.rb
81
+ - lib/money_tracking/cli/views/expense_created.rb
82
+ - lib/money_tracking/cli/views/expense_deleted.rb
83
+ - lib/money_tracking/cli/views/expense_item.rb
84
+ - lib/money_tracking/cli/views/expense_list.rb
85
+ - lib/money_tracking/cli/views/expense_not_found.rb
86
+ - lib/money_tracking/cli/views/expense_not_updated.rb
87
+ - lib/money_tracking/cli/views/expense_updated.rb
88
+ - lib/money_tracking/data_store/file_store.rb
89
+ - lib/money_tracking/data_store/protocol.rb
90
+ - lib/money_tracking/domain.rb
91
+ - lib/money_tracking/domain/expense.rb
92
+ - lib/money_tracking/domain/expense_factory.rb
93
+ - lib/money_tracking/domain/expense_finder.rb
94
+ - lib/money_tracking/version.rb
95
+ - money_tracking.gemspec
96
+ - spec/aruba_helper.rb
97
+ - spec/integration/cli_spec.rb
98
+ - spec/money_tracking/cli/create_command_spec.rb
99
+ - spec/money_tracking/cli/delete_command_spec.rb
100
+ - spec/money_tracking/cli/list_command_spec.rb
101
+ - spec/money_tracking/cli/update_command_spec.rb
102
+ - spec/money_tracking/cli/views/expense_item_spec.rb
103
+ - spec/money_tracking/cli/views/expense_list_spec.rb
104
+ - spec/money_tracking/data_store/acts_as_a_data_store.rb
105
+ - spec/money_tracking/data_store/file_store_spec.rb
106
+ - spec/money_tracking/domain/expense_factory_spec.rb
107
+ - spec/money_tracking/domain/expense_finder_spec.rb
108
+ - spec/money_tracking/domain/expense_spec.rb
109
+ - spec/spec_helper.rb
110
+ homepage: https://github.com/waterlink/money_tracking
111
+ licenses:
112
+ - MIT
113
+ metadata: {}
114
+ post_install_message:
115
+ rdoc_options: []
116
+ require_paths:
117
+ - lib
118
+ required_ruby_version: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ required_rubygems_version: !ruby/object:Gem::Requirement
124
+ requirements:
125
+ - - ">="
126
+ - !ruby/object:Gem::Version
127
+ version: '0'
128
+ requirements: []
129
+ rubyforge_project:
130
+ rubygems_version: 2.2.2
131
+ signing_key:
132
+ specification_version: 4
133
+ summary: CLI tool for tracking your expenses.
134
+ test_files:
135
+ - spec/aruba_helper.rb
136
+ - spec/integration/cli_spec.rb
137
+ - spec/money_tracking/cli/create_command_spec.rb
138
+ - spec/money_tracking/cli/delete_command_spec.rb
139
+ - spec/money_tracking/cli/list_command_spec.rb
140
+ - spec/money_tracking/cli/update_command_spec.rb
141
+ - spec/money_tracking/cli/views/expense_item_spec.rb
142
+ - spec/money_tracking/cli/views/expense_list_spec.rb
143
+ - spec/money_tracking/data_store/acts_as_a_data_store.rb
144
+ - spec/money_tracking/data_store/file_store_spec.rb
145
+ - spec/money_tracking/domain/expense_factory_spec.rb
146
+ - spec/money_tracking/domain/expense_finder_spec.rb
147
+ - spec/money_tracking/domain/expense_spec.rb
148
+ - spec/spec_helper.rb