apes 1.0.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 (122) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +7 -0
  3. data/.rubocop.yml +82 -0
  4. data/.travis-gemfile +15 -0
  5. data/.travis.yml +15 -0
  6. data/.yardopts +1 -0
  7. data/CHANGELOG.md +3 -0
  8. data/Gemfile +22 -0
  9. data/README.md +177 -0
  10. data/Rakefile +44 -0
  11. data/apes.gemspec +34 -0
  12. data/doc/Apes.html +130 -0
  13. data/doc/Apes/Concerns.html +127 -0
  14. data/doc/Apes/Concerns/Errors.html +1089 -0
  15. data/doc/Apes/Concerns/Pagination.html +636 -0
  16. data/doc/Apes/Concerns/Request.html +766 -0
  17. data/doc/Apes/Concerns/Response.html +940 -0
  18. data/doc/Apes/Controller.html +1100 -0
  19. data/doc/Apes/Errors.html +125 -0
  20. data/doc/Apes/Errors/AuthenticationError.html +133 -0
  21. data/doc/Apes/Errors/BadRequestError.html +157 -0
  22. data/doc/Apes/Errors/BaseError.html +320 -0
  23. data/doc/Apes/Errors/InvalidDataError.html +157 -0
  24. data/doc/Apes/Errors/MissingDataError.html +157 -0
  25. data/doc/Apes/Model.html +378 -0
  26. data/doc/Apes/PaginationCursor.html +2138 -0
  27. data/doc/Apes/RuntimeConfiguration.html +909 -0
  28. data/doc/Apes/Serializers.html +125 -0
  29. data/doc/Apes/Serializers/JSON.html +389 -0
  30. data/doc/Apes/Serializers/JWT.html +452 -0
  31. data/doc/Apes/Serializers/List.html +347 -0
  32. data/doc/Apes/UrlsParser.html +1432 -0
  33. data/doc/Apes/Validators.html +125 -0
  34. data/doc/Apes/Validators/BaseValidator.html +278 -0
  35. data/doc/Apes/Validators/BooleanValidator.html +494 -0
  36. data/doc/Apes/Validators/EmailValidator.html +350 -0
  37. data/doc/Apes/Validators/PhoneValidator.html +375 -0
  38. data/doc/Apes/Validators/ReferenceValidator.html +372 -0
  39. data/doc/Apes/Validators/TimestampValidator.html +640 -0
  40. data/doc/Apes/Validators/UuidValidator.html +372 -0
  41. data/doc/Apes/Validators/ZipCodeValidator.html +372 -0
  42. data/doc/Apes/Version.html +189 -0
  43. data/doc/ApplicationController.html +547 -0
  44. data/doc/Concerns.html +128 -0
  45. data/doc/Concerns/ErrorHandling.html +826 -0
  46. data/doc/Concerns/PaginationHandling.html +463 -0
  47. data/doc/Concerns/RequestHandling.html +512 -0
  48. data/doc/Concerns/ResponseHandling.html +579 -0
  49. data/doc/Errors.html +126 -0
  50. data/doc/Errors/AuthenticationError.html +123 -0
  51. data/doc/Errors/BadRequestError.html +147 -0
  52. data/doc/Errors/BaseError.html +289 -0
  53. data/doc/Errors/InvalidDataError.html +147 -0
  54. data/doc/Errors/MissingDataError.html +147 -0
  55. data/doc/Model.html +315 -0
  56. data/doc/PaginationCursor.html +764 -0
  57. data/doc/Serializers.html +126 -0
  58. data/doc/Serializers/JSON.html +253 -0
  59. data/doc/Serializers/JWT.html +253 -0
  60. data/doc/Serializers/List.html +245 -0
  61. data/doc/Validators.html +126 -0
  62. data/doc/Validators/BaseValidator.html +209 -0
  63. data/doc/Validators/BooleanValidator.html +391 -0
  64. data/doc/Validators/EmailValidator.html +298 -0
  65. data/doc/Validators/PhoneValidator.html +313 -0
  66. data/doc/Validators/ReferenceValidator.html +284 -0
  67. data/doc/Validators/TimestampValidator.html +476 -0
  68. data/doc/Validators/UuidValidator.html +310 -0
  69. data/doc/Validators/ZipCodeValidator.html +310 -0
  70. data/doc/_index.html +435 -0
  71. data/doc/class_list.html +58 -0
  72. data/doc/css/common.css +1 -0
  73. data/doc/css/full_list.css +57 -0
  74. data/doc/css/style.css +339 -0
  75. data/doc/file.README.html +252 -0
  76. data/doc/file_list.html +60 -0
  77. data/doc/frames.html +26 -0
  78. data/doc/index.html +252 -0
  79. data/doc/js/app.js +219 -0
  80. data/doc/js/full_list.js +181 -0
  81. data/doc/js/jquery.js +4 -0
  82. data/doc/method_list.html +615 -0
  83. data/doc/top-level-namespace.html +112 -0
  84. data/lib/apes.rb +40 -0
  85. data/lib/apes/concerns/errors.rb +111 -0
  86. data/lib/apes/concerns/pagination.rb +81 -0
  87. data/lib/apes/concerns/request.rb +237 -0
  88. data/lib/apes/concerns/response.rb +74 -0
  89. data/lib/apes/controller.rb +77 -0
  90. data/lib/apes/errors.rb +38 -0
  91. data/lib/apes/model.rb +94 -0
  92. data/lib/apes/pagination_cursor.rb +152 -0
  93. data/lib/apes/runtime_configuration.rb +80 -0
  94. data/lib/apes/serializers.rb +88 -0
  95. data/lib/apes/urls_parser.rb +233 -0
  96. data/lib/apes/validators.rb +234 -0
  97. data/lib/apes/version.rb +24 -0
  98. data/spec/apes/concerns/errors_spec.rb +141 -0
  99. data/spec/apes/concerns/pagination_spec.rb +114 -0
  100. data/spec/apes/concerns/request_spec.rb +244 -0
  101. data/spec/apes/concerns/response_spec.rb +79 -0
  102. data/spec/apes/controller_spec.rb +54 -0
  103. data/spec/apes/errors_spec.rb +14 -0
  104. data/spec/apes/models_spec.rb +148 -0
  105. data/spec/apes/pagination_cursor_spec.rb +113 -0
  106. data/spec/apes/runtime_configuration_spec.rb +100 -0
  107. data/spec/apes/serializers_spec.rb +70 -0
  108. data/spec/apes/urls_parser_spec.rb +150 -0
  109. data/spec/apes/validators_spec.rb +237 -0
  110. data/spec/spec_helper.rb +30 -0
  111. data/views/_included.json.jbuilder +9 -0
  112. data/views/_pagination.json.jbuilder +9 -0
  113. data/views/collection.json.jbuilder +4 -0
  114. data/views/errors/400.json.jbuilder +9 -0
  115. data/views/errors/403.json.jbuilder +7 -0
  116. data/views/errors/404.json.jbuilder +6 -0
  117. data/views/errors/422.json.jbuilder +19 -0
  118. data/views/errors/500.json.jbuilder +12 -0
  119. data/views/errors/501.json.jbuilder +7 -0
  120. data/views/layouts/general.json.jbuilder +36 -0
  121. data/views/object.json.jbuilder +4 -0
  122. metadata +262 -0
