uchi 0.1.0 → 0.1.2

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 (93) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +17 -0
  3. data/.github/workflows/build.yml +23 -0
  4. data/.github/workflows/lint.yml +30 -0
  5. data/package.json +31 -0
  6. data/test/components/uchi/field/belongs_to_test.rb +134 -0
  7. data/test/components/uchi/field/blank_test.rb +119 -0
  8. data/test/components/uchi/field/boolean_test.rb +163 -0
  9. data/test/components/uchi/field/date_test.rb +163 -0
  10. data/test/components/uchi/field/date_time_test.rb +152 -0
  11. data/test/components/uchi/field/has_many_test.rb +138 -0
  12. data/test/components/uchi/field/id_test.rb +113 -0
  13. data/test/components/uchi/field/number_test.rb +163 -0
  14. data/test/components/uchi/field/string_test.rb +159 -0
  15. data/test/controllers/uchi/authors_controller_test.rb +119 -0
  16. data/test/controllers/uchi/repository_controller_test.rb +93 -0
  17. data/test/controllers/uchi/scoped_repository_controller_test.rb +73 -0
  18. data/test/dummy/Rakefile +6 -0
  19. data/test/dummy/app/assets/images/.keep +0 -0
  20. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  21. data/test/dummy/app/controllers/application_controller.rb +4 -0
  22. data/test/dummy/app/controllers/concerns/.keep +0 -0
  23. data/test/dummy/app/controllers/uchi/authors_controller.rb +7 -0
  24. data/test/dummy/app/controllers/uchi/books_controller.rb +7 -0
  25. data/test/dummy/app/controllers/uchi/titles_controller.rb +7 -0
  26. data/test/dummy/app/helpers/application_helper.rb +2 -0
  27. data/test/dummy/app/jobs/application_job.rb +7 -0
  28. data/test/dummy/app/mailers/application_mailer.rb +4 -0
  29. data/test/dummy/app/models/application_record.rb +3 -0
  30. data/test/dummy/app/models/author.rb +3 -0
  31. data/test/dummy/app/models/book.rb +3 -0
  32. data/test/dummy/app/models/concerns/.keep +0 -0
  33. data/test/dummy/app/models/title.rb +3 -0
  34. data/test/dummy/app/uchi/repositories/author.rb +20 -0
  35. data/test/dummy/app/uchi/repositories/book.rb +16 -0
  36. data/test/dummy/app/uchi/repositories/title.rb +17 -0
  37. data/test/dummy/app/views/layouts/application.html.erb +27 -0
  38. data/test/dummy/app/views/layouts/mailer.html.erb +13 -0
  39. data/test/dummy/app/views/layouts/mailer.text.erb +1 -0
  40. data/test/dummy/app/views/pwa/manifest.json.erb +22 -0
  41. data/test/dummy/app/views/pwa/service-worker.js +26 -0
  42. data/test/dummy/bin/dev +2 -0
  43. data/test/dummy/bin/rails +4 -0
  44. data/test/dummy/bin/rake +4 -0
  45. data/test/dummy/bin/setup +34 -0
  46. data/test/dummy/config/application.rb +29 -0
  47. data/test/dummy/config/boot.rb +5 -0
  48. data/test/dummy/config/cable.yml +10 -0
  49. data/test/dummy/config/database.yml +32 -0
  50. data/test/dummy/config/environment.rb +5 -0
  51. data/test/dummy/config/environments/development.rb +69 -0
  52. data/test/dummy/config/environments/production.rb +89 -0
  53. data/test/dummy/config/environments/test.rb +53 -0
  54. data/test/dummy/config/initializers/content_security_policy.rb +25 -0
  55. data/test/dummy/config/initializers/filter_parameter_logging.rb +8 -0
  56. data/test/dummy/config/initializers/inflections.rb +16 -0
  57. data/test/dummy/config/locales/da.yml +51 -0
  58. data/test/dummy/config/locales/en.yml +31 -0
  59. data/test/dummy/config/puma.rb +38 -0
  60. data/test/dummy/config/routes.rb +9 -0
  61. data/test/dummy/config/storage.yml +34 -0
  62. data/test/dummy/config.ru +6 -0
  63. data/test/dummy/db/migrate/20251002183635_create_authors.rb +11 -0
  64. data/test/dummy/db/migrate/20251005131726_create_books.rb +9 -0
  65. data/test/dummy/db/migrate/20251005131811_create_titles.rb +11 -0
  66. data/test/dummy/db/schema.rb +38 -0
  67. data/test/dummy/log/.keep +0 -0
  68. data/test/dummy/public/400.html +114 -0
  69. data/test/dummy/public/404.html +114 -0
  70. data/test/dummy/public/406-unsupported-browser.html +114 -0
  71. data/test/dummy/public/422.html +114 -0
  72. data/test/dummy/public/500.html +114 -0
  73. data/test/dummy/public/icon.png +0 -0
  74. data/test/dummy/public/icon.svg +3 -0
  75. data/test/dummy/storage/.keep +0 -0
  76. data/test/dummy/test/fixtures/authors.yml +11 -0
  77. data/test/dummy/test/models/author_test.rb +7 -0
  78. data/test/dummy/tmp/.keep +0 -0
  79. data/test/dummy/tmp/pids/.keep +0 -0
  80. data/test/dummy/tmp/storage/.keep +0 -0
  81. data/test/test_helper.rb +15 -0
  82. data/test/uchi/field_test.rb +63 -0
  83. data/test/uchi/i18n_test.rb +18 -0
  84. data/test/uchi/repository/routes_test.rb +49 -0
  85. data/test/uchi/repository/translate_test.rb +263 -0
  86. data/test/uchi/repository_test.rb +137 -0
  87. data/test/uchi/sort_order_test.rb +47 -0
  88. data/test/uchi_test.rb +7 -0
  89. metadata +146 -7
  90. data/README.md +0 -35
  91. data/Rakefile +0 -6
  92. data/lib/uchi/version.rb +0 -5
  93. data/lib/uchi.rb +0 -8
