flagsmith 4.0.1 → 4.1.1

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 (44) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +5 -3
  3. data/lib/flagsmith/engine/environments/models.rb +14 -3
  4. data/lib/flagsmith/sdk/analytics_processor.rb +7 -2
  5. data/lib/flagsmith/sdk/config.rb +4 -1
  6. data/lib/flagsmith/sdk/pooling_manager.rb +15 -2
  7. data/lib/flagsmith/version.rb +1 -1
  8. data/lib/flagsmith.rb +31 -9
  9. metadata +2 -37
  10. data/example/.env.development +0 -5
  11. data/example/.env.test +0 -4
  12. data/example/.gitignore +0 -5
  13. data/example/.hanamirc +0 -3
  14. data/example/.rspec +0 -2
  15. data/example/Gemfile +0 -25
  16. data/example/Gemfile.lock +0 -274
  17. data/example/README.md +0 -29
  18. data/example/Rakefile +0 -9
  19. data/example/apps/web/application.rb +0 -162
  20. data/example/apps/web/config/routes.rb +0 -1
  21. data/example/apps/web/controllers/.gitkeep +0 -0
  22. data/example/apps/web/controllers/home/index.rb +0 -32
  23. data/example/apps/web/templates/application.html.slim +0 -7
  24. data/example/apps/web/templates/home/index.html.slim +0 -10
  25. data/example/apps/web/views/application_layout.rb +0 -7
  26. data/example/apps/web/views/home/index.rb +0 -29
  27. data/example/config/boot.rb +0 -2
  28. data/example/config/environment.rb +0 -17
  29. data/example/config/initializers/.gitkeep +0 -0
  30. data/example/config/initializers/flagsmith.rb +0 -7
  31. data/example/config/puma.rb +0 -15
  32. data/example/config.ru +0 -3
  33. data/example/spec/example/entities/.gitkeep +0 -0
  34. data/example/spec/example/mailers/.gitkeep +0 -0
  35. data/example/spec/example/repositories/.gitkeep +0 -0
  36. data/example/spec/features_helper.rb +0 -12
  37. data/example/spec/spec_helper.rb +0 -103
  38. data/example/spec/support/.gitkeep +0 -0
  39. data/example/spec/support/capybara.rb +0 -8
  40. data/example/spec/web/controllers/.gitkeep +0 -0
  41. data/example/spec/web/controllers/home/index_spec.rb +0 -9
  42. data/example/spec/web/features/.gitkeep +0 -0
  43. data/example/spec/web/views/application_layout_spec.rb +0 -10
  44. data/example/spec/web/views/home/index_spec.rb +0 -10
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bf49e28a71c8b23ec9ec005b827dd4354cef0471504ca65e40808d4c206f65ad
4
- data.tar.gz: de53c7c6d6d17918b5a8ffdf0bdc505a641a63cb637d3dd74ac26c7da5442a99
3
+ metadata.gz: 8b908dee8f4935d4c754400d2e314e8a61e545dc242490ca396704f6b00ef1e1
4
+ data.tar.gz: 4c9203ad57f71fb3699b78ccb9a50aa7b4c89eaf1433803d0c16e3b7644a91c3
5
5
  SHA512:
6
- metadata.gz: ff47303eae7c600cf32807a4b3aad303fa8fbac31678570d9262366e152e96342083ed31f9f8be91614ebfee10c525707ae66ec418a193dc32c35513686816bd
7
- data.tar.gz: 0d2cc7b84114d1595c93c8e6adea2aa4de9e8f3576bd3bd2cab0fcaac54131ec25ba5cbdd7f74cf795b8846f74aeeeabf9fd0bccadf99e98c104030a134fa4f3
6
+ metadata.gz: a41d33186ccd7bf6b7405a123186888ea9aef9e0890762b2384d1681b897ceed602e471eb4903190bf09b0c1c48a6b99a831053f10dde55cbcd6e9875851dfde
7
+ data.tar.gz: e654da93bb040ce2a08fa0cb6b15d167a2b557853fec1e8deb3cd45df124177998d7fb40e6ccae777cf8e62b0cdc72efd0cbd3a8e6fd4fcd894ed2b23d228c90
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- flagsmith (4.0.1)
4
+ flagsmith (4.1.1)
5
5
  faraday (>= 2.0.1)
6
6
  faraday-retry
7
7
  semantic
@@ -17,7 +17,7 @@ GEM
17
17
  faraday-net_http (>= 2.0, < 3.2)
18
18
  faraday-net_http (3.1.0)
19
19
  net-http
20
- faraday-retry (2.2.0)
20
+ faraday-retry (2.2.1)
21
21
  faraday (~> 2.0)
22
22
  gem-release (2.2.2)
23
23
  json (2.7.1)
@@ -39,7 +39,8 @@ GEM
39
39
  rainbow (3.1.1)
40
40
  rake (13.1.0)
41
41
  regexp_parser (2.9.0)
42
- rexml (3.2.6)
42
+ rexml (3.2.8)
43
+ strscan (>= 3.0.9)
43
44
  rspec (3.12.0)
44
45
  rspec-core (~> 3.12.0)
45
46
  rspec-expectations (~> 3.12.0)
@@ -68,6 +69,7 @@ GEM
68
69
  parser (>= 3.2.1.0)
69
70
  ruby-progressbar (1.13.0)
70
71
  semantic (1.6.1)
72
+ strscan (3.1.0)
71
73
  unicode-display_width (2.5.0)
72
74
  uri (0.13.0)
73
75
 
@@ -6,24 +6,35 @@ module Flagsmith
6
6
  class Environment
7
7
  attr_reader :id, :api_key
8
8
  attr_accessor :project, :feature_states, :amplitude_config, :segment_config,
9
- :mixpanel_config, :heap_config
9
+ :mixpanel_config, :heap_config, :identity_overrides
10
10
 
11
- def initialize(id:, api_key:, project:, feature_states: [])
11
+ def initialize(id:, api_key:, project:, feature_states: [], identity_overrides: [])
12
12
  @id = id
13
13
  @api_key = api_key
14
14
  @project = project
15
15
  @feature_states = feature_states
16
+ @identity_overrides = identity_overrides
16
17
  end
17
18
 
18
19
  class << self