@@ -0,0 +1,79 @@
1
+ require "spec_helper"
2
+
3
+ describe Apes::Concerns::Response do
4
+ class ResponseHandlingMockContainer
5
+ include Apes::Concerns::Response
6
+ end
7
+
8
+ module Mockspace
9
+ class NameMockController
10
+ end
11
+ end
12
+
13
+ subject { ResponseHandlingMockContainer.new }
14
+
15
+ describe "#response_template_for" do
16
+ it "should return the right template" do
17
+ expect(subject.response_template_for(Mockspace::NameMockController.new)).to eq("mockspace_name_mock_controller")
18
+ expect(subject.response_template_for([Mockspace::NameMockController.new])).to eq("mockspace_name_mock_controller")
19
+ end
20
+ end
21
+
22
+ describe "#response_meta" do
23
+ it "should return the right meta" do
24
+ expect(subject.response_meta).to be_a(HashWithIndifferentAccess)
25
+ expect(subject.response_meta("FOO")).to eq("FOO")
26
+
27
+ subject.instance_variable_set(:@meta, "BAR")
28
+ expect(subject.response_meta).to eq("BAR")
29
+ end
30
+ end
31
+
32
+ describe "#response_data" do
33
+ it "should return the right data" do
34
+ expect(subject.response_data).to be_a(HashWithIndifferentAccess)
35
+ expect(subject.response_data("FOO")).to eq("FOO")
36
+
37
+ subject.instance_variable_set(:@data, "BAR")
38
+ expect(subject.response_data).to eq("BAR")
39
+ end
40
+ end
41
+
42
+ describe "#response_links" do
43
+ it "should return the right links" do
44
+ expect(subject.response_links).to be_a(HashWithIndifferentAccess)
45
+ expect(subject.response_links("FOO")).to eq("FOO")
46
+
47
+ subject.instance_variable_set(:@links, "BAR")
48
+ expect(subject.response_links).to eq("BAR")
49
+ end
50
+ end
51
+
52
+ describe "#response_included" do
53
+ it "should return the right included data" do
54
+ allow(subject).to receive(:controller).and_return(OpenStruct.new(included: nil))
55
+ expect(subject.response_included).to be_a(HashWithIndifferentAccess)
56
+ expect(subject.response_included("FOO")).to eq("FOO")
57
+
58
+ allow(subject).to receive(:controller).and_return(OpenStruct.new(included: "BAR"))
59
+ subject.instance_variable_set(:@links, "BAR")
60
+ expect(subject.response_links).to eq("BAR")
61
+ end
62
+ end
63
+
64
+ describe "#response_include" do
65
+ it "should add included data" do
66
+ data = {}
67
+ allow(subject).to receive(:controller).and_return(OpenStruct.new(included: data))
68
+
69
+ subject.response_include("DATA")
70
+ expect(data).to eq({"string:DATA"=>["DATA", nil]})
71
+ end
72
+ end
73
+
74
+ describe "#response_timestamp" do
75
+ it "should return the right timestamp" do
76
+ expect(subject.response_timestamp(DateTime.civil(2024, 12, 6, 3, 2, 1, "+7"))).to eq("2024-12-06T03:02:01.000+0700")
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,54 @@
1
+ #
2
+ # This file is part of the apes gem. Copyright (C) 2016 and above Shogun <shogun@cowtech.it>.
3
+ # Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
4
+ #
5
+
6
+ require "spec_helper"
7
+
8
+ describe Apes::Controller do
9
+ describe "#handle_cors", type: :controller do
10
+ it "should render the right content" do
11
+ expect(subject).to receive(:render).with(nothing: true, status: :no_content)
12
+ subject.handle_cors
13
+ end
14
+ end
15
+
16
+ describe "#default_url_options" do
17
+ it "should always mark the host as needed in URLs" do
18
+ allow(Apes::RuntimeConfiguration).to receive(:development?).and_return(true)
19
+ expect(subject).to receive(:request).and_return(OpenStruct.new(url: "http://localhost"))
20
+ expect(subject.default_url_options[:only_path]).to be_falsey
21
+ end
22
+ end
23
+
24
+ describe "#render_error" do
25
+ it "should render the right template" do
26
+ expect(subject).to receive(:render).with("errors/403", status: :forbidden)
27
+ subject.render_error(:forbidden, ["1", "2"])
28
+ expect(subject.instance_variable_get(:@errors)).to eq(["1", "2"])
29
+
30
+ expect(subject).to receive(:render).with("errors/404", status: 404)
31
+ subject.render_error(404, ["3", "4"])
32
+ expect(subject.instance_variable_get(:@errors)).to eq(["3", "4"])
33
+ end
34
+ end
35
+
36
+ describe "#render_default_views (private)" do
37
+ it "should render the object template if a object is set" do
38
+ subject.instance_variable_set(:@object, "FOO")
39
+ expect(subject).to receive(:render).with("/object")
40
+ subject.send(:render_default_views, RuntimeError.new)
41
+ end
42
+
43
+ it "should render the collection template if a collection is set" do
44
+ subject.instance_variable_set(:@objects, "FOO")
45
+ expect(subject).to receive(:render).with("/collection")
46
+ subject.send(:render_default_views, RuntimeError.new)
47
+ end
48
+
49
+ it "should fallback to the default handler otherwise" do
50
+ expect(subject).to receive(:error_handle_exception).with(an_instance_of(RuntimeError))
51
+ subject.send(:render_default_views, RuntimeError.new)
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,14 @@
1
+ #
2
+ # This file is part of the apes gem. Copyright (C) 2016 and above Shogun <shogun@cowtech.it>.
3
+ # Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
4
+ #
5
+
6
+ require "spec_helper"
7
+
8
+ describe Apes::Errors::BaseError do
9
+ it "should save details" do
10
+ subject = Apes::Errors::BaseError.new({a: 1})
11
+ expect(subject.message).to eq("")
12
+ expect(subject.details).to eq({a: 1})
13
+ end
14
+ end
@@ -0,0 +1,148 @@
1
+ #
2
+ # This file is part of the apes gem. Copyright (C) 2016 and above Shogun <shogun@cowtech.it>.
3
+ # Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
4
+ #
5
+
6
+ require "spec_helper"
7
+
8
+ describe Apes::Model do
9
+ class MockBaseModel < ActiveRecord::Base
10
+ include Apes::Model
11
+
12
+ self.abstract_class = true
13
+ end
14
+
15
+ class MockQueryingModel < MockBaseModel
16
+ SECONDARY_QUERY = "name = :id"
17
+
18
+ def self.table_name
19
+ "querying_temp_table"
20
+ end
21
+
22
+ attr_reader :field
23
+ validates :field, "presence" => true
24
+ end
25
+
26
+ class MockQueryingOtherModel < MockBaseModel
27
+ include Apes::Model
28
+
29
+ SECONDARY_KEY = :handle
30
+
31
+ def self.table_name
32
+ "querying_temp_table"
33
+ end
34
+ end
35
+
36
+ class MockQueryingAnotherModel < MockBaseModel
37
+ include Apes::Model
38
+
39
+ def self.table_name
40
+ "querying_temp_table"
41
+ end
42
+ end
43
+
44
+ subject {
45
+ MockQueryingModel.new(id: SecureRandom.uuid, handle: "HANDLE", name: "NAME")
46
+ }
47
+
48
+ around(:each) do |example|
49
+ db = Tempfile.new("apes-test")
50
+ MockBaseModel.establish_connection(adapter: "sqlite3", database: db.path)
51
+ MockBaseModel.connection.execute("CREATE TABLE IF NOT EXISTS querying_temp_table(id uuid, handle varchar, name varchar);")
52
+ example.call
53
+ db.unlink
54
+ end
55
+
56
+ describe ".find_with_any!" do
57
+ it "should find a record using the primary key when the ID is a UUID" do
58
+ expect(MockQueryingOtherModel).to receive(:find).with(subject.id).and_return(subject)
59
+ expect(MockQueryingOtherModel.find_with_any!(subject.id)).to eq(subject)
60
+ end
61
+
62
+ it "should find a record using the secondary key" do
63
+ expect(MockQueryingOtherModel).to receive(:find_by!).with(handle: subject.handle).and_return(subject)
64
+ expect(MockQueryingOtherModel.find_with_any!(subject.handle)).to eq(subject)
65
+ end
66
+
67
+ it "should find a record using the secondary query" do
68
+ expect(MockQueryingModel).to receive(:find_by!).with("name = :id", {id: subject.name}).and_return(subject)
69
+ expect(MockQueryingModel.find_with_any!(subject.name).id).to eq(subject.id)
70
+ end
71
+
72
+ it "should fallback to a reasonable query" do
73
+ expect(MockQueryingAnotherModel).to receive(:find_by!).with(handle: subject.handle).and_return(subject)
74
+ expect(MockQueryingAnotherModel.find_with_any!(subject.handle).id).to eq(subject.id)
75
+ end
76
+
77
+ it "should raise an exception when nothing is found" do
78
+ expect { MockQueryingOtherModel.find_with_any!("NOTHING") }.to raise_error(ActiveRecord::RecordNotFound)
79
+ end
80
+ end
81
+
82
+ describe ".find_with_any" do
83
+ it "should find a records" do
84
+ expect(MockQueryingOtherModel).to receive(:find_by!).with(handle: subject.handle).and_return(subject)
85
+ expect(MockQueryingOtherModel.find_with_any(subject.handle)).to eq(subject)
86
+ end
87
+
88
+ it "should raise an exception when nothing is found" do
89
+ expect { MockQueryingOtherModel.find_with_any("NOTHING") }.not_to raise_error
90
+ end
91
+ end
92
+
93
+ describe ".search" do
94
+ let(:params) { {filter: {query: "ABC"}} }
95
+ let(:table_name) { "querying_temp_table" }
96
+
97
+ it "should do nothing if no value is present" do
98
+ expect(MockQueryingOtherModel.search().to_sql).to eq("SELECT \"#{table_name}\".* FROM \"#{table_name}\"")
99
+ end
100
+
101
+ it "should perform a query on the fields" do
102
+ expect(MockQueryingOtherModel.search(params: params, fields: [:name, :token, :secret]).to_sql).to eq("SELECT \"#{table_name}\".* FROM \"#{table_name}\" WHERE (name ILIKE '%ABC%' OR token ILIKE '%ABC%' OR secret ILIKE '%ABC%')")
103
+ end
104
+
105
+ it "should allow prefix based queries" do
106
+ expect(MockQueryingOtherModel.search(params: params, start_only: true).to_sql).to eq("SELECT \"#{table_name}\".* FROM \"#{table_name}\" WHERE (name ILIKE 'ABC%')")
107
+ end
108
+
109
+ it "should allow case sensitive searches" do
110
+ expect(MockQueryingOtherModel.search(params: params, case_sensitive: true).to_sql).to eq("SELECT \"#{table_name}\".* FROM \"#{table_name}\" WHERE (name LIKE '%ABC%')")
111
+ end
112
+
113
+ it "should allow to use AND based searches" do
114
+ expect(MockQueryingOtherModel.search(params: params, method: :other).to_sql).to eq("SELECT \"#{table_name}\".* FROM \"#{table_name}\" WHERE (name ILIKE '%ABC%')")
115
+ end
116
+
117
+ it "should extend existing queries" do
118
+ expect(MockQueryingOtherModel.search(params: params, query: MockQueryingOtherModel.where("secret IS NOT NULL")).to_sql).to eq("SELECT \"#{table_name}\".* FROM \"#{table_name}\" WHERE (secret IS NOT NULL) AND (name ILIKE '%ABC%')")
119
+ end
120
+ end
121
+
122
+ describe "#additional_errors" do
123
+ it "should return a ActiveModel::Errors object" do
124
+ expect(MockQueryingModel.new.additional_errors).to be_a(ActiveModel::Errors)
125
+ end
126
+ end
127
+
128
+ describe "#run_validations!" do
129
+ it "should merge errors when validating" do
130
+ subject = MockQueryingModel.new
131
+ subject.additional_errors.add(:field, "ANOTHER")
132
+ subject.validate
133
+ expect(subject.errors.to_hash).to eq({field: ["ANOTHER", "can't be blank"]})
134
+ end
135
+ end
136
+
137
+ describe "#all_validation_errors" do
138
+ it "should allow to add additional errors after validation" do
139
+ subject = MockQueryingModel.new
140
+ expect(subject.all_validation_errors.to_hash).to eq({})
141
+ subject.validate
142
+ expect(subject.all_validation_errors.to_hash).to eq({field: ["can't be blank"]})
143
+ subject.additional_errors.add(:field, "ANOTHER")
144
+ expect(subject.all_validation_errors.to_hash).to eq({field: ["can't be blank", "ANOTHER"]})
145
+ expect(subject.all_validation_errors.to_hash).to eq({field: ["can't be blank", "ANOTHER"]}) # Should not add errors twice
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,113 @@
1
+ #
2
+ # This file is part of the apes gem. Copyright (C) 2016 and above Shogun <shogun@cowtech.it>.
3
+ # Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
4
+ #
5
+
6
+ require "spec_helper"
7
+
8
+ describe Apes::PaginationCursor do
9
+ def create_cursor(value = nil, direction = "next", count = nil, use_offset = false)
10
+ Apes::PaginationCursor.new({count: count, page: JWT.encode({aud: "pagination", sub: {value: value, use_offset: use_offset, direction: direction}}, Apes::RuntimeConfiguration.jwt_token, "HS256")})
11
+ end
12
+
13
+ def decode_cursor(cursor)
14
+ JWT.decode(cursor, Apes::RuntimeConfiguration.jwt_token, true, {algorithm: "HS256", verify_aud: true, aud: "pagination"}).dig(0, "sub")
15
+ end
16
+
17
+ describe "#initialize" do
18
+ it "should load a JWT token from data" do
19
+ subject = create_cursor("1", "previous", 3, true)
20
+
21
+ expect(subject.value).to eq("1")
22
+ expect(subject.direction).to eq("previous")
23
+ expect(subject.size).to eq(3)
24
+ expect(subject.use_offset).to be_truthy
25
+ end
26
+
27
+ it "should ensure good defaults" do
28
+ subject = Apes::PaginationCursor.new({count: 3, page: "FOO"})
29
+
30
+ expect(subject.value).to be_nil
31
+ expect(subject.direction).to eq("next")
32
+ expect(subject.size).to eq(3)
33
+ expect(subject.use_offset).to be_falsey
34
+
35
+ end
36
+
37
+ it "should sanitize values" do
38
+ subject = create_cursor("1", "other", -1)
39
+
40
+ expect(subject.direction).to eq("next")
41
+ expect(subject.size).to eq(Apes::PaginationCursor::DEFAULT_SIZE)
42
+ end
43
+ end
44
+
45
+ describe "#operator" do
46
+ it "should return the right operator" do
47
+ subject = create_cursor("", "next", -1)
48
+ expect(subject.operator(:asc)).to eq(">")
49
+ expect(subject.operator(:desc)).to eq("<")
50
+
51
+ subject = create_cursor("", "previous", -1)
52
+ expect(subject.operator(:asc)).to eq("<")
53
+ expect(subject.operator(:desc)).to eq(">")
54
+ end
55
+ end
56
+
57
+ describe "#might_exist?" do
58
+ it "should check if a pagination link might exist" do
59
+ subject = create_cursor("", "next", -1)
60
+ expect(subject.might_exist?("first", [])).to be_truthy
61
+ expect(subject.might_exist?("next", [])).to be_falsey
62
+ expect(subject.might_exist?("prev", [])).to be_falsey
63
+ expect(subject.might_exist?("first", [1])).to be_truthy
64
+ expect(subject.might_exist?("next", [1])).to be_truthy
65
+ expect(subject.might_exist?("prev", [1])).to be_falsey
66
+
67
+ subject = create_cursor("1", "next", -1)
68
+ expect(subject.might_exist?("prev", [1])).to be_truthy
69
+ end
70
+ end
71
+
72
+ describe "#save" do
73
+ describe "when NOT using offset based pagination" do
74
+ it "should generate a valid token for direction next" do
75
+ cursor = create_cursor(1, "next", -1).save([OpenStruct.new(id: 1), OpenStruct.new(id: 2)], "next")
76
+ subject = decode_cursor(cursor)
77
+ expect(subject).to eq({"value" => 2, "use_offset" => false, "direction" => "next", "size" => 25})
78
+ end
79
+
80
+ it "should generate a valid token for direction prev" do
81
+ cursor = create_cursor(1, "next", -1).save([OpenStruct.new(id: 1), OpenStruct.new(id: 2)], "previous")
82
+ subject = decode_cursor(cursor)
83
+ expect(subject).to eq({"value" => 1, "use_offset" => false, "direction" => "previous", "size" => 25})
84
+ end
85
+
86
+ it "should generate a valid token for direction first" do
87
+ cursor = create_cursor(1, "next", -1).save([OpenStruct.new(id: 1), OpenStruct.new(id: 2)], "first")
88
+ subject = decode_cursor(cursor)
89
+ expect(subject).to eq({"value" => nil, "use_offset" => false, "direction" => "next", "size" => 25})
90
+ end
91
+ end
92
+
93
+ describe "when using offset based pagination" do
94
+ it "should generate a valid token for direction next" do
95
+ cursor = create_cursor(30, "next", -1).save([OpenStruct.new(id: 1), OpenStruct.new(id: 2)], "next", use_offset: true)
96
+ subject = decode_cursor(cursor)
97
+ expect(subject).to eq({"value" => 55, "use_offset" => true, "direction" => "next", "size" => 25})
98
+ end
99
+
100
+ it "should generate a valid token for direction prev" do
101
+ cursor = create_cursor(30, "next", -1).save([OpenStruct.new(id: 1), OpenStruct.new(id: 2)], "previous", use_offset: true)
102
+ subject = decode_cursor(cursor)
103
+ expect(subject).to eq({"value" => 5, "use_offset" => true, "direction" => "previous", "size" => 25})
104
+ end
105
+
106
+ it "should generate a valid token for direction first" do
107
+ cursor = create_cursor(30, "next", -1).save([OpenStruct.new(id: 1), OpenStruct.new(id: 2)], "first", use_offset: true)
108
+ subject = decode_cursor(cursor)
109
+ expect(subject).to eq({"value" => nil, "use_offset" => true, "direction" => "next", "size" => 25})
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,100 @@
1
+ #
2
+ # This file is part of the apes gem. Copyright (C) 2016 and above Shogun <shogun@cowtech.it>.
3
+ # Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
4
+ #
5
+
6
+ require "spec_helper"
7
+
8
+ describe Apes::RuntimeConfiguration do
9
+ describe ".root" do
10
+ it "should get the information from RubyGems" do
11
+ expect(Apes::RuntimeConfiguration.root).to be_a(String)
12
+ end
13
+ end
14
+
15
+ describe ".rails_root" do
16
+ it "should get the information from Rails" do
17
+ stub_const("Rails", {root: "/ABC"}.ensure_access(:dotted))
18
+ expect(Apes::RuntimeConfiguration.rails_root).to eq("/ABC")
19
+ end
20
+
21
+ it "should fallback to a default" do
22
+ allow(Rails).to receive(:root).and_raise(RuntimeError)
23
+
24
+ expect(Apes::RuntimeConfiguration.rails_root).to be_nil
25
+ expect(Apes::RuntimeConfiguration.rails_root("DEFAULT")).to eq("DEFAULT")
26
+ end
27
+ end
28
+
29
+ describe ".gems_root" do
30
+ it "should get the information from Rails" do
31
+ expect(Apes::RuntimeConfiguration.gems_root).to be_a(String)
32
+ end
33
+
34
+ it "should fallback to a default" do
35
+ allow(Gem).to receive(:loaded_specs).and_raise(RuntimeError)
36
+
37
+ expect(Apes::RuntimeConfiguration.gems_root).to be_nil
38
+ expect(Apes::RuntimeConfiguration.gems_root("DEFAULT")).to eq("DEFAULT")
39
+ end
40
+ end
41
+
42
+ describe ".environment" do
43
+ it "should get the information from Rails secrets" do
44
+ stub_const("Rails", {env: "FOO"}.ensure_access(:dotted))
45
+ expect(Apes::RuntimeConfiguration.environment).to eq("FOO")
46
+ end
47
+
48
+ it "should fallback to a default" do
49
+ allow(Rails).to receive(:env).and_raise(RuntimeError)
50
+ expect(Apes::RuntimeConfiguration.environment).to eq("development")
51
+ expect(Apes::RuntimeConfiguration.environment("DEFAULT")).to eq("DEFAULT")
52
+ end
53
+ end
54
+
55
+ describe ".environment" do
56
+ it "should check if Rails is in development" do
57
+ stub_const("Rails", {env: "development"}.ensure_access(:dotted))
58
+ expect(Apes::RuntimeConfiguration.development?).to be_truthy
59
+
60
+ stub_const("Rails", {env: "FOO"}.ensure_access(:dotted))
61
+ expect(Apes::RuntimeConfiguration.development?).to be_falsey
62
+ end
63
+ end
64
+
65
+ describe ".jwt_token" do
66
+ it "should get the information from Rails secrets" do
67
+ stub_const("Rails", {application: {secrets: {jwt: "SECRET"}}}.ensure_access(:dotted))
68
+ expect(Apes::RuntimeConfiguration.jwt_token).to eq("SECRET")
69
+ end
70
+
71
+ it "should fallback to a default" do
72
+ expect(Apes::RuntimeConfiguration.jwt_token).to eq("secret")
73
+ expect(Apes::RuntimeConfiguration.jwt_token("DEFAULT")).to eq("DEFAULT")
74
+ end
75
+ end
76
+
77
+ describe ".cors_source" do
78
+ it "should get the information from Rails secrets" do
79
+ stub_const("Rails", {application: {secrets: {cors_source: "SOURCE"}}}.ensure_access(:dotted))
80
+ expect(Apes::RuntimeConfiguration.cors_source).to eq("SOURCE")
81
+ end
82
+
83
+ it "should fallback to a default" do
84
+ expect(Apes::RuntimeConfiguration.cors_source).to eq("localhost")
85
+ expect(Apes::RuntimeConfiguration.cors_source("DEFAULT")).to eq("DEFAULT")
86
+ end
87
+ end
88
+
89
+ describe ".timestamp_formats" do
90
+ it "should get the information from Rails secrets" do
91
+ stub_const("Rails", {application: {config: {timestamp_formats: {a: 1}}}}.ensure_access(:dotted))
92
+ expect(Apes::RuntimeConfiguration.timestamp_formats).to eq({a: 1})
93
+ end
94
+
95
+ it "should fallback to a default" do
96
+ expect(Apes::RuntimeConfiguration.timestamp_formats).to eq({})
97
+ expect(Apes::RuntimeConfiguration.timestamp_formats("DEFAULT")).to eq("DEFAULT")
98
+ end
99
+ end
100
+ end