ecfr 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 (115) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +11 -0
  3. data/.gitignore +11 -0
  4. data/.rspec +3 -0
  5. data/.rspec_parallel +4 -0
  6. data/.rubocop.yml +28 -0
  7. data/.yardopts +3 -0
  8. data/CHANGELOG.md +6 -0
  9. data/Dockerfile +6 -0
  10. data/Gemfile +6 -0
  11. data/Gemfile.lock +138 -0
  12. data/LICENSE.txt +21 -0
  13. data/README.md +133 -0
  14. data/Rakefile +12 -0
  15. data/bin/console +15 -0
  16. data/bin/setup +8 -0
  17. data/ecfr.gemspec +74 -0
  18. data/lib/ecfr/admin_service/agency/hierarchy.rb +27 -0
  19. data/lib/ecfr/admin_service/agency.rb +34 -0
  20. data/lib/ecfr/admin_service/api_documentation.rb +7 -0
  21. data/lib/ecfr/admin_service/base.rb +26 -0
  22. data/lib/ecfr/admin_service/build.rb +38 -0
  23. data/lib/ecfr/admin_service/ecfr_correction/cfr_reference.rb +17 -0
  24. data/lib/ecfr/admin_service/ecfr_correction.rb +78 -0
  25. data/lib/ecfr/admin_service/editorial_note/hierarchy.rb +19 -0
  26. data/lib/ecfr/admin_service/editorial_note.rb +40 -0
  27. data/lib/ecfr/admin_service/ibr_cfr_range/address.rb +17 -0
  28. data/lib/ecfr/admin_service/ibr_cfr_range/organization.rb +28 -0
  29. data/lib/ecfr/admin_service/ibr_cfr_range.rb +67 -0
  30. data/lib/ecfr/admin_service/issue/change.rb +19 -0
  31. data/lib/ecfr/admin_service/issue.rb +86 -0
  32. data/lib/ecfr/admin_service/site_notification.rb +34 -0
  33. data/lib/ecfr/admin_service/status.rb +7 -0
  34. data/lib/ecfr/attribute_caster.rb +72 -0
  35. data/lib/ecfr/attribute_method_definition.rb +92 -0
  36. data/lib/ecfr/base.rb +71 -0
  37. data/lib/ecfr/client.rb +318 -0
  38. data/lib/ecfr/common/hierarchy.rb +35 -0
  39. data/lib/ecfr/configuration.rb +58 -0
  40. data/lib/ecfr/constants.rb +21 -0
  41. data/lib/ecfr/default_documentation_setup.rb +39 -0
  42. data/lib/ecfr/default_status_setup.rb +46 -0
  43. data/lib/ecfr/diff_service/base.rb +17 -0
  44. data/lib/ecfr/diff_service/status.rb +34 -0
  45. data/lib/ecfr/extensible.rb +45 -0
  46. data/lib/ecfr/facet_attribute_method_definition.rb +47 -0
  47. data/lib/ecfr/faraday/user_agent/middleware.rb +14 -0
  48. data/lib/ecfr/ofr_profile_service/base.rb +20 -0
  49. data/lib/ecfr/ofr_profile_service/status.rb +7 -0
  50. data/lib/ecfr/parallel_client.rb +33 -0
  51. data/lib/ecfr/prince_xml_service/base.rb +17 -0
  52. data/lib/ecfr/prince_xml_service/pdf.rb +31 -0
  53. data/lib/ecfr/renderer_service/base.rb +31 -0
  54. data/lib/ecfr/renderer_service/content.rb +34 -0
  55. data/lib/ecfr/renderer_service/diff.rb +31 -0
  56. data/lib/ecfr/renderer_service/origin.rb +56 -0
  57. data/lib/ecfr/renderer_service/status.rb +7 -0
  58. data/lib/ecfr/request_representation.rb +12 -0
  59. data/lib/ecfr/search_service/api_documentation.rb +7 -0
  60. data/lib/ecfr/search_service/base.rb +23 -0
  61. data/lib/ecfr/search_service/content_version/count.rb +33 -0
  62. data/lib/ecfr/search_service/content_version/hierarchical_count.rb +17 -0
  63. data/lib/ecfr/search_service/content_version/hierarchical_count_node.rb +30 -0
  64. data/lib/ecfr/search_service/content_version/hierarchichal_result.rb +42 -0
  65. data/lib/ecfr/search_service/content_version/result.rb +110 -0
  66. data/lib/ecfr/search_service/content_version/suggestion.rb +76 -0
  67. data/lib/ecfr/search_service/content_version/summary.rb +27 -0
  68. data/lib/ecfr/search_service/content_version.rb +85 -0
  69. data/lib/ecfr/search_service/date_facet.rb +19 -0
  70. data/lib/ecfr/search_service/facet_base.rb +55 -0
  71. data/lib/ecfr/search_service/status.rb +7 -0
  72. data/lib/ecfr/search_service/title_facet.rb +18 -0
  73. data/lib/ecfr/subscriptions_service/base.rb +19 -0
  74. data/lib/ecfr/subscriptions_service/status.rb +7 -0
  75. data/lib/ecfr/subscriptions_service/subscription.rb +97 -0
  76. data/lib/ecfr/testing/extensions/admin_service/ecfr_correction_extensions.rb +13 -0
  77. data/lib/ecfr/testing/extensions/admin_service/issue_extensions.rb +13 -0
  78. data/lib/ecfr/testing/extensions/renderer_service/origin_extensions.rb +13 -0
  79. data/lib/ecfr/testing/extensions/search_service/content_version_result_extensions.rb +16 -0
  80. data/lib/ecfr/testing/extensions/search_service/date_facet_extensions.rb +13 -0
  81. data/lib/ecfr/testing/extensions/versioner_service/ancestors_extensions.rb +20 -0
  82. data/lib/ecfr/testing/extensions/versioner_service/title_extenstions.rb +16 -0
  83. data/lib/ecfr/testing/factories/admin_service/cfr_reference_factory.rb +14 -0
  84. data/lib/ecfr/testing/factories/admin_service/ecfr_correction_factory.rb +31 -0
  85. data/lib/ecfr/testing/factories/admin_service/issue_change_factory.rb +12 -0
  86. data/lib/ecfr/testing/factories/admin_service/issue_factory.rb +21 -0
  87. data/lib/ecfr/testing/factories/common/hierarchy_factory.rb +36 -0
  88. data/lib/ecfr/testing/factories/renderer_service/origin_factory.rb +32 -0
  89. data/lib/ecfr/testing/factories/search_service/content_version_count_factory.rb +20 -0
  90. data/lib/ecfr/testing/factories/search_service/content_version_result_factory.rb +76 -0
  91. data/lib/ecfr/testing/factories/search_service/date_facet_factory.rb +12 -0
  92. data/lib/ecfr/testing/factories/versioner_service/ancestors_factory.rb +26 -0
  93. data/lib/ecfr/testing/factories/versioner_service/metadata_node_info_factory.rb +15 -0
  94. data/lib/ecfr/testing/factories/versioner_service/node_summary_factory.rb +16 -0
  95. data/lib/ecfr/testing/factories/versioner_service/structure_factory.rb +57 -0
  96. data/lib/ecfr/testing/factories/versioner_service/title_factory.rb +36 -0
  97. data/lib/ecfr/testing/factory_bot_helpers/content_version.rb +38 -0
  98. data/lib/ecfr/testing/factory_bot_helpers/ecfr_gem_initialize_helpers.rb +51 -0
  99. data/lib/ecfr/testing/helpers/response_helper.rb +5 -0
  100. data/lib/ecfr/testing/strategies/ecfr_attribute_hash_strategy.rb +37 -0
  101. data/lib/ecfr/testing.rb +28 -0
  102. data/lib/ecfr/version.rb +5 -0
  103. data/lib/ecfr/versioner_service/ancestors/metadata_node_info.rb +22 -0
  104. data/lib/ecfr/versioner_service/ancestors/node_summary.rb +54 -0
  105. data/lib/ecfr/versioner_service/ancestors.rb +152 -0
  106. data/lib/ecfr/versioner_service/api_documentation.rb +7 -0
  107. data/lib/ecfr/versioner_service/base.rb +24 -0
  108. data/lib/ecfr/versioner_service/status.rb +7 -0
  109. data/lib/ecfr/versioner_service/structure.rb +120 -0
  110. data/lib/ecfr/versioner_service/title.rb +78 -0
  111. data/lib/ecfr/versioner_service/xml_content.rb +59 -0
  112. data/lib/ecfr.rb +90 -0
  113. data/lib/yard/attribute_handler.rb +87 -0
  114. data/lib/yard/metadata_handler.rb +87 -0
  115. metadata +389 -0