@@ -0,0 +1,15 @@
1
+ # Configure Rails Environment
2
+ ENV["RAILS_ENV"] = "test"
3
+
4
+ require_relative "../test/dummy/config/environment"
5
+ ActiveRecord::Migrator.migrations_paths = [File.expand_path("../test/dummy/db/migrate", __dir__)]
6
+ ActiveRecord::Migrator.migrations_paths << File.expand_path("../db/migrate", __dir__)
7
+ require "rails/test_help"
8
+
9
+ # Load fixtures from the engine
10
+ if ActiveSupport::TestCase.respond_to?(:fixture_paths=)
11
+ ActiveSupport::TestCase.fixture_paths = [File.expand_path("fixtures", __dir__)]
12
+ ActionDispatch::IntegrationTest.fixture_paths = ActiveSupport::TestCase.fixture_paths
13
+ ActiveSupport::TestCase.file_fixture_path = File.expand_path("fixtures", __dir__) + "/files"
14
+ ActiveSupport::TestCase.fixtures :all
15
+ end
@@ -0,0 +1,63 @@
1
+ require "test_helper"
2
+ require "ostruct"
3
+
4
+ class UchiFieldTest < ActiveSupport::TestCase
5
+ def setup
6
+ @field = Uchi::Field.new(:name)
7
+ end
8
+
9
+ test "initializes with name" do
10
+ field = Uchi::Field.new(:title)
11
+ assert_equal :title, field.name
12
+ end
13
+
14
+ test "converts string name to symbol" do
15
+ field = Uchi::Field.new("title")
16
+ assert_equal :title, field.name
17
+ end
18
+
19
+ test "has default options" do
20
+ assert_equal [:edit, :index, :show], @field.on
21
+ assert_equal true, @field.sortable
22
+ end
23
+
24
+ test "#column_name returns humanized name" do
25
+ field = Uchi::Field.new(:first_name)
26
+ assert_equal "First name", field.column_name
27
+ end
28
+
29
+ test "#param_key returns name as symbol" do
30
+ assert_equal :name, @field.param_key
31
+ end
32
+
33
+ test "#searchable? returns false by default" do
34
+ assert_not @field.searchable?
35
+ end
36
+
37
+ test "#searchable? returns true when explicitly set" do
38
+ field = Uchi::Field.new(:name, searchable: true)
39
+ assert field.searchable?
40
+ end
41
+
42
+ test "#sortable? returns true by default" do
43
+ assert @field.sortable?
44
+ end
45
+
46
+ test "#sortable? returns false when explicitly set" do
47
+ field = Uchi::Field.new(:name, sortable: false)
48
+ assert_not field.sortable?
49
+ end
50
+
51
+ test "#value uses reader to get value from record" do
52
+ record = OpenStruct.new(name: "Test Name")
53
+ assert_equal "Test Name", @field.value(record)
54
+ end
55
+
56
+ test "#value uses custom reader when provided" do
57
+ custom_reader = ->(record, field_name) { "Custom: #{record.public_send(field_name)}" }
58
+ field = Uchi::Field.new(:name, reader: custom_reader)
59
+ record = OpenStruct.new(name: "Test")
60
+
61
+ assert_equal "Custom: Test", field.value(record)
62
+ end
63
+ end
@@ -0,0 +1,18 @@
1
+ require "test_helper"
2
+
3
+ class UchiI18nTest < ActiveSupport::TestCase
4
+ test "translate method delegates to I18n with uchi scope" do
5
+ # This should not raise an error
6
+ result = Uchi::I18n.translate("test_key", default: "fallback")
7
+ assert_equal "fallback", result
8
+ end
9
+
10
+ test "translate method accepts custom scope" do
11
+ result = Uchi::I18n.translate("test_key", scope: "custom", default: "fallback")
12
+ assert_equal "fallback", result
13
+ end
14
+
15
+ test "module responds to translate" do
16
+ assert Uchi::I18n.respond_to?(:translate)
17
+ end
18
+ end
@@ -0,0 +1,49 @@
1
+ require "test_helper"
2
+ require_relative "../../dummy/app/uchi/repositories/author"
3
+
4
+ class UchiRepositoryRoutesTest < ActiveSupport::TestCase
5
+ def setup
6
+ @repository = Uchi::Repositories::Author.new
7
+ @routes = @repository.routes
8
+ end
9
+
10
+ test "initializes with repository" do
11
+ assert_equal @repository, @routes.repository
12
+ end
13
+
14
+ test "#singular returns the singular route name" do
15
+ assert_equal "author", @routes.singular
16
+ end
17
+
18
+ test "#plural returns the plural route name" do
19
+ assert_equal "authors", @routes.plural
20
+ end
21
+
22
+ test "#path_for returns path to create action" do
23
+ assert_equal "/uchi/authors", @routes.path_for(:create)
24
+ end
25
+
26
+ test "#path_for returns path to destroy action" do
27
+ assert_equal "/uchi/authors/1", @routes.path_for(:destroy, id: 1)
28
+ end
29
+
30
+ test "#path_for returns path to edit action" do
31
+ assert_equal "/uchi/authors/1/edit", @routes.path_for(:edit, id: 1)
32
+ end
33
+
34
+ test "#path_for returns path to index action" do
35
+ assert_equal "/uchi/authors", @routes.path_for(:index)
36
+ end
37
+
38
+ test "#path_for returns path to new action" do
39
+ assert_equal "/uchi/authors/new", @routes.path_for(:new)
40
+ end
41
+
42
+ test "#path_for returns path to show action" do
43
+ assert_equal "/uchi/authors/1", @routes.path_for(:show, id: 1)
44
+ end
45
+
46
+ test "#path_for returns path to update action" do
47
+ assert_equal "/uchi/authors/1", @routes.path_for(:update, id: 1)
48
+ end
49
+ end
@@ -0,0 +1,263 @@
1
+ require "test_helper"
2
+ require_relative "../../dummy/app/uchi/repositories/author"
3
+
4
+ class UchiRepositoryTranslateTest < ActiveSupport::TestCase
5
+ def setup
6
+ @repository = Uchi::Repositories::Author.new
7
+ @translate = @repository.translate
8
+ @field = Uchi::Field.new(:name)
9
+ end
10
+
11
+ test "initializes with repository" do
12
+ assert_equal @repository, @translate.repository
13
+ end
14
+
15
+ test "#breadcrumb_label returns translation from uchi.repository.author.breadcrumb.index.label" do
16
+ I18n.with_locale(:da) do
17
+ result = @translate.breadcrumb_label(:index)
18
+ assert_equal "Forfattere", result
19
+ end
20
+ end
21
+
22
+ test "#breadcrumb_label for index page defaults to plural name" do
23
+ result = @translate.breadcrumb_label(:index)
24
+ assert_equal "Authors", result
25
+ end
26
+
27
+ test "#breadcrumb_label for show page returns translation from uchi.repository.author.breadcrumb.show.label" do
28
+ I18n.with_locale(:da) do
29
+ result = @translate.breadcrumb_label(:show, record: Author.new(name: "Test Author"))
30
+ assert_equal "Vis Test Author", result
31
+ end
32
+ end
33
+
34
+ test "#breadcrumb_label for show page defaults to record title" do
35
+ result = @translate.breadcrumb_label(:show, record: Author.new(name: "Test Author"))
36
+ assert_equal "Test Author", result
37
+ end
38
+
39
+ test "#breadcrumb_label for edit page returns translation from uchi.repository.author.breadcrumb.edit.label" do
40
+ I18n.with_locale(:da) do
41
+ result = @translate.breadcrumb_label(:edit, record: Author.new(name: "Test Author"))
42
+ assert_equal "Rediger Test Author", result
43
+ end
44
+ end
45
+
46
+ test "#breadcrumb_label for edit page defaults to page name" do
47
+ result = @translate.breadcrumb_label(:edit, record: Author.new(name: "Test Author"))
48
+ assert_equal "Edit", result
49
+ end
50
+
51
+ test "#destroy_dialog_title returns translation from uchi.repository.author.dialog.destroy.title" do
52
+ record = Author.new(name: "J. K. Rowling")
53
+ result = @translate.destroy_dialog_title(record)
54
+ assert_equal "Er du sikker på, at du vil slette J. K. Rowling?", result
55
+ end
56
+
57
+ test "#destroy_dialog_title falls back to default translation" do
58
+ result = @translate.destroy_dialog_title(:destroy)
59
+ assert_equal "Are you sure?", result
60
+ end
61
+
62
+ test "#description returns translation from uchi.repository.author.description.index" do
63
+ result = @translate.description(:index)
64
+ assert_nil result
65
+ end
66
+
67
+ test "#description falls back to nil" do
68
+ result = @translate.description(:index)
69
+ assert_nil result
70
+ end
71
+
72
+ test "failed_destroy returns translation from uchi.repository.author.destroy.failure" do
73
+ I18n.with_locale(:da) do
74
+ result = @translate.failed_destroy
75
+ assert_equal "Forfatteren kunne ikke slettes", result
76
+ end
77
+ end
78
+
79
+ test "failed_destroy falls back to default translation" do
80
+ result = @translate.failed_destroy
81
+ assert_equal "The record could not be deleted", result
82
+ end
83
+
84
+ test "#field_label returns translation from uchi.repository.author.field.name.label" do
85
+ I18n.with_locale(:da) do
86
+ result = @translate.field_label(@field)
87
+ assert_equal "Navn", result
88
+ end
89
+ end
90
+
91
+ test "#field_label falls back to human_attribute_name" do
92
+ result = @translate.field_label(@field)
93
+ assert_equal "Name", result
94
+ end
95
+
96
+ test "#field_hint returns translation from uchi.repository.author.field.name.hint" do
97
+ I18n.with_locale(:da) do
98
+ result = @translate.field_hint(@field)
99
+ assert_equal "Indtast forfatterens navn", result
100
+ end
101
+ end
102
+
103
+ test "#field_hint falls back to nil" do
104
+ result = @translate.field_hint(@field)
105
+ assert_nil result
106
+ end
107
+
108
+ test "#link_to_cancel returns cancel text" do
109
+ I18n.with_locale(:da) do
110
+ result = @translate.link_to_cancel
111
+ assert_equal "Annuller", result
112
+ end
113
+ end
114
+
115
+ test "#link_to_cancel falls back to Cancel" do
116
+ result = @translate.link_to_cancel
117
+ assert_equal "Cancel", result
118
+ end
119
+
120
+ test "#link_to_destroy returns destroy text" do
121
+ author = Author.new(name: "Brandon Sanderson")
122
+ I18n.with_locale(:da) do
123
+ result = @translate.link_to_destroy(author)
124
+ assert_equal "Slet Brandon Sanderson", result
125
+ end
126
+ end
127
+
128
+ test "#link_to_destroy falls back to delete" do
129
+ author = Author.new(name: "Brandon Sanderson")
130
+ result = @translate.link_to_destroy(author)
131
+ assert_equal "Delete", result
132
+ end
133
+
134
+ test "#link_to_edit returns translation from uchi.repository.author.button.link_to_edit" do
135
+ author = Author.new(name: "Test Author")
136
+ I18n.with_locale(:da) do
137
+ result = @translate.link_to_edit(author)
138
+ assert_equal "Rediger", result
139
+ end
140
+ end
141
+
142
+ test "#link_to_edit falls back to Edit" do
143
+ author = Author.new(name: "Test Author")
144
+ result = @translate.link_to_edit(author)
145
+ assert_equal "Edit", result
146
+ end
147
+
148
+ test "#link_to_new returns translation from uchi.repository.author.button.link_to_new" do
149
+ I18n.with_locale(:da) do
150
+ result = @translate.link_to_new
151
+ assert_equal "Ny forfatter", result
152
+ end
153
+ end
154
+
155
+ test "#link_to_new falls back to New %{model}" do
156
+ result = @translate.link_to_new
157
+ assert_equal "New Author", result
158
+ end
159
+
160
+ test "#loading_message returns translation from uchi.repository.common.loading" do
161
+ I18n.with_locale(:da) do
162
+ result = @translate.loading_message
163
+ assert_equal "Indlæser...", result
164
+ end
165
+ end
166
+
167
+ test "#loading_message falls back to Loading..." do
168
+ result = @translate.loading_message
169
+ assert_equal "Loading...", result
170
+ end
171
+
172
+ test "#plural_name returns translation from uchi.repository.author.model with count 2" do
173
+ I18n.with_locale(:da) do
174
+ result = @translate.plural_name
175
+ assert_equal "Forfattere", result
176
+ end
177
+ end
178
+
179
+ test "#plural_name falls back to humanized plural model name" do
180
+ result = @translate.plural_name
181
+ assert_equal "Authors", result
182
+ end
183
+
184
+ test "#submit_button returns translation from uchi.common.save" do
185
+ I18n.with_locale(:da) do
186
+ result = @translate.submit_button
187
+ assert_equal "Gem", result
188
+ end
189
+ end
190
+
191
+ test "#submit_button falls back to Save" do
192
+ result = @translate.submit_button
193
+ assert_equal "Save", result
194
+ end
195
+
196
+ test "successful_create returns translation from uchi.repository.author.create.success" do
197
+ I18n.with_locale(:da) do
198
+ result = @translate.successful_create
199
+ assert_equal "Forfatteren er blevet tilføjet", result
200
+ end
201
+ end
202
+
203
+ test "successful_create falls back to default translation" do
204
+ result = @translate.successful_create
205
+ assert_equal "Your changes have been saved", result
206
+ end
207
+
208
+ test "successful_destroy returns translation from uchi.repository.author.destroy.success" do
209
+ I18n.with_locale(:da) do
210
+ result = @translate.successful_destroy
211
+ assert_equal "Forfatteren er blevet slettet", result
212
+ end
213
+ end
214
+
215
+ test "successful_destroy falls back to default translation" do
216
+ result = @translate.successful_destroy
217
+ assert_equal "The record has been deleted", result
218
+ end
219
+
220
+ test "successful_update returns translation from uchi.repository.author.update.success" do
221
+ I18n.with_locale(:da) do
222
+ result = @translate.successful_update
223
+ assert_equal "Dine ændringer til forfatteren blev gemt", result
224
+ end
225
+ end
226
+
227
+ test "successful_update falls back to default translation" do
228
+ result = @translate.successful_update
229
+ assert_equal "Your changes have been saved", result
230
+ end
231
+
232
+ test "#title returns repository title for show page with record" do
233
+ author = Author.new(name: "Test Author")
234
+ result = @translate.title(:show, record: author)
235
+ assert_equal "Test Author", result
236
+ end
237
+
238
+ test "#title returns translation from uchi.repository.author.index.title for index page" do
239
+ I18n.with_locale(:da) do
240
+ result = @translate.title(:index)
241
+ assert_equal "Forfattere", result
242
+ end
243
+ end
244
+
245
+ test "#title returns translation from uchi.repository.author.edit.title for edit page" do
246
+ I18n.with_locale(:da) do
247
+ result = @translate.title(:edit)
248
+ assert_equal "Rediger forfatter", result
249
+ end
250
+ end
251
+
252
+ test "#title returns translation from uchi.repository.author.new.title for new page" do
253
+ I18n.with_locale(:da) do
254
+ result = @translate.title(:new)
255
+ assert_equal "Ny forfatter", result
256
+ end
257
+ end
258
+
259
+ test "#title falls back to plural_name" do
260
+ result = @translate.title(:index)
261
+ assert_equal "Authors", result
262
+ end
263
+ end
@@ -0,0 +1,137 @@
1
+ require "test_helper"
2
+
3
+ require_relative "../dummy/app/uchi/repositories/author"
4
+
5
+ class UchiRepositoryTest < ActiveSupport::TestCase
6
+ test ".all returns all Uchi::Repository's" do
7
+ repositories = Uchi::Repository.all
8
+
9
+ assert_equal \
10
+ repositories.sort_by(&:name),
11
+ [Uchi::Repositories::Author, Uchi::Repositories::Book, Uchi::Repositories::Title]
12
+ end
13
+
14
+ test ".for_model returns the repository for the given model" do
15
+ assert_equal Uchi::Repositories::Author, Uchi::Repository.for_model(Author)
16
+ assert_equal Uchi::Repositories::Author, Uchi::Repository.for_model("Author")
17
+ assert_equal Uchi::Repositories::Author, Uchi::Repository.for_model(:Author)
18
+ end
19
+
20
+ test ".model returns the model class the repository manages" do
21
+ assert_equal Author, Uchi::Repositories::Author.model
22
+ end
23
+
24
+ test "#build returns a new, unsaved instance of the model the repository manages" do
25
+ author = author_repository.build(name: "Alice")
26
+
27
+ assert author.is_a?(Author)
28
+ assert_equal "Alice", author.name
29
+ assert author.new_record?
30
+ end
31
+
32
+ test "#controller_name returns a URL slug for the controller" do
33
+ assert_equal "authors", author_repository.controller_name
34
+ end
35
+
36
+ test "#default_sort_order returns a sort by id ascending" do
37
+ sort_order = author_repository.default_sort_order
38
+
39
+ assert sort_order.is_a?(Uchi::SortOrder)
40
+ assert_equal :id, sort_order.name
41
+ assert_equal :asc, sort_order.direction
42
+ end
43
+
44
+ test "#fields_for_edit returns fields to include on the edit page" do
45
+ fields = author_repository.fields_for_edit
46
+
47
+ assert_equal [:name, :born_on, :biography], fields.map(&:name)
48
+ end
49
+
50
+ test "#fields_for_index returns fields to include on the index page" do
51
+ fields = author_repository.fields_for_index
52
+
53
+ assert_equal [:id, :name, :born_on], fields.map(&:name)
54
+ end
55
+
56
+ test "#fields_for_show returns fields to include on the show page" do
57
+ fields = author_repository.fields_for_show
58
+
59
+ assert_equal [:id, :name, :born_on, :biography], fields.map(&:name)
60
+ end
61
+
62
+ test "#find_all returns all records of the model the repository manages" do
63
+ alice = Author.create!(name: "Alice")
64
+ bob = Author.create!(name: "Bob")
65
+
66
+ authors = author_repository.find_all
67
+
68
+ assert_equal [alice, bob], authors
69
+ end
70
+
71
+ # TODO: How to test this?
72
+ # test "#find_all applies includes if given"
73
+
74
+ test "#find_all applies a search query if given" do
75
+ alice = Author.create!(name: "Alice")
76
+ _bob = Author.create!(name: "Bob")
77
+
78
+ authors = author_repository.find_all(search: "IC")
79
+
80
+ assert_equal [alice], authors
81
+ end
82
+
83
+ test "#find_all applies a sort order if given" do
84
+ alice = Author.create!(name: "Alice")
85
+ bob = Author.create!(name: "Bob")
86
+
87
+ authors = author_repository.find_all(sort_order: Uchi::SortOrder.new(:name, :desc))
88
+
89
+ assert_equal [bob, alice], authors
90
+ end
91
+
92
+ test "#find returns a single record by its ID" do
93
+ alice = Author.create!(name: "Alice")
94
+
95
+ result = author_repository.find(alice.id)
96
+
97
+ assert_equal alice, result
98
+ end
99
+
100
+ test "#find raises ActiveRecord::RecordNotFound when the record is not found" do
101
+ assert_raises(ActiveRecord::RecordNotFound) do
102
+ author_repository.find(42)
103
+ end
104
+ end
105
+
106
+ test "#model returns the model class the repository manages" do
107
+ assert_equal Author, author_repository.model
108
+ end
109
+
110
+ test "#routes returns an instance of the routes helper" do
111
+ assert_instance_of Uchi::Repository::Routes, author_repository.routes
112
+ end
113
+
114
+ test "#searchable? returns true if the repository has searchable fields" do
115
+ assert author_repository.searchable?
116
+ end
117
+
118
+ test "#title returns a string representation of the record" do
119
+ author = Author.new(name: "Alice")
120
+
121
+ assert_equal "Alice", author_repository.title(author)
122
+ end
123
+
124
+ test "#title returns nil when record is nil" do
125
+ assert_nil author_repository.title(nil)
126
+ end
127
+
128
+ test "#translate returns the translate helper" do
129
+ assert_instance_of Uchi::Repository::Translate, author_repository.translate
130
+ end
131
+
132
+ private
133
+
134
+ def author_repository
135
+ Uchi::Repositories::Author.new
136
+ end
137
+ end
@@ -0,0 +1,47 @@
1
+ require "test_helper"
2
+
3
+ class UchiSortOrderTest < ActiveSupport::TestCase
4
+ test ".from_params returns nil when no params are given" do
5
+ assert_nil Uchi::SortOrder.from_params({})
6
+ end
7
+
8
+ test ".from_params defaults to ascending when direction isn't given" do
9
+ sort_order = Uchi::SortOrder.from_params(sort: {by: :name})
10
+ assert_instance_of Uchi::SortOrder, sort_order
11
+ assert_equal :name, sort_order.name
12
+ assert_equal :asc, sort_order.direction
13
+ end
14
+
15
+ test ".from_params returns a new SortOrder when both 'by' and 'direction' are given" do
16
+ sort_order = Uchi::SortOrder.from_params(sort: {by: :born_on, direction: :desc})
17
+ assert_instance_of Uchi::SortOrder, sort_order
18
+ assert_equal :born_on, sort_order.name
19
+ assert_equal :desc, sort_order.direction
20
+ end
21
+
22
+ test "#ascending? returns true when direction is :asc" do
23
+ assert Uchi::SortOrder.new(:id, :asc).ascending?
24
+ end
25
+
26
+ test "#ascending? returns false when direction is :desc" do
27
+ assert_not Uchi::SortOrder.new(:id, :desc).ascending?
28
+ end
29
+
30
+ test "#apply applies the sort order to the given query" do
31
+ sort_order = Uchi::SortOrder.new(:name, :desc)
32
+ query = Author.all
33
+
34
+ sorted_query = sort_order.apply(query)
35
+
36
+ assert_includes sorted_query.to_sql, "ORDER BY \"authors\".\"name\" DESC"
37
+ assert_equal sorted_query, query.order(name: :desc)
38
+ end
39
+
40
+ test "#descending? returns false when direction is :asc" do
41
+ assert_not Uchi::SortOrder.new(:id, :asc).descending?
42
+ end
43
+
44
+ test "#descending? returns true when direction is :desc" do
45
+ assert Uchi::SortOrder.new(:id, :desc).descending?
46
+ end
47
+ end
data/test/uchi_test.rb ADDED
@@ -0,0 +1,7 @@
1
+ require "test_helper"
2
+
3
+ class UchiTest < ActiveSupport::TestCase
4
+ test "it has a version number" do
5
+ assert Uchi::VERSION
6
+ end
7
+ end