20
+ # rubocop:disable Metrics/MethodLength
19
21
  def build(json)
20
22
  project = Flagsmith::Engine::Project.build(json[:project])
21
23
  feature_states = json[:feature_states].map do |fs|
22
24
  Flagsmith::Engine::FeatureState.build(fs)
23
25
  end
24
26
 
25
- new(**json.slice(:id, :api_key).merge(project: project, feature_states: feature_states))
27
+ identity_overrides = json.fetch(:identity_overrides, []).map do |io|
28
+ Flagsmith::Engine::Identity.build(io)
29
+ end
30
+
31
+ new(**json.slice(:id, :api_key).merge(
32
+ project: project,
33
+ feature_states: feature_states,
34
+ identity_overrides: identity_overrides
35
+ ))
26
36
  end
37
+ # rubocop:enable Metrics/MethodLength
27
38
  end
28
39
  end
29
40
 
@@ -19,15 +19,20 @@ module Flagsmith
19
19
  @analytics_data = {}
20
20
  @api_client = data.fetch(:api_client)
21
21
  @timeout = data.fetch(:timeout, 3)
22
+ @logger = data.fetch(:logger)
22
23
  end
23
24
 
24
25
  # Sends all the collected data to the api asynchronously and resets the timer
25
26
  def flush
26
27
  return if @analytics_data.empty?
27
28
 
28
- @api_client.post(ENDPOINT, @analytics_data.to_json)
29
+ begin
30
+ @api_client.post(ENDPOINT, @analytics_data.to_json)
31
+ @analytics_data = {}
32
+ rescue StandardError => e
33
+ @logger.warn "Temporarily unable to access flag analytics endpoint for exception: #{e}"
34
+ end
29
35
 
30
- @analytics_data = {}
31
36
  @last_flushed = Time.now
32
37
  end
33
38
 
@@ -7,7 +7,7 @@ module Flagsmith
7
7
  OPTIONS = %i[
8
8
  environment_key api_url custom_headers request_timeout_seconds enable_local_evaluation
9
9
  environment_refresh_interval_seconds retries enable_analytics default_flag_handler
10
- offline_mode offline_handler logger
10
+ offline_mode offline_handler polling_manager_failure_limit logger
11
11
  ].freeze
12
12
 
13
13
  # Available Configs
@@ -38,6 +38,8 @@ module Flagsmith
38
38
  # bypasses requests to the api.
39
39
  # +offline_handler+ - A file object that contains a JSON serialization of
40
40
  # the entire environment, project, flags, etc.
41
+ # +polling_manager_failure_limit+ - An integer to control how long to suppress errors in
42
+ # the polling manager for local evaluation mode.
41
43
  # +logger+ - Pass your logger, default is Logger.new($stdout)
42
44
  #
43
45
  attr_reader(*OPTIONS)
@@ -89,6 +91,7 @@ module Flagsmith
89
91
  @default_flag_handler = opts[:default_flag_handler]
90
92
  @offline_mode = opts.fetch(:offline_mode, false)
91
93
  @offline_handler = opts[:offline_handler]
94
+ @polling_manager_failure_limit = opts.fetch(:polling_manager_failure_limit, 10)
92
95
  @logger = options.fetch(:logger, Logger.new($stdout).tap { |l| l.level = :debug })
93
96
  end
94
97
  # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
@@ -7,20 +7,33 @@ module Flagsmith
7
7
  class EnvironmentDataPollingManager
8
8
  include Flagsmith::SDK::Intervals
9
9
 
10
- def initialize(main, refresh_interval_seconds)
10
+ attr_reader :failures_since_last_update
11
+
12
+ def initialize(main, refresh_interval_seconds, polling_manager_failure_limit)
11
13
  @main = main
12
14
  @refresh_interval_seconds = refresh_interval_seconds
15
+ @polling_manager_failure_limit = polling_manager_failure_limit
16
+ @failures_since_last_update = 0
13
17
  end
14
18
 
19
+ # rubocop:disable Metrics/MethodLength
15
20
  def start
16
21
  update_environment = lambda {
17
22
  stop
18
- @interval = set_interval(@refresh_interval_seconds) { @main.update_environment }
23
+ @interval = set_interval(@refresh_interval_seconds) do
24
+ @main.update_environment
25
+ @failures_since_last_update = 0
26
+ rescue StandardError => e
27
+ @failures_since_last_update += 1
28
+ @main.config.logger.warn "Failure to update the environment due to an error: #{e}"
29
+ raise e if @failures_since_last_update > @polling_manager_failure_limit
30
+ end
19
31
  }
20
32
 
21
33
  # TODO: this call should be awaited for getIdentityFlags/getEnvironmentFlags when enableLocalEvaluation is true
22
34
  update_environment.call
23
35
  end
36
+ # rubocop:enable Metrics/MethodLength
24
37
 
25
38
  def stop
26
39
  return unless @interval
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Flagsmith
4
- VERSION = '4.0.1'
4
+ VERSION = '4.1.1'
5
5
  end
data/lib/flagsmith.rb CHANGED
@@ -45,17 +45,18 @@ module Flagsmith
45
45
  #
46
46
  # :environment_key, :api_url, :custom_headers, :request_timeout_seconds, :enable_local_evaluation,
47
47
  # :environment_refresh_interval_seconds, :retries, :enable_analytics, :default_flag_handler,
48
- # :offline_mode, :offline_handler
48
+ # :offline_mode, :offline_handler, :polling_manager_failure_limit
49
49
  #
50
50
  # You can see full description in the Flagsmith::Config
51
51
 
52
- attr_reader :config, :environment
52
+ attr_reader :config, :environment, :identity_overrides_by_identifier
53
53
 
54
54
  delegate Flagsmith::Config::OPTIONS => :@config
55
55
 
56
56
  def initialize(config)
57
57
  @_mutex = Mutex.new
58
58
  @config = Flagsmith::Config.new(config)
59
+ @identity_overrides_by_identifier = {}
59
60
 
60
61
  validate_offline_mode!
61
62
 
@@ -91,7 +92,8 @@ module Flagsmith
91
92
  @analytics_processor ||=
92
93
  Flagsmith::AnalyticsProcessor.new(
93
94
  api_client: api_client,
94
- timeout: request_timeout_seconds
95
+ timeout: request_timeout_seconds,
96
+ logger: @config.logger
95
97
  )
