money_tracking 0.99.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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