@@ -0,0 +1,85 @@
1
+ module Ecfr
2
+ module SearchService
3
+ class ContentVersion < Base
4
+ require_relative "./content_version/count"
5
+ require_relative "./content_version/hierarchichal_result"
6
+ require_relative "./content_version/result"
7
+ require_relative "./content_version/suggestion"
8
+ require_relative "./content_version/summary"
9
+
10
+ #
11
+ # Metadata about the number of matching items
12
+ #
13
+ # @param [<Hash>] args valid search arguments, see {Result.find}
14
+ #
15
+ # @return [<Count>] count metadata
16
+ #
17
+ def self.count(args)
18
+ lookup(Ecfr::SearchService::ContentVersion::Count).find(args)
19
+ end
20
+
21
+ #
22
+ # Search results in a hierarchical format with score data
23
+ #
24
+ # @param [<Hash>] args valid search arguments, see {Result.find}
25
+ #
26
+ # @return [<HierarchicalSearchCount>] hierarchical search results
27
+ #
28
+ def self.hierarchical_search(args)
29
+ lookup(
30
+ Ecfr::SearchService::ContentVersion::HierarchicalResult
31
+ ).find(args)
32
+ end
33
+
34
+ #
35
+ # Search results with excerpts and score data
36
+ #
37
+ # @param [<Hash>] args valid search arguments, see {Result.find}
38
+ #
39
+ # @return [<Result>] results of a search
40
+ #
41
+ def self.search(args)
42
+ lookup(Ecfr::SearchService::ContentVersion::Result).find(args)
43
+ end
44
+
45
+ #
46
+ # Suggestions based on the content of a search.
47
+ # Currently suggests direct link to a portion of the CFR when
48
+ # a CFR citation is detected as part of the `query`
49
+ #
50
+ # @param [<Hash>] args valid search arguments, see {Result.find}
51
+ #
52
+ # @return [<Suggestion>] search suggestions
53
+ #
54
+ def self.suggestions(args)
55
+ lookup(Ecfr::SearchService::ContentVersion::Suggestion).find(args)
56
+ end
57
+
58
+ #
59
+ # Summary of the search based on the arguments provided
60
+ # - summary only makes use of the :hierarchy and :query
61
+ # args currenly
62
+ #
63
+ # @param [<Hash>] args valid search arguments, see {Result.find}
64
+ #
65
+ # @return [<Summary>] A descriptive summary of the search
66
+ #
67
+ def self.summary(args)
68
+ lookup(Ecfr::SearchService::ContentVersion::Summary).find(args)
69
+ end
70
+
71
+ #
72
+ # Support inheritance by looking up class. See
73
+ # Ecfr::Extensible for details.
74
+ #
75
+ def self.lookup(klass)
76
+ if const_defined?("#{klass}::KLASS")
77
+ klass::KLASS
78
+ else
79
+ klass
80
+ end
81
+ end
82
+ private_class_method :lookup
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,19 @@
1
+ module Ecfr
2
+ module SearchService
3
+ class DateFacet < FacetBase
4
+ include FacetAttributeMethodDefinition
5
+
6
+ result_key :dates
7
+
8
+ attribute :count, as: :value
9
+ attribute :date, type: :date, as: :key
10
+
11
+ # @param [<Symbol, String>] type currently only supports :daily
12
+ # @return [<DateFacet>] counts by date
13
+ def self.search(type, options = {})
14
+ # no-op documentation only
15
+ super(type, options)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,55 @@
1
+ module Ecfr
2
+ module SearchService
3
+ class FacetBase < Base
4
+ COUNTS_PATH = "v1/counts"
5
+
6
+ #
7
+ # Retrive counts of changed CFR sections by date
8
+ #
9
+ # @param [<Hash>] args valid facet search parameters
10
+ # @option options [<Ecfr::SearchService::ContentVersion::Hierarchy>] :hierarchy levels of CFR hierarchy to limit the search to
11
+ # @option options [<String>] :last_modified_after ISO date
12
+ # @option options [<String>] :last_modified_on_or_after ISO date
13
+ # @option options [<String>] :last_modified_before ISO date
14
+ # @option options [<String>] :last_modified_on_or_before ISO date
15
+ # @option options [<String>] :query search terms
16
+ # @option options [<Boolean>] :reserved whether counts should be for Reserved content (default false)
17
+ # @option options [<Boolean>] :substantive whether counts should be for substantive content (default true)
18
+ #
19
+ # @return [<DateFacet>] counts by date
20
+ #
21
+ def self.search(type, args = {})
22
+ prepare_search_options(args)
23
+
24
+ perform(
25
+ :get,
26
+ counts_path(type),
27
+ params: args
28
+ )
29
+ end
30
+
31
+ def self.counts_path(type)
32
+ "#{COUNTS_PATH}/#{type}"
33
+ end
34
+ private_class_method :counts_path
35
+
36
+ VALID_SEARCH_OPTIONS = %i[
37
+ hierarchy last_modified_after last_modified_on_or_after
38
+ last_modified_before last_modified_on_or_before query reserved
39
+ substantive
40
+ ]
41
+
42
+ def self.prepare_search_options(args)
43
+ args.deep_symbolize_keys!
44
+ args.slice!(*VALID_SEARCH_OPTIONS)
45
+
46
+ if args[:hierarchy]
47
+ args[:hierarchy] = args[:hierarchy].slice(
48
+ *Ecfr::Constants::Hierarchy::HIERARCHY_LEVELS.map(&:to_sym)
49
+ )
50
+ end
51
+ end
52
+ private_class_method :prepare_search_options
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,7 @@
1
+ module Ecfr
2
+ module SearchService
3
+ class Status < Base
4
+ include DefaultStatusSetup
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,18 @@
1
+ module Ecfr
2
+ module SearchService
3
+ class TitleFacet < FacetBase
4
+ include FacetAttributeMethodDefinition
5
+
6
+ result_key :titles
7
+
8
+ attribute :count, as: :value
9
+ attribute :title, as: :key
10
+
11
+ # @return [<TitleFacet>] counts by title
12
+ def self.search(options = {})
13
+ type = "titles"
14
+ super(type, options)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,19 @@
1
+ module Ecfr
2
+ module SubscriptionsService
3
+ class Base < Ecfr::Base
4
+ require_relative "status"
5
+
6
+ require_relative "subscription"
7
+
8
+ SERVICE_PATH = "/api/subscriptions"
9
+
10
+ def self.base_url
11
+ Ecfr.config.subscriptions_service_url || Ecfr.config.base_url
12
+ end
13
+
14
+ def self.service_name
15
+ "Subscriptions Service"
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,7 @@
1
+ module Ecfr
2
+ module SubscriptionsService
3
+ class Status < Base
4
+ include DefaultStatusSetup
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,97 @@
1
+ module Ecfr
2
+ module SubscriptionsService
3
+ class Subscription < Base
4
+ result_key :subscriptions
5
+
6
+ attribute :title,
7
+ desc: "a description of the subscription"
8
+
9
+ attribute :delivery_count,
10
+ type: :integer,
11
+ desc: "the number of times the subscription has been delivered"
12
+ attribute :id,
13
+ type: :integer,
14
+ desc: "the subscription id"
15
+
16
+ attribute :created_at,
17
+ type: :date,
18
+ desc: "date the subscription was created"
19
+ attribute :last_delivered_at,
20
+ type: :date,
21
+ desc: "last date this subscription had matches and was delivered"
22
+
23
+ # TODO: upgrade to a class
24
+
25
+ # @return [Hash] with "query", and "hierarchy" keys
26
+ attribute :parameters,
27
+ desc: "the subscription search parameters"
28
+
29
+ SUBSCRIPTIONS_PATH = "v1/subscriptions"
30
+
31
+ #
32
+ # Retrive a list of subscriptions for a user
33
+ #
34
+ # @param [<Integer>] user_id id of user
35
+ #
36
+ # @return [[<Subscription>]] an array of subscriptions
37
+ #
38
+ def self.get_subscriptions(user_id)
39
+ perform(
40
+ :get,
41
+ "#{SUBSCRIPTIONS_PATH}/#{user_id}.json",
42
+ client_options: basic_auth_client_options
43
+ )
44
+ end
45
+
46
+ #
47
+ # Create a subscription for a user
48
+ #
49
+ # @param [<Integer>] user_id id of user
50
+ # @param [<Hash>] subscription_data arguments
51
+ # required to create a subscription
52
+ # @option subscription_data [String] requesting_ip (required)
53
+ # @option subscription_data [Hash] search (required)
54
+ # @option subscription_data [String] search[:query] subscription search terms
55
+ # @option subscription_data [Ecfr::Common::Hierarchy] search[:hierarchy] hierarchy to limit subscription search
56
+ #
57
+ # @return [<Subscription>] the created subscription
58
+ #
59
+ def self.create_subscription(user_id, subscription_data)
60
+ perform(
61
+ :post,
62
+ "#{SUBSCRIPTIONS_PATH}/#{user_id}",
63
+ params: subscription_data,
64
+ client_options: basic_auth_client_options,
65
+ perform_options: {attributes_key: "subscription"}
66
+ )
67
+ end
68
+
69
+ #
70
+ # Delete a subscription
71
+ #
72
+ # @param [<Integer>] user_id id of user
73
+ # @param [<String>] token unique delete token
74
+ # @param [<String>] subscription_id id of subscription
75
+ #
76
+ # @return [[<Subscription>, <Integer>]] the deleted subscription and response code
77
+ #
78
+ def self.delete_subscription(user_id, token, subscription_id)
79
+ unsubscribe_data = {
80
+ token: token,
81
+ user_id: user_id,
82
+ subscription_id: subscription_id
83
+ }
84
+
85
+ subscription = perform(
86
+ :delete,
87
+ "#{SUBSCRIPTIONS_PATH}/unsubscribe",
88
+ params: unsubscribe_data,
89
+ client_options: basic_auth_client_options,
90
+ perform_options: {attributes_key: "subscription"}
91
+ )
92
+
93
+ [subscription, subscription.response_status]
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,13 @@
1
+ class Ecfr::AdminService::EcfrCorrection
2
+ extend ResponseHelper
3
+
4
+ def self.response_for(corrections)
5
+ results = {
6
+ ecfr_corrections: corrections.is_a?(Array) ? corrections : [corrections]
7
+ }.to_json
8
+
9
+ build(
10
+ response: stubbed_response(results)
11
+ )
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ class Ecfr::AdminService::Issue
2
+ extend ResponseHelper
3
+
4
+ def self.response_for(issues)
5
+ results = {
6
+ issues: issues.is_a?(Array) ? issues : [issues]
7
+ }.to_json
8
+
9
+ build(
10
+ response: stubbed_response(results)
11
+ )
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ class Ecfr::RendererService::Origin
2
+ extend ResponseHelper
3
+
4
+ def self.response_for(origins)
5
+ results = {
6
+ origins: origins.is_a?(Array) ? origins : [origins]
7
+ }
8
+
9
+ build(
10
+ response: stubbed_response(results.to_json)
11
+ )
12
+ end
13
+ end
@@ -0,0 +1,16 @@
1
+ class Ecfr::SearchService::ContentVersion::Result
2
+ extend ResponseHelper
3
+
4
+ def self.response_for(content_versions)
5
+ content_versions = content_versions.is_a?(Array) ? content_versions : [content_versions]
6
+
7
+ results = {
8
+ results: content_versions,
9
+ meta: content_versions.first.fetch("meta", nil)
10
+ }.compact
11
+
12
+ build(
13
+ response: stubbed_response(results.to_json)
14
+ )
15
+ end
16
+ end
@@ -0,0 +1,13 @@
1
+ class Ecfr::SearchService::DateFacet
2
+ extend ResponseHelper
3
+
4
+ def self.response_for(date_facets)
5
+ results = {
6
+ dates: date_facets
7
+ }.to_json
8
+
9
+ build(
10
+ response: stubbed_response(results)
11
+ )
12
+ end
13
+ end
@@ -0,0 +1,20 @@
1
+ class Ecfr::VersionerService::Ancestors
2
+ extend ResponseHelper
3
+
4
+ def self.response_for(ancestors)
5
+ # ancestors can be a hash of attributes from the :ancestors factory,
6
+ # or one+ NodeSummary attribute hashes from the :node_summary
7
+ # factory
8
+ results = if ancestors.is_a?(Hash) && ancestors.key?("ancestors")
9
+ ancestors
10
+ else
11
+ {
12
+ ancestors: ancestors.is_a?(Array) ? ancestors : [ancestors]
13
+ }
14
+ end
15
+
16
+ build(
17
+ response: stubbed_response(results.to_json)
18
+ )
19
+ end
20
+ end
@@ -0,0 +1,16 @@
1
+ class Ecfr::VersionerService::Title
2
+ extend ResponseHelper
3
+
4
+ def self.response_for(titles)
5
+ titles = titles.is_a?(Array) ? titles : [titles]
6
+
7
+ results = {
8
+ titles: titles,
9
+ meta: titles.first.fetch("meta", nil)
10
+ }.compact
11
+
12
+ build(
13
+ response: stubbed_response(results.to_json)
14
+ )
15
+ end
16
+ end
@@ -0,0 +1,14 @@
1
+ FactoryBot.define do
2
+ factory :cfr_reference, class: "Ecfr::AdminService::EcfrCorrection::CfrReference" do
3
+ skip_create
4
+
5
+ cfr_reference { "1 CFR 1" }
6
+ hierarchy {
7
+ ecfr_attribute_hash(:hierarchy, title: "1", part: "1")
8
+ }
9
+
10
+ initialize_with {
11
+ new(attributes.deep_stringify_keys)
12
+ }
13
+ end
14
+ end
@@ -0,0 +1,31 @@
1
+ FactoryBot.define do
2
+ factory :ecfr_correction, class: "Ecfr::AdminService::EcfrCorrection" do
3
+ skip_create
4
+
5
+ corrective_action { "corrected" }
6
+ fr_citation { "84 FR 12345" }
7
+
8
+ id { 1 }
9
+ position { 1 }
10
+ title { 1 }
11
+ year { correction_year }
12
+
13
+ error_corrected { Date.parse("#{year}-03-03") }
14
+ error_occurred { Date.parse("#{year}-01-01") }
15
+ last_modified { error_corrected }
16
+
17
+ cfr_references {
18
+ [ecfr_attribute_hash(:cfr_reference)]
19
+ }
20
+
21
+ display_in_toc { false }
22
+
23
+ initialize_with {
24
+ new(attributes.deep_stringify_keys)
25
+ }
26
+
27
+ transient do
28
+ correction_year { 2017 }
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,12 @@
1
+ FactoryBot.define do
2
+ factory :issue_change, class: "Ecfr::AdminService::Issue::Change" do
3
+ skip_create
4
+
5
+ change_description { "5 CFR 123" }
6
+ change_type { :effective }
7
+
8
+ initialize_with {
9
+ new(attributes.deep_stringify_keys)
10
+ }
11
+ end
12
+ end
@@ -0,0 +1,21 @@
1
+ FactoryBot.define do
2
+ factory :issue, class: "Ecfr::AdminService::Issue" do
3
+ skip_create
4
+
5
+ description { "January 1, 2019" }
6
+
7
+ titles { [5, 7, 9] }
8
+
9
+ end_date { "2019-01-01" }
10
+ issue_date { "2019-01-01" }
11
+ start_date { "2019-01-01" }
12
+
13
+ changes {
14
+ [ecfr_attribute_hash(:issue_change)]
15
+ }
16
+
17
+ initialize_with {
18
+ new(attributes.deep_stringify_keys)
19
+ }
20
+ end
21
+ end
@@ -0,0 +1,36 @@
1
+ FactoryBot.define do
2
+ factory :hierarchy, class: "Ecfr::Common::Hierarchy" do
3
+ skip_create
4
+
5
+ title { nil }
6
+ subtitle { nil }
7
+ chapter { nil }
8
+ subchapter { nil }
9
+ part { nil }
10
+ subpart { nil }
11
+ subject_group { nil }
12
+ section { nil }
13
+ appendix { nil }
14
+
15
+ initialize_with {
16
+ new(attributes.deep_stringify_keys)
17
+ }
18
+
19
+ trait :with_defaults do
20
+ title { "1" }
21
+ subtitle { "A" }
22
+ chapter { "I" }
23
+ subchapter { "I" }
24
+ part { "1" }
25
+ subpart { "B" }
26
+ subject_group { nil }
27
+ section { "1.1" }
28
+ appendix { nil }
29
+ end
30
+
31
+ trait :appendix do
32
+ section { nil }
33
+ appendix { "Appendix A to Part 1" }
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,32 @@
1
+ FactoryBot.define do
2
+ factory :origin, class: "Ecfr::RendererService::Origin" do
3
+ skip_create
4
+
5
+ identifier { "121" }
6
+ label_level { "Part 121" }
7
+ level { "part" }
8
+ link { "/current/title-40/part-121" }
9
+ title { "Part 121" }
10
+
11
+ authority {
12
+ ["Sec. 21 (b) and (c), 84 Stat. 91 (<a href=\"https://www.govinfo.gov/link/uscode/33/1171\" class=\"usc external\" target=\"_blank\" rel=\"noopener noreferrer\">33 U.S.C. 1171(b)</a> (1970)); Reorganization Plan No. 3 of 1970. "]
13
+ }
14
+ source {
15
+ ["<a href=\"https://www.federalregister.gov/citation/36-FR-22487\" class=\"fr-reference\" data-reference=\"36 FR 22487\">36 FR 22487</a>, Nov. 25, 1971, unless otherwise noted. Redesignated at <a href=\"https://www.federalregister.gov/citation/37-FR-21441\" class=\"fr-reference\" data-reference=\"37 FR 21441\">37 FR 21441</a>, Oct. 11, 1972, and further redesignated at <a href=\"https://www.federalregister.gov/citation/44-FR-32899\" class=\"fr-reference\" data-reference=\"44 FR 32899\">44 FR 32899</a>, June 7, 1979. "]
16
+ }
17
+
18
+ current { false }
19
+
20
+ hierarchy {
21
+ ecfr_attribute_hash(:hierarchy,
22
+ title: "40",
23
+ chapter: "I",
24
+ subchapter: "D",
25
+ part: "121")
26
+ }
27
+
28
+ initialize_with {
29
+ new(attributes.deep_stringify_keys)
30
+ }
31
+ end
32
+ end
@@ -0,0 +1,20 @@
1
+ FactoryBot.define do
2
+ factory :content_version_count, class: "Ecfr::SearchService::ContentVersion::Count" do
3
+ skip_create
4
+
5
+ meta {
6
+ {
7
+ description: "Description of results...",
8
+ total_count: total_count
9
+ }
10
+ }
11
+
12
+ transient do
13
+ total_count { 10 }
14
+ end
15
+
16
+ initialize_with {
17
+ new(attributes.deep_stringify_keys)
18
+ }
19
+ end
20
+ end
@@ -0,0 +1,76 @@
1
+ FactoryBot.define do
2
+ factory :content_version_result, class: "Ecfr::SearchService::ContentVersion::Result" do
3
+ skip_create
4
+
5
+ change_types { [] }
6
+
7
+ full_text_excerpt {
8
+ "Section 100.100 full text excerpt with <strong>formatting</strong>"
9
+ }
10
+
11
+ hierarchy {
12
+ {
13
+ title: "10",
14
+ subtitle: "B",
15
+ chapter: "II",
16
+ subchapter: "H",
17
+ part: "100",
18
+ subpart: "D",
19
+ subject_group: nil,
20
+ section: (type == "Section") ? "100.100" : nil,
21
+ appendix: (type == "Appendix") ? "Appendix A to Subpart D of Part 100" : nil
22
+ }
23
+ }
24
+
25
+ # defaults for these are generated in helpers based on the hierarchy
26
+ # provided - any provided here will override just those keys
27
+ headings { {} }
28
+ hierarchy_headings { {} }
29
+
30
+ reserved { false }
31
+ removed { false }
32
+
33
+ score { 16.946056 }
34
+ structure_index { 1 }
35
+
36
+ starts_on { "2017-01-03" }
37
+ ends_on { nil }
38
+
39
+ type { "Section" }
40
+
41
+ trait :appendix do
42
+ type { "Appendix" }
43
+ end
44
+
45
+ meta {
46
+ {
47
+ current_page: current_page,
48
+ description: description,
49
+ min_date: min_date,
50
+ max_date: max_date,
51
+ max_score: max_score,
52
+ total_count: total_count,
53
+ total_pages: total_pages
54
+ }
55
+ }
56
+
57
+ transient do
58
+ current_page { 1 }
59
+ description { "Results for search terms x, y, and z" }
60
+ min_date { "2017-01-03" }
61
+ max_date { "2017-01-10" }
62
+ max_score { 1 }
63
+ total_count { 1 }
64
+ total_pages { 1 }
65
+ end
66
+
67
+ initialize_with {
68
+ attrs = FactoryBotHelpers::EcfrGemInitializeHelpers.pre_initialize_attrs_for(
69
+ :content_version_result,
70
+ attributes
71
+ )
72
+
73
+ new(attrs.deep_stringify_keys)
74
+ }
75
+ end
76
+ end