96
98
  end
97
99
 
@@ -102,10 +104,10 @@ module Flagsmith
102
104
  def environment_data_polling_manager
103
105
  return nil unless @config.local_evaluation?
104
106
 
105
- update_environment
107
+ update_environment if @environment_data_polling_manager.nil?
106
108
 
107
109
  @environment_data_polling_manager ||= Flagsmith::EnvironmentDataPollingManager.new(
108
- self, environment_refresh_interval_seconds
110
+ self, environment_refresh_interval_seconds, @config.polling_manager_failure_limit
109
111
  ).tap(&:start)
110
112
  end
111
113
 
@@ -113,6 +115,16 @@ module Flagsmith
113
115
  # You only need to call this if you wish to bypass environment_refresh_interval_seconds.
114
116
  def update_environment
115
117
  @_mutex.synchronize { @environment = environment_from_api }
118
+ update_identity_overrides
119
+ end
120
+
121
+ def update_identity_overrides
122
+ return unless @environment
123
+
124
+ @identity_overrides_by_identifier = {}
125
+ @environment.identity_overrides.each do |identity|
126
+ @identity_overrides_by_identifier[identity.identifier] = identity
127
+ end
116
128
  end
117
129
 
118
130
  def environment_from_api
@@ -177,7 +189,7 @@ module Flagsmith
177
189
  'Local evaluation or offline handler is required to obtain identity segments.'
178
190
  end
179
191
 
180
- identity_model = build_identity_model(identifier, traits)
192
+ identity_model = get_identity_model(identifier, traits)
181
193
  segment_models = engine.get_identity_segments(environment, identity_model)
182
194
  segment_models.map { |sm| Flagsmith::Segments::Segment.new(id: sm.id, name: sm.name) }.compact
183
195
  end
@@ -194,10 +206,11 @@ module Flagsmith
194
206
  end
195
207
 
196
208
  def get_identity_flags_from_document(identifier, traits = {})
197
- identity_model = build_identity_model(identifier, traits)
209
+ identity_model = get_identity_model(identifier, traits)
198
210
 
199
211
  Flagsmith::Flags::Collection.from_feature_state_models(
200
212
  engine.get_identity_feature_states(environment, identity_model),
213
+ identity_id: identity_model.composite_key,
201
214
  analytics_processor: analytics_processor,
202
215
  default_flag_handler: default_flag_handler,
203
216
  offline_handler: offline_handler
@@ -275,19 +288,28 @@ module Flagsmith
275
288
  )
276
289
  end
277
290
 
278
- def build_identity_model(identifier, traits = {})
291
+ # rubocop:disable Metrics/MethodLength
292
+ def get_identity_model(identifier, traits = {})
279
293
  unless environment
280
294
  raise Flagsmith::ClientError,
281
- 'Unable to build identity model when no local environment present.'
295
+ 'Unable to get identity model when no local environment present.'
282
296
  end
283
297
 
284
298
  trait_models = traits.map do |key, value|
285
299
  Flagsmith::Engine::Identities::Trait.new(trait_key: key, trait_value: value)
286
300
  end
301
+
302
+ if identity_overrides_by_identifier.key? identifier
303
+ identity = identity_overrides_by_identifier[identifier]
304
+ identity.update_traits trait_models
305
+ return identity
306
+ end
307
+
287
308
  Flagsmith::Engine::Identity.new(
288
309
  identity_traits: trait_models, environment_api_key: environment_key, identifier: identifier
289
310
  )
290
311
  end
312
+ # rubocop:enable Metrics/MethodLength
291
313
 
292
314
  def generate_identities_data(identifier, traits = {})
293
315
  {
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flagsmith
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.1
4
+ version: 4.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tom Stuart
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2024-02-06 00:00:00.000000000 Z
13
+ date: 2024-05-22 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bundler
@@ -171,41 +171,6 @@ files:
171
171
  - LICENCE
172
172
  - README.md
173
173
  - Rakefile
174
- - example/.env.development
175
- - example/.env.test
176
- - example/.gitignore
177
- - example/.hanamirc
178
- - example/.rspec
179
- - example/Gemfile
180
- - example/Gemfile.lock
181
- - example/README.md
182
- - example/Rakefile
183
- - example/apps/web/application.rb
184
- - example/apps/web/config/routes.rb
185
- - example/apps/web/controllers/.gitkeep
186
- - example/apps/web/controllers/home/index.rb
187
- - example/apps/web/templates/application.html.slim
188
- - example/apps/web/templates/home/index.html.slim
189
- - example/apps/web/views/application_layout.rb
190
- - example/apps/web/views/home/index.rb
191
- - example/config.ru
192
- - example/config/boot.rb
193
- - example/config/environment.rb
194
- - example/config/initializers/.gitkeep
195
- - example/config/initializers/flagsmith.rb
196
- - example/config/puma.rb
197
- - example/spec/example/entities/.gitkeep
198
- - example/spec/example/mailers/.gitkeep
199
- - example/spec/example/repositories/.gitkeep
200
- - example/spec/features_helper.rb
201
- - example/spec/spec_helper.rb
202
- - example/spec/support/.gitkeep
203
- - example/spec/support/capybara.rb
204
- - example/spec/web/controllers/.gitkeep
205
- - example/spec/web/controllers/home/index_spec.rb
206
- - example/spec/web/features/.gitkeep
207
- - example/spec/web/views/application_layout_spec.rb
208
- - example/spec/web/views/home/index_spec.rb
209
174
  - flagsmith.gemspec
210
175
  - lib/flagsmith.rb
211
176
  - lib/flagsmith/engine/core.rb
@@ -1,5 +0,0 @@
1
- # Define ENV variables for development environment
2
- DATABASE_URL="sqlite://db/example_development.sqlite"
3
- SERVE_STATIC_ASSETS="true"
4
- WEB_SESSIONS_SECRET="4743628fa58981a0eaf99cc636146f49ceffd0ab6a8423c0e2493e67cd825f67"
5
- FLAGSMITH_ENVIRONMENT_KEY="YOUR_FLAGSMITH_ENVIRONMENT_KEY"
data/example/.env.test DELETED
@@ -1,4 +0,0 @@
1
- # Define ENV variables for test environment
2
- DATABASE_URL="sqlite://db/example_test.sqlite"
3
- SERVE_STATIC_ASSETS="true"
4
- WEB_SESSIONS_SECRET="50f1a22a68ccc6d06b48387f4cd4aa63cbaabd2b525c288f0f7a7046b10cc6ac"
data/example/.gitignore DELETED
@@ -1,5 +0,0 @@
1
- /db/*.sqlite
2
- /public/assets*
3
- /tmp
4
- .env.local
5
- .env.*.local
data/example/.hanamirc DELETED
@@ -1,3 +0,0 @@
1
- project=example
2
- test=rspec
3
- template=slim
data/example/.rspec DELETED
@@ -1,2 +0,0 @@
1
- --color
2
- --require spec_helper
data/example/Gemfile DELETED
@@ -1,25 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gem 'hanami', '~> 1.3'
4
- gem 'hanami-model', '~> 1.3'
5
- gem 'slim'
6
- gem 'sqlite3'
7
- gem "puma", "~> 6.3"
8
-
9
- gemspec path: '../'
10
-
11
- group :development do
12
- # Code reloading
13
- # See: https://guides.hanamirb.org/projects/code-reloading
14
- gem 'hanami-webconsole'
15
- gem 'shotgun', platforms: :ruby
16
- end
17
-
18
- group :test, :development do
19
- gem 'dotenv', '~> 2.4'
20
- end
21
-
22
- group :test do
23
- gem 'capybara'
24
- gem 'rspec'
25
- end
data/example/Gemfile.lock DELETED
@@ -1,274 +0,0 @@
1
- PATH
2
- remote: ..
3
- specs:
4
- flagsmith (3.1.1)
5
- faraday
6
- faraday-retry
7
- faraday_middleware
8
- semantic
9
-
10
- GEM
11
- remote: https://rubygems.org/
12
- specs:
13
- addressable (2.8.4)
14
- public_suffix (>= 2.0.2, < 6.0)
15
- ast (2.4.2)
16
- better_errors (2.9.1)
17
- coderay (>= 1.0.0)
18
- erubi (>= 1.0.0)
19
- rack (>= 0.9.0)
20
- bigdecimal (1.4.4)
21
- binding_of_caller (0.8.0)
22
- debug_inspector (>= 0.0.1)
23
- capybara (3.39.0)
24
- addressable
25
- matrix
26
- mini_mime (>= 0.1.3)
27
- nokogiri (~> 1.8)
28
- rack (>= 1.6.0)
29
- rack-test (>= 0.6.3)
30
- regexp_parser (>= 1.5, < 3.0)
31
- xpath (~> 3.2)
32
- coderay (1.1.3)
33
- concurrent-ruby (1.1.10)
34
- debug_inspector (1.1.0)
35
- diff-lcs (1.5.0)
36
- dotenv (2.7.6)
37
- dry-cli (0.7.0)
38
- dry-configurable (0.11.6)
39
- concurrent-ruby (~> 1.0)
40
- dry-core (~> 0.4, >= 0.4.7)
41
- dry-equalizer (~> 0.2)
42
- dry-container (0.7.2)
43
- concurrent-ruby (~> 1.0)
44
- dry-configurable (~> 0.1, >= 0.1.3)
45
- dry-core (0.4.9)
46
- concurrent-ruby (~> 1.0)
47
- dry-equalizer (0.3.0)
48
- dry-initializer (1.4.1)
49
- dry-logic (0.4.2)
50
- dry-container (~> 0.2, >= 0.2.6)
51
- dry-core (~> 0.2)
52
- dry-equalizer (~> 0.2)
53
- dry-struct (0.3.1)
54
- dry-configurable (~> 0.1)
55
- dry-core (~> 0.3)
56
- dry-equalizer (~> 0.2)
57
- dry-types (~> 0.9, >= 0.9.0)
58
- ice_nine (~> 0.11)
59
- dry-types (0.11.1)
60
- concurrent-ruby (~> 1.0)
61
- dry-configurable (~> 0.1)
62
- dry-container (~> 0.3)
63
- dry-core (~> 0.2, >= 0.2.1)
64
- dry-equalizer (~> 0.2)
65
- dry-logic (~> 0.4, >= 0.4.0)
66
- inflecto (~> 0.0.0, >= 0.0.2)
67
- dry-validation (0.11.0)
68
- concurrent-ruby (~> 1.0)
69
- dry-configurable (~> 0.1, >= 0.1.3)
70
- dry-core (~> 0.2, >= 0.2.1)
71
- dry-equalizer (~> 0.2)
72
- dry-logic (~> 0.4, >= 0.4.0)
73
- dry-types (~> 0.11.0)
74
- erubi (1.10.0)
75
- faraday (1.10.3)
76
- faraday-em_http (~> 1.0)
77
- faraday-em_synchrony (~> 1.0)
78
- faraday-excon (~> 1.1)
79
- faraday-httpclient (~> 1.0)
80
- faraday-multipart (~> 1.0)
81
- faraday-net_http (~> 1.0)
82
- faraday-net_http_persistent (~> 1.0)
83
- faraday-patron (~> 1.0)
84
- faraday-rack (~> 1.0)
85
- faraday-retry (~> 1.0)
86
- ruby2_keywords (>= 0.0.4)
87
- faraday-em_http (1.0.0)
88
- faraday-em_synchrony (1.0.0)
89
- faraday-excon (1.1.0)
90
- faraday-httpclient (1.0.1)
91
- faraday-multipart (1.0.4)
92
- multipart-post (~> 2)
93
- faraday-net_http (1.0.1)
94
- faraday-net_http_persistent (1.2.0)
95
- faraday-patron (1.0.0)
96
- faraday-rack (1.0.0)
97
- faraday-retry (1.0.3)
98
- faraday_middleware (1.2.0)
99
- faraday (~> 1.0)
100
- gem-release (2.2.2)
101
- hanami (1.3.5)
102
- bundler (>= 1.6, < 3)
103
- concurrent-ruby (~> 1.0)
104
- dry-cli (~> 0.5)
105
- hanami-assets (~> 1.3)
106
- hanami-controller (~> 1.3, >= 1.3.3)
107
- hanami-helpers (~> 1.3)
108
- hanami-mailer (~> 1.3)
109
- hanami-router (~> 1.3)
110
- hanami-utils (~> 1.3)
111
- hanami-validations (>= 1.3, < 3)
112
- hanami-view (~> 1.3)
113
- hanami-assets (1.3.5)
114
- hanami-helpers (~> 1.3)
115
- hanami-utils (~> 1.3)
116
- tilt (~> 2.0, >= 2.0.2)
117
- hanami-controller (1.3.3)
118
- hanami-utils (~> 1.3)
119
- rack (~> 2.0)
120
- hanami-helpers (1.3.3)
121
- hanami-utils (~> 1.3)
122
- hanami-mailer (1.3.3)
123
- hanami-utils (~> 1.3)
124
- mail (~> 2.6)
125
- tilt (~> 2.0, >= 2.0.1)
126
- hanami-model (1.3.3)
127
- bigdecimal (~> 1.4)
128
- concurrent-ruby (~> 1.0)
129
- dry-logic (~> 0.4.2, < 0.5)
130
- dry-types (~> 0.11.0)
131
- hanami-utils (~> 1.3)
132
- rom (~> 3.3, >= 3.3.3)
133
- rom-repository (~> 1.4)
134
- rom-sql (~> 1.3, >= 1.3.5)
135
- hanami-router (1.3.2)
136
- hanami-utils (~> 1.3)
137
- http_router (= 0.11.2)
138
- rack (~> 2.0)
139
- hanami-utils (1.3.8)
140
- concurrent-ruby (~> 1.0)
141
- transproc (~> 1.0)
142
- hanami-validations (1.3.8)
143
- dry-configurable (<= 0.12)
144
- dry-logic (~> 0.4.2, < 0.5)
145
- dry-validation (~> 0.11, < 0.12)
146
- hanami-utils (~> 1.3)
147
- hanami-view (1.3.3)
148
- hanami-utils (~> 1.3)
149
- tilt (~> 2.0, >= 2.0.1)
150
- hanami-webconsole (0.1.0)
151
- better_errors (~> 2.4)
152
- binding_of_caller (~> 0.8)
153
- http_router (0.11.2)
154
- rack (>= 1.0.0)
155
- url_mount (~> 0.2.1)
156
- ice_nine (0.11.2)
157
- inflecto (0.0.2)
158
- mail (2.7.1)
159
- mini_mime (>= 0.1.1)
160
- matrix (0.4.2)
161
- method_source (1.0.0)
162
- mini_mime (1.1.2)
163
- multipart-post (2.3.0)
164
- nio4r (2.5.9)
165
- nokogiri (1.14.3-arm64-darwin)
166
- racc (~> 1.4)
167
- nokogiri (1.14.3-x86_64-linux)
168
- racc (~> 1.4)
169
- parallel (1.20.1)
170
- parser (3.1.2.0)
171
- ast (~> 2.4.1)
172
- pry (0.14.1)
173
- coderay (~> 1.1)
174
- method_source (~> 1.0)
175
- public_suffix (5.0.1)
176
- puma (6.3.1)
177
- nio4r (~> 2.0)
178
- racc (1.6.2)
179
- rack (2.2.7)
180
- rack-test (2.1.0)
181
- rack (>= 1.3)
182
- rainbow (3.1.1)
183
- rake (13.0.6)
184
- regexp_parser (2.8.0)
185
- rexml (3.2.5)
186
- rom (3.3.3)
187
- concurrent-ruby (~> 1.0)
188
- dry-core (~> 0.3)
189
- dry-equalizer (~> 0.2)
190
- dry-initializer (~> 1.3)
191
- dry-types (~> 0.9, >= 0.9.4)
192
- rom-mapper (~> 0.5, >= 0.5.1)
193
- rom-mapper (0.5.1)
194
- dry-core (~> 0.2, >= 0.2.3)
195
- dry-equalizer (~> 0.2)
196
- transproc (~> 1.0)
197
- rom-repository (1.4.0)
198
- dry-core (~> 0.3, >= 0.3.1)
199
- dry-struct (~> 0.3)
200
- rom (~> 3.3)
201
- rom-mapper (~> 0.5)
202
- rom-sql (1.3.5)
203
- dry-core (~> 0.3)
204
- dry-equalizer (~> 0.2)
205
- dry-types (~> 0.11.0)
206
- rom (~> 3.2, >= 3.2.2)
207
- sequel (~> 4.43)
208
- rspec (3.11.0)
209
- rspec-core (~> 3.11.0)
210
- rspec-expectations (~> 3.11.0)
211
- rspec-mocks (~> 3.11.0)
212
- rspec-core (3.11.0)
213
- rspec-support (~> 3.11.0)
214
- rspec-expectations (3.11.0)
215
- diff-lcs (>= 1.2.0, < 2.0)
216
- rspec-support (~> 3.11.0)
217
- rspec-mocks (3.11.1)
218
- diff-lcs (>= 1.2.0, < 2.0)
219
- rspec-support (~> 3.11.0)
220
- rspec-support (3.11.0)
221
- rubocop (1.12.1)
222
- parallel (~> 1.10)
223
- parser (>= 3.0.0.0)
224
- rainbow (>= 2.2.2, < 4.0)
225
- regexp_parser (>= 1.8, < 3.0)
226
- rexml
227
- rubocop-ast (>= 1.2.0, < 2.0)
228
- ruby-progressbar (~> 1.7)
229
- unicode-display_width (>= 1.4.0, < 3.0)
230
- rubocop-ast (1.4.1)
231
- parser (>= 2.7.1.5)
232
- ruby-progressbar (1.11.0)
233
- ruby2_keywords (0.0.5)
234
- semantic (1.6.1)
235
- sequel (4.49.0)
236
- shotgun (0.9.2)
237
- rack (>= 1.0)
238
- slim (4.1.0)
239
- temple (>= 0.7.6, < 0.9)
240
- tilt (>= 2.0.6, < 2.1)
241
- sqlite3 (1.4.2)
242
- temple (0.8.2)
243
- tilt (2.0.10)
244
- transproc (1.1.1)
245
- unicode-display_width (2.1.0)
246
- url_mount (0.2.1)
247
- rack
248
- xpath (3.2.0)
249
- nokogiri (~> 1.8)
250
-
251
- PLATFORMS
252
- arm64-darwin-21
253
- x86_64-linux
254
-
255
- DEPENDENCIES
256
- bundler
257
- capybara
258
- dotenv (~> 2.4)
259
- flagsmith!
260
- gem-release
261
- hanami (~> 1.3)
262
- hanami-model (~> 1.3)
263
- hanami-webconsole
264
- pry
265
- puma (~> 6.3)
266
- rake
267
- rspec
268
- rubocop
269
- shotgun
270
- slim
271
- sqlite3
272
-
273
- BUNDLED WITH
274
- 2.3.14
data/example/README.md DELETED
@@ -1,29 +0,0 @@
1
- # Flagsmith Basic Ruby Example
2
-
3
- This directory contains a basic Flask application which utilises Flagsmith. To run the example application, you'll
4
- need to go through the following steps:
5
-
6
- 1. Create an account, organisation and project on [Flagsmith](https://flagsmith.com)
7
- 2. Create a feature in the project called "secret_button"
8
- 3. Give the feature a value using the json editor as follows:
9
-
10
- ```json
11
- {"colour": "#ababab"}
12
- ```
13
-
14
- 4. Create a .env.local file from the template located in this directory with the environment key of one of the environments
15
- in flagsmith (This can be found on the 'settings' page accessed from the menu on the left under the chosen environment.)
16
- 5. From a terminal window, export those environment variables (either manually or by using `export $(cat .env)`)
17
- 6. Install dependencies:
18
- ```bash
19
- bundle install
20
- ```
21
- 7. Run the application:
22
- ```
23
- bundle exec hanami server
24
- ```
25
- 8. Browse to http://localhost:2300
26
-
27
- Now you can play around with the 'secret_button' feature in flagsmith, turn it on to show it and edit the colour in the
28
- json value to edit the colour of the button. You can also identify as a given user and then update the settings for the
29
- secret button feature for that user in the flagsmith interface to see the affect that has too.
data/example/Rakefile DELETED
@@ -1,9 +0,0 @@
1
- require 'rake'
2
- require 'hanami/rake_tasks'
3
-
4
- begin
5
- require 'rspec/core/rake_task'
6
- RSpec::Core::RakeTask.new(:spec)
7
- task default: :spec
8
- rescue LoadError
9
- end
@@ -1,162 +0,0 @@
1
- require 'hanami/helpers'
2
- require 'hanami/assets'
3
-
4
- require_relative '../../../lib/flagsmith'
5
-
6
- module Web
7
- class Application < Hanami::Application
8
- configure do
9
- root __dir__
10
-
11
- load_paths << %w[
12
- controllers
13
- views
14
- ]
15
-
16
- routes 'config/routes'
17
-
18
- layout :application # It will load Web::Views::ApplicationLayout
19
-
20
- templates 'templates'
21
-
22
- ##
23
- # ASSETS
24
- #
25
- assets do
26
- # In order to skip JavaScript compression comment the following line
27
- javascript_compressor :builtin
28
-
29
- # In order to skip stylesheet compression comment the following line
30
- stylesheet_compressor :builtin
31
- end
32
-
33
- ##
34
- # SECURITY
35
- #
36
-
37
- # X-Frame-Options is a HTTP header supported by modern browsers.
38
- # It determines if a web page can or cannot be included via <frame> and
39
- # <iframe> tags by untrusted domains.
40
- #
41
- # Web applications can send this header to prevent Clickjacking attacks.
42
- #
43
- # Read more at:
44
- #
45
- # * https://developer.mozilla.org/en-US/docs/Web/HTTP/X-Frame-Options
46
- # * https://www.owasp.org/index.php/Clickjacking
47
- #
48
- security.x_frame_options 'DENY'
49
-
50
- # X-Content-Type-Options prevents browsers from interpreting files as
51
- # something else than declared by the content type in the HTTP headers.
52
- #
53
- # Read more at:
54
- #
55
- # * https://www.owasp.org/index.php/OWASP_Secure_Headers_Project#X-Content-Type-Options
56
- # * https://msdn.microsoft.com/en-us/library/gg622941%28v=vs.85%29.aspx
57
- # * https://blogs.msdn.microsoft.com/ie/2008/09/02/ie8-security-part-vi-beta-2-update
58
- #
59
- security.x_content_type_options 'nosniff'
60
-
61
- # X-XSS-Protection is a HTTP header to determine the behavior of the
62
- # browser in case an XSS attack is detected.
63
- #
64
- # Read more at:
65
- #
66
- # * https://www.owasp.org/index.php/Cross-site_Scripting_(XSS)
67
- # * https://www.owasp.org/index.php/OWASP_Secure_Headers_Project#X-XSS-Protection
68
- #
69
- security.x_xss_protection '1; mode=block'
70
-
71
- # Content-Security-Policy (CSP) is a HTTP header supported by modern
72
- # browsers. It determines trusted sources of execution for dynamic
73
- # contents (JavaScript) or other web related assets: stylesheets, images,
74
- # fonts, plugins, etc.
75
- #
76
- # Web applications can send this header to mitigate Cross Site Scripting
77
- # (XSS) attacks.
78
- #
79
- # The default value allows images, scripts, AJAX, fonts and CSS from the
80
- # same origin, and does not allow any other resources to load (eg object,
81
- # frame, media, etc).
82
- #
83
- # Inline JavaScript is NOT allowed. To enable it, please use:
84
- # "script-src 'unsafe-inline'".
85
- #
86
- # Content Security Policy introduction:
87
- #
88
- # * http://www.html5rocks.com/en/tutorials/security/content-security-policy/
89
- # * https://www.owasp.org/index.php/Content_Security_Policy
90
- # * https://www.owasp.org/index.php/Cross-site_Scripting_%28XSS%29
91
- #
92
- # Inline and eval JavaScript risks:
93
- #
94
- # * http://www.html5rocks.com/en/tutorials/security/content-security-policy/#inline-code-considered-harmful
95
- # * http://www.html5rocks.com/en/tutorials/security/content-security-policy/#eval-too
96
- #
97
- # Content Security Policy usage:
98
- #
99
- # * http://content-security-policy.com/
100
- # * https://developer.mozilla.org/en-US/docs/Web/Security/CSP/Using_Content_Security_Policy
101
- #
102
- # Content Security Policy references:
103
- #
104
- # * https://developer.mozilla.org/en-US/docs/Web/Security/CSP/CSP_policy_directives
105
- #
106
- security.content_security_policy %(
107
- form-action 'self';
108
- frame-ancestors 'self';
109
- base-uri 'self';
110
- default-src 'none';
111
- script-src 'self';
112
- connect-src 'self';
113
- img-src 'self' https: data:;
114
- style-src 'self' 'unsafe-inline' https:;
115
- font-src 'self';
116
- object-src 'none';
117
- plugin-types application/pdf;
118
- child-src 'self';
119
- frame-src 'self';
120
- media-src 'self'
121
- )
122
-
123
- ##
124
- # FRAMEWORKS
125
- #
126
-
127
- # Configure the code that will yield each time Web::Action is included
128
- # This is useful for sharing common functionality
129
- #
130
- # See: http://www.rubydoc.info/gems/hanami-controller#Configuration
131
- controller.prepare do
132
- # include MyAuthentication # included in all the actions
133
- # before :authenticate! # run an authentication before callback
134
- end
135
-
136
- # Configure the code that will yield each time Web::View is included
137
- # This is useful for sharing common functionality
138
- #
139
- # See: http://www.rubydoc.info/gems/hanami-view#Configuration
140
- view.prepare do
141
- include Hanami::Helpers
142
- include Web::Assets::Helpers
143
- end
144
- end
145
-
146
- ##
147
- # DEVELOPMENT
148
- #
149
- configure :development do
150
- # Don't handle exceptions, render the stack trace
151
- handle_exceptions false
152
- end
153
-
154
- ##
155
- # TEST
156
- #
157
- configure :test do
158
- # Don't handle exceptions, render the stack trace
159
- handle_exceptions false
160
- end
161
- end
162
- end
@@ -1 +0,0 @@
1
- get '/', to: 'home#index'
File without changes
@@ -1,32 +0,0 @@
1
- module Web
2
- module Controllers
3
- module Home
4
- class Index
5
- include Web::Action
6
-
7
- expose :identifier, :show_button, :button_color
8
-
9
- def call(params)
10
- @identifier = params.get(:flagsmith, :identifier)
11
-
12
- if @identifier.nil? || @identifier.blank?
13
- # Get the default flags for the current environment
14
- flags = $flagsmith.get_environment_flags
15
- @show_button = flags.is_feature_enabled("secret_button")
16
- @button_data = JSON.parse(flags.get_feature_value("secret_button"))["colour"]
17
- else
18
- trait_key = params.get(:flagsmith, :trait_key)
19
- trait_value = params.get(:flagsmith, :trait_value)
20
- traits = trait_key.nil? ? nil : { trait_key: trait_value }
21
-
22
- # Get the flags for an identity, including the provided trait which will be
23
- # persisted to the API for future requests.
24
- identity_flags = $flagsmith.get_identity_flags(identifier, traits)
25
- @show_button = identity_flags.is_feature_enabled('secret_button')
26
- @button_color = JSON.parse(identity_flags.get_feature_value('secret_button'))['colour']
27
- end
28
- end
29
- end
30
- end
31
- end
32
- end
@@ -1,7 +0,0 @@
1
- doctype html
2
- html
3
- head
4
- title Flagsmith Example
5
- body
6
- main[style="max-width: 768px; margin: auto; text-align: center"]
7
- = yield
@@ -1,10 +0,0 @@
1
- p
2
- ' Hello,
3
- = (identifier.nil? || identifier.blank?) ? 'World' : identifier
4
-
5
- = if show_button
6
- button[style="background-color: #{button_color}"] A secret button
7
-
8
- p
9
-
10
- = form
@@ -1,7 +0,0 @@
1
- module Web
2
- module Views
3
- class ApplicationLayout
4
- include Web::Layout
5
- end
6
- end
7
- end
@@ -1,29 +0,0 @@
1
- module Web
2
- module Views
3
- module Home
4
- class Index
5
- include Web::View
6
-
7
- def form
8
- form_for :flagsmith, '/', method: :get do
9
- h3 'Identify as a User'
10
- div style: 'margin-bottom: 1em;' do
11
- label :identifier
12
- text_field :identifier
13
- end
14
- p '... with an optional user trait'
15
- div style: 'margin-bottom: 1em;' do
16
- label :trait_key
17
- text_field :trait_key
18
- end
19
- div style: 'margin-bottom: 1em;' do
20
- label :trait_value
21
- text_field :trait_value
22
- end
23
- div { submit 'Identify!' }
24
- end
25
- end
26
- end
27
- end
28
- end
29
- end
@@ -1,2 +0,0 @@
1
- require_relative './environment'
2
- Hanami.boot
@@ -1,17 +0,0 @@
1
- require 'bundler/setup'
2
- require 'hanami/setup'
3
- require 'hanami/model'
4
- require_relative '../apps/web/application'
5
-
6
- Hanami.configure do
7
- mount Web::Application, at: '/'
8
-
9
- model do
10
- adapter :sql, ENV.fetch('DATABASE_URL')
11
- end
12
-
13
- environment :development do
14
- # See: https://guides.hanamirb.org/projects/logging
15
- logger level: :debug
16
- end
17
- end
File without changes
@@ -1,7 +0,0 @@
1
- $flagsmith = Flagsmith::Client.new(
2
- enable_local_evaluation: true,
3
- environment_refresh_interval_seconds: 60,
4
- default_flag_handler: lambda { |feature_name|
5
- Flagsmith::Flags::DefaultFlag.new(enabled: false, value: {}.to_json)
6
- }
7
- )
@@ -1,15 +0,0 @@
1
- require_relative './environment'
2
- workers 1
3
-
4
- threads_count = 1
5
- threads threads_count, threads_count
6
-
7
- preload_app!
8
-
9
- rackup DefaultRackup
10
- port 2300
11
- environment 'development'
12
-
13
- on_worker_boot do
14
- Hanami.boot
15
- end
data/example/config.ru DELETED
@@ -1,3 +0,0 @@
1
- require_relative 'config/environment'
2
-
3
- run Hanami.app
File without changes
File without changes
File without changes
@@ -1,12 +0,0 @@
1
- # Require this file for feature tests
2
- require_relative './spec_helper'
3
-
4
- require 'capybara'
5
- require 'capybara/rspec'
6
-
7
- RSpec.configure do |config|
8
- config.include RSpec::FeatureExampleGroup
9
-
10
- config.include Capybara::DSL, feature: true
11
- config.include Capybara::RSpecMatchers, feature: true
12
- end
@@ -1,103 +0,0 @@
1
- # Require this file for unit tests
2
- ENV['HANAMI_ENV'] ||= 'test'
3
-
4
- require_relative '../config/environment'
5
- Hanami.boot
6
- Hanami::Utils.require!("#{__dir__}/support")
7
-
8
- # This file was generated by the `rspec --init` command. Conventionally, all
9
- # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
10
- # The generated `.rspec` file contains `--require spec_helper` which will cause
11
- # this file to always be loaded, without a need to explicitly require it in any
12
- # files.
13
- #
14
- # Given that it is always loaded, you are encouraged to keep this file as
15
- # light-weight as possible. Requiring heavyweight dependencies from this file
16
- # will add to the boot time of your test suite on EVERY test run, even for an
17
- # individual file that may not need all of that loaded. Instead, consider making
18
- # a separate helper file that requires the additional dependencies and performs
19
- # the additional setup, and require it from the spec files that actually need
20
- # it.
21
- #
22
- # The `.rspec` file also contains a few flags that are not defaults but that
23
- # users commonly want.
24
- #
25
- # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
26
- RSpec.configure do |config|
27
- # rspec-expectations config goes here. You can use an alternate
28
- # assertion/expectation library such as wrong or the stdlib/minitest
29
- # assertions if you prefer.
30
- config.expect_with :rspec do |expectations|
31
- # This option will default to `true` in RSpec 4. It makes the `description`
32
- # and `failure_message` of custom matchers include text for helper methods
33
- # defined using `chain`, e.g.:
34
- # be_bigger_than(2).and_smaller_than(4).description
35
- # # => "be bigger than 2 and smaller than 4"
36
- # ...rather than:
37
- # # => "be bigger than 2"
38
- expectations.include_chain_clauses_in_custom_matcher_descriptions = true
39
- end
40
-
41
- # rspec-mocks config goes here. You can use an alternate test double
42
- # library (such as bogus or mocha) by changing the `mock_with` option here.
43
- config.mock_with :rspec do |mocks|
44
- # Prevents you from mocking or stubbing a method that does not exist on
45
- # a real object. This is generally recommended, and will default to
46
- # `true` in RSpec 4.
47
- mocks.verify_partial_doubles = true
48
- end
49
-
50
- # The settings below are suggested to provide a good initial experience
51
- # with RSpec, but feel free to customize to your heart's content.
52
- =begin
53
- # These two settings work together to allow you to limit a spec run
54
- # to individual examples or groups you care about by tagging them with
55
- # `:focus` metadata. When nothing is tagged with `:focus`, all examples
56
- # get run.
57
- config.filter_run :focus
58
- config.run_all_when_everything_filtered = true
59
-
60
- # Allows RSpec to persist some state between runs in order to support
61
- # the `--only-failures` and `--next-failure` CLI options. We recommend
62
- # you configure your source control system to ignore this file.
63
- config.example_status_persistence_file_path = "spec/examples.txt"
64
-
65
- # Limits the available syntax to the non-monkey patched syntax that is
66
- # recommended. For more details, see:
67
- # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
68
- # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
69
- # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
70
- config.disable_monkey_patching!
71
-
72
- # This setting enables warnings. It's recommended, but in many cases may
73
- # be too noisy due to issues in dependencies.
74
- config.warnings = false
75
-
76
- # Many RSpec users commonly either run the entire suite or an individual
77
- # file, and it's useful to allow more verbose output when running an
78
- # individual spec file.
79
- if config.files_to_run.one?
80
- # Use the documentation formatter for detailed output,
81
- # unless a formatter has already been configured
82
- # (e.g. via a command-line flag).
83
- config.default_formatter = 'doc'
84
- end
85
-
86
- # Print the 10 slowest examples and example groups at the
87
- # end of the spec run, to help surface which specs are running
88
- # particularly slow.
89
- config.profile_examples = 10
90
-
91
- # Run specs in random order to surface order dependencies. If you find an
92
- # order dependency and want to debug it, you can fix the order by providing
93
- # the seed, which is printed after each run.
94
- # --seed 1234
95
- config.order = :random
96
-
97
- # Seed global randomization in this process using the `--seed` CLI option.
98
- # Setting this allows you to use `--seed` to deterministically reproduce
99
- # test failures related to randomization by passing the same `--seed` value
100
- # as the one that triggered the failure.
101
- Kernel.srand config.seed
102
- =end
103
- end
File without changes
@@ -1,8 +0,0 @@
1
- module RSpec
2
- module FeatureExampleGroup
3
- def self.included(group)
4
- group.metadata[:type] = :feature
5
- Capybara.app = Hanami.app
6
- end
7
- end
8
- end
File without changes
@@ -1,9 +0,0 @@
1
- RSpec.describe Web::Controllers::Home::Index, type: :action do
2
- let(:action) { described_class.new }
3
- let(:params) { Hash[] }
4
-
5
- it 'is successful' do
6
- response = action.call(params)
7
- expect(response[0]).to eq 200
8
- end
9
- end
File without changes
@@ -1,10 +0,0 @@
1
- require "spec_helper"
2
-
3
- RSpec.describe Web::Views::ApplicationLayout, type: :view do
4
- let(:layout) { Web::Views::ApplicationLayout.new({ format: :html }, "contents") }
5
- let(:rendered) { layout.render }
6
-
7
- it 'contains application name' do
8
- expect(rendered).to include('Web')
9
- end
10
- end
@@ -1,10 +0,0 @@
1
- RSpec.describe Web::Views::Home::Index, type: :view do
2
- let(:exposures) { Hash[format: :html] }
3
- let(:template) { Hanami::View::Template.new('apps/web/templates/home/index.html.slim') }
4
- let(:view) { described_class.new(template, exposures) }
5
- let(:rendered) { view.render }
6
-
7
- it 'exposes #format' do
8
- expect(view.format).to eq exposures.fetch(:format)
9
- end
10
- end