so_far_so_good 0.0.3 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +54 -34
- data/lib/so_far_so_good/subchapter.rb +88 -0
- data/lib/so_far_so_good/{clause.rb → subpart.rb} +20 -5
- data/lib/so_far_so_good/version.rb +1 -1
- data/lib/so_far_so_good.rb +27 -5
- data/script/release +36 -1
- data/script/vendor +2 -1
- data/test/so_far_so_good_subchapter_test.rb +59 -0
- data/test/so_far_so_good_subpart_test.rb +59 -0
- data/test/so_far_so_good_test.rb +19 -6
- data/vendor/{CFR-2010-title48-vol2-chap1-subchapH.xml → CFR-2013-title48-vol2-chap1-subchapH.xml} +2664 -2225
- data/vendor/CFR-2013-title48-vol3-chap2-subchapH.xml +10668 -0
- metadata +10 -10
- data/lib/so_far_so_good/clauses.rb +0 -58
- data/output.json +0 -1
- data/test/so_far_so_good_clause_test.rb +0 -58
- data/test/so_far_so_good_clauses_test.rb +0 -49
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ab77e766152edb727d4513fc59371d119f0339b3
|
4
|
+
data.tar.gz: fd27195a2227fa669f86d93593a5eeded9c8310c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 305cdec6f88a0555b7af3504414b48814e8927efc19b42e93746f553a69f9b9d181e5bfe748db258ed242b7c51bd5d758faf47fa236f07fbf28329d5acb3263f
|
7
|
+
data.tar.gz: 09d6f2de3a92e53f8f3e7079b89fa18793fd588d522738ead0e9969f48a8ebd5ef09216d28365df55845b7dcc66470d43914d541566ffb8348126fb8149d2475
|
data/README.md
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
# So FAR so Good
|
2
2
|
|
3
|
-
A Ruby Gem to parse and manipulate the Federal Acquisition Regulation
|
3
|
+
A Ruby Gem to parse and manipulate the Federal Acquisition Regulation (FAR) and Defense Federal Acquisition Regulation Supplement (DFARs)
|
4
4
|
|
5
5
|
[![Gem Version](https://badge.fury.io/rb/so_far_so_good.svg)](http://badge.fury.io/rb/so_far_so_good) [![Build Status](https://travis-ci.org/benbalter/so_far_so_good.svg)](https://travis-ci.org/benbalter/so_far_so_good)
|
6
6
|
|
7
7
|
## What it does
|
8
8
|
|
9
|
-
So FAR so Good is a Ruby Gem to interact with the Federal Acquisition Regulation. Right now, it
|
9
|
+
So FAR so Good is a Ruby Gem to interact with the Federal Acquisition Regulation (FAR) and Defense Federal Acquisition Regulation Supplement (DFARs). Right now, it supports section 52.20x and 252.20x, the FAR and DFARs standard contracting clause templates.
|
10
10
|
|
11
11
|
For any contract clause, it will provide:
|
12
12
|
|
@@ -16,6 +16,7 @@ For any contract clause, it will provide:
|
|
16
16
|
* The formal citation
|
17
17
|
* The body (full clause text)
|
18
18
|
* The extract (what's inserted into the contract)
|
19
|
+
* A link to the full text online
|
19
20
|
|
20
21
|
It will give you access to this information in object-oriented Ruby, as JSON, or as a markdown table for use elsewhere.
|
21
22
|
|
@@ -24,69 +25,77 @@ It will give you access to this information in object-oriented Ruby, as JSON, or
|
|
24
25
|
### Basic usage
|
25
26
|
|
26
27
|
```ruby
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
#<SoFarSoGood::
|
34
|
-
|
35
|
-
|
36
|
-
SoFarSoGood::
|
28
|
+
subchapters = SoFarSoGood.subchapters
|
29
|
+
=> [#<SoFarSoGood::Subchapter year=2013 title=48 volume=2 chapter=1 name="FAR">,
|
30
|
+
#<SoFarSoGood::Subchapter year=2013 title=48 volume=3 chapter=2 name="DFARs">]
|
31
|
+
|
32
|
+
# Get the FAR's subparts
|
33
|
+
subparts = SoFarSoGood.far.subparts
|
34
|
+
=> [#<SoFarSoGood::Subpart year=2013 title=48 volume=2 chapter=1 number="52.200" subject="Scope of subpart." document="FAR" reserved=false>,
|
35
|
+
#<SoFarSoGood::Subpart year=2013 title=48 volume=2 chapter=1 number="52.202-1" subject="Definitions." document="FAR" reserved=false>,
|
36
|
+
#<SoFarSoGood::Subpart year=2013 title=48 volume=2 chapter=1 number="52.203-1" subject="[Reserved]" document="FAR" reserved=true>,
|
37
|
+
#<SoFarSoGood::Subpart year=2013 title=48 volume=2 chapter=1 number="52.203-2" subject="Certificate of Independent Price Determination." document="FAR" reserved=false>,
|
38
|
+
#<SoFarSoGood::Subpart year=2013 title=48 volume=2 chapter=1 number="52.203-3" subject="Gratuities." document="FAR" reserved=false>,
|
39
|
+
#<SoFarSoGood::Subpart year=2013 title=48 volume=2 chapter=1 number="52.203-4" subject="[Reserved]" document="FAR" reserved=true>...]
|
40
|
+
|
41
|
+
# Get a list of subpart numbers
|
42
|
+
SoFarSoGood.far.numbers
|
37
43
|
=> ["52.200", "52.202-1", "52.203-1", "52.203-2", "52.203-3", "52.203-4", "52.203-5", ... ]
|
38
44
|
|
39
|
-
# Get a list of
|
40
|
-
SoFarSoGood
|
45
|
+
# Get a list of subpart numbers, excluding reserved clauses
|
46
|
+
SoFarSoGood.far.numbers(:reserved => false)
|
41
47
|
=> ["52.200", "52.202-1", "52.203-1", "52.203-2", "52.203-3", "52.203-4", "52.203-5", ... ]
|
42
48
|
|
43
|
-
# Get a list of
|
44
|
-
SoFarSoGood
|
49
|
+
# Get a list of subpart subjects
|
50
|
+
SoFarSoGood.far.subjects
|
45
51
|
=> ["Scope of subpart.", "Definitions.", "[Reserved]", "Certificate of Independent Price Determination.", ... ]
|
46
52
|
```
|
47
53
|
|
48
54
|
### Working with individual clauses
|
49
55
|
|
50
56
|
```ruby
|
51
|
-
# Get a specific
|
52
|
-
|
53
|
-
=> #<SoFarSoGood::
|
57
|
+
# Get a specific subpart
|
58
|
+
subpart = SoFarSoGood["52.202-1"]
|
59
|
+
=> #<SoFarSoGood::Subpart year=2013 title=48 volume=2 chapter=1 number="52.202-1" subject="Definitions." document="FAR" reserved=false>
|
54
60
|
|
55
|
-
|
61
|
+
subpart.number
|
56
62
|
=> "52.202-1"
|
57
63
|
|
58
|
-
|
64
|
+
subpart.subject
|
59
65
|
=> "Definitions"
|
60
66
|
|
61
|
-
|
67
|
+
subpart.reserved?
|
62
68
|
=> false
|
63
69
|
|
64
|
-
|
70
|
+
subpart.citation
|
65
71
|
=> "[69 FR 34228, June 18, 2004]"
|
66
72
|
|
67
73
|
# The full clause body
|
68
|
-
|
74
|
+
subpart.body
|
69
75
|
=> "As prescribed in 2.201, insert the following clause:..."
|
70
76
|
|
71
77
|
# The actual clause text to be inserted in the contract
|
72
|
-
|
78
|
+
subpart.extract
|
73
79
|
=> "Definitions (JUL 2004)(a) When a solicitation provision or contract clause uses a word..."
|
80
|
+
|
81
|
+
subpart.link
|
82
|
+
=> "http://www.law.cornell.edu/cfr/text/48/52.202-1"
|
74
83
|
```
|
75
84
|
|
76
|
-
### Using
|
85
|
+
### Using subpart data elsewhere
|
77
86
|
|
78
87
|
#### As JSON
|
79
88
|
|
80
89
|
```ruby
|
81
90
|
|
82
|
-
SoFarSoGood
|
91
|
+
SoFarSoGood.far.to_json
|
83
92
|
=> "[{\"number\":\"52.200\",\"subject\":\"Scope of subpart.\",\"reserverd\":false,\"citation\":..."
|
84
93
|
```
|
85
94
|
|
86
95
|
#### As a markdown table
|
87
96
|
|
88
97
|
```ruby
|
89
|
-
puts SoFarSoGood
|
98
|
+
puts SoFarSoGood.far.to_md
|
90
99
|
|-----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
91
100
|
| Clause | Description |
|
92
101
|
|-----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
@@ -97,11 +106,11 @@ puts SoFarSoGood::Clauses.to_md
|
|
97
106
|
| 52.203-5 | Covenant Against Contingent Fees. |
|
98
107
|
...
|
99
108
|
|
100
|
-
# Table without reserved
|
101
|
-
puts SoFarSoGood
|
109
|
+
# Table without reserved subparts
|
110
|
+
puts SoFarSoGood.dfars.to_md(:reserved => false)
|
102
111
|
|
103
112
|
# Table with links to text
|
104
|
-
puts SoFarSoGood
|
113
|
+
puts SoFarSoGood.far.to_md(:links => true)
|
105
114
|
...
|
106
115
|
| [52.222-34](http://www.law.cornell.edu/cfr/text/48/52.222-34) | Project Labor Agreement. |
|
107
116
|
| [52.222-35](http://www.law.cornell.edu/cfr/text/48/52.222-35) | Equal Opportunity for Veterans. |
|
@@ -112,15 +121,26 @@ puts SoFarSoGood::Clauses.to_md(:links => true)
|
|
112
121
|
...
|
113
122
|
```
|
114
123
|
|
115
|
-
####
|
124
|
+
#### As a CSV
|
125
|
+
```ruby
|
126
|
+
puts SoFarSoGood.far.to_csv(:reserved => false)
|
127
|
+
Clause,Description
|
128
|
+
52.200,Scope of subpart.
|
129
|
+
52.202-1,Definitions.
|
130
|
+
52.203-2,Certificate of Independent Price Determination.
|
131
|
+
52.203-3,Gratuities.
|
132
|
+
52.203-5,Covenant Against Contingent Fees.
|
133
|
+
```
|
134
|
+
|
135
|
+
#### Individual subparts as markdown
|
116
136
|
|
117
137
|
```ruby
|
118
138
|
# The body
|
119
|
-
puts SoFarSoGood
|
139
|
+
puts SoFarSoGood["52.202-1"].body(:format => :markdown)
|
120
140
|
=> As prescribed in 2.201, insert the following clause:
|
121
141
|
|
122
142
|
# The extract
|
123
|
-
puts SoFarSoGood
|
143
|
+
puts SoFarSoGood["52.202-1"].extract(:format => :markdown)
|
124
144
|
=> ### Definitions (JUL 2004)
|
125
145
|
|
126
146
|
(a) When a solicitation provision or contract clause uses a word or term that is defined in the Federal Acquisition Regulation (FAR), the word or term has the same meaning as the definition in FAR 2.101 in effect at the time the solicitation was issued, unless— ...
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module SoFarSoGood
|
2
|
+
class Subchapter
|
3
|
+
|
4
|
+
attr_reader :year
|
5
|
+
attr_reader :title
|
6
|
+
attr_reader :volume
|
7
|
+
attr_reader :chapter
|
8
|
+
attr_reader :name
|
9
|
+
|
10
|
+
def initialize(hash)
|
11
|
+
@volume = hash[:volume]
|
12
|
+
@chapter = hash[:chapter]
|
13
|
+
@name = hash[:name]
|
14
|
+
@year = SoFarSoGood::YEAR
|
15
|
+
@title = SoFarSoGood::TITLE
|
16
|
+
end
|
17
|
+
|
18
|
+
def numbers(options = {})
|
19
|
+
@numbers ||= subparts(options).map { |s| s.number }
|
20
|
+
end
|
21
|
+
|
22
|
+
def subjects(options = {})
|
23
|
+
@subjects ||= subparts(options).map { |s| s.subject }
|
24
|
+
end
|
25
|
+
|
26
|
+
def subparts(options = {})
|
27
|
+
@subparts ||= sections.map { |node| SoFarSoGood::Subpart.new(to_hash.merge(:node => node)) }
|
28
|
+
@subparts.select { |subpart| options.all? { |k,v| subpart.send(k) == v } }
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_md(options = {})
|
32
|
+
links = options.delete(:links) == true
|
33
|
+
rows = subparts(options).map { |c| [ links ? "[#{c.number}](#{c.link})" : c.number , c.subject] }
|
34
|
+
Terminal::Table.new(:rows => rows, :style => { :border_i => "|" }, :headings => HEADINGS).to_s
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_json(options = {})
|
38
|
+
subparts(options).to_json(options)
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_csv(options = {})
|
42
|
+
CSV.generate do |csv|
|
43
|
+
csv << HEADINGS
|
44
|
+
subparts(options).each do |c|
|
45
|
+
csv << [c.number , c.subject]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_hash
|
51
|
+
{
|
52
|
+
:year => year,
|
53
|
+
:title => title,
|
54
|
+
:volume => volume,
|
55
|
+
:chapter => chapter,
|
56
|
+
:name => name
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
def [](number)
|
61
|
+
subparts.find { |s| s.number == number }
|
62
|
+
end
|
63
|
+
|
64
|
+
def inspect
|
65
|
+
"#<SoFarSoGood::Subchapter year=#{year} title=#{title} volume=#{volume} chapter=#{chapter} name=\"#{name}\">"
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def filename
|
71
|
+
"CFR-#{YEAR}-title#{TITLE}-vol#{volume}-chap#{chapter}-subchapH.xml"
|
72
|
+
end
|
73
|
+
|
74
|
+
def source_path
|
75
|
+
@source_path ||= File.expand_path filename, SoFarSoGood.vendor_directory
|
76
|
+
end
|
77
|
+
|
78
|
+
def doc
|
79
|
+
@doc ||= Nokogiri::XML(File.open(source_path)) do |config|
|
80
|
+
config.noblanks.nonet
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def sections
|
85
|
+
@subpart ||= doc.css("PART SUBPART")[name == "FAR" ? 4 : 3].children.css("SECTION")
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -1,10 +1,20 @@
|
|
1
1
|
module SoFarSoGood
|
2
|
-
class
|
2
|
+
class Subpart
|
3
3
|
|
4
4
|
attr_reader :node
|
5
|
+
attr_reader :year
|
6
|
+
attr_reader :title
|
7
|
+
attr_reader :volume
|
8
|
+
attr_reader :chapter
|
9
|
+
attr_reader :document
|
5
10
|
|
6
|
-
def initialize(
|
7
|
-
@
|
11
|
+
def initialize(hash)
|
12
|
+
@year = hash[:year]
|
13
|
+
@title = hash[:title]
|
14
|
+
@volume = hash[:volume]
|
15
|
+
@chapter = hash[:chapter]
|
16
|
+
@document = hash[:name]
|
17
|
+
@node = hash[:node]
|
8
18
|
normalize!
|
9
19
|
end
|
10
20
|
|
@@ -51,13 +61,18 @@ module SoFarSoGood
|
|
51
61
|
|
52
62
|
def to_hash(options={})
|
53
63
|
{
|
64
|
+
:year => year,
|
65
|
+
:title => title,
|
66
|
+
:volume => volume,
|
67
|
+
:chapter => chapter,
|
54
68
|
:number => number,
|
55
69
|
:subject => subject,
|
56
70
|
:reserverd => reserved,
|
57
71
|
:citation => citation,
|
58
72
|
:extract => extract(options),
|
59
73
|
:body => body(options),
|
60
|
-
:link => link
|
74
|
+
:link => link,
|
75
|
+
:document => document,
|
61
76
|
}
|
62
77
|
end
|
63
78
|
|
@@ -66,7 +81,7 @@ module SoFarSoGood
|
|
66
81
|
end
|
67
82
|
|
68
83
|
def inspect
|
69
|
-
"#<SoFarSoGood::
|
84
|
+
"#<SoFarSoGood::Subpart year=#{year} title=#{title} volume=#{volume} chapter=#{chapter} number=\"#{number}\" subject=\"#{subject}\" document=\"#{document}\" reserved=#{reserved}>"
|
70
85
|
end
|
71
86
|
|
72
87
|
private
|
data/lib/so_far_so_good.rb
CHANGED
@@ -1,15 +1,37 @@
|
|
1
1
|
require "nokogiri"
|
2
2
|
require "terminal-table"
|
3
|
-
require "json"
|
4
3
|
require "reverse_markdown"
|
4
|
+
require "json"
|
5
|
+
require 'csv'
|
5
6
|
require_relative "so_far_so_good/version"
|
6
|
-
require_relative "so_far_so_good/
|
7
|
-
require_relative "so_far_so_good/
|
7
|
+
require_relative "so_far_so_good/subchapter"
|
8
|
+
require_relative "so_far_so_good/subpart"
|
8
9
|
|
9
10
|
module SoFarSoGood
|
11
|
+
|
12
|
+
HEADINGS = ["Clause", "Description"]
|
13
|
+
YEAR = 2013
|
14
|
+
TITLE = 48
|
15
|
+
|
10
16
|
class << self
|
11
|
-
def
|
12
|
-
SoFarSoGood::
|
17
|
+
def far
|
18
|
+
@far ||= SoFarSoGood::Subchapter.new(:name => "FAR", :volume => 2, :chapter => 1)
|
19
|
+
end
|
20
|
+
|
21
|
+
def dfars
|
22
|
+
@dfars ||= SoFarSoGood::Subchapter.new(:name => "DFARs", :volume => 3, :chapter => 2)
|
23
|
+
end
|
24
|
+
|
25
|
+
def subchapters
|
26
|
+
[far, dfars]
|
27
|
+
end
|
28
|
+
|
29
|
+
def subparts(options = {})
|
30
|
+
subchapters.map { |d| d.subparts(options) }.flatten
|
31
|
+
end
|
32
|
+
|
33
|
+
def [](subpart)
|
34
|
+
subparts.find { |s| s.number == subpart }
|
13
35
|
end
|
14
36
|
|
15
37
|
def vendor_directory
|
data/script/release
CHANGED
@@ -1,3 +1,38 @@
|
|
1
1
|
#!/bin/sh
|
2
|
+
# Tag and push a release.
|
2
3
|
|
3
|
-
|
4
|
+
set -e
|
5
|
+
|
6
|
+
# Make sure we're in the project root.
|
7
|
+
|
8
|
+
cd $(dirname "$0")/..
|
9
|
+
|
10
|
+
# Build a new gem archive.
|
11
|
+
|
12
|
+
rm -rf so_far_so_good-*.gem
|
13
|
+
gem build -q so_far_so_good.gemspec
|
14
|
+
|
15
|
+
# Make sure we're on the master branch.
|
16
|
+
|
17
|
+
(git branch | grep -q '* master') || {
|
18
|
+
echo "Only release from the master branch."
|
19
|
+
exit 1
|
20
|
+
}
|
21
|
+
|
22
|
+
# Figure out what version we're releasing.
|
23
|
+
|
24
|
+
tag=v`ls so_far_so_good-*.gem | sed 's/^so_far_so_good-\(.*\)\.gem$/\1/'`
|
25
|
+
|
26
|
+
# Make sure we haven't released this version before.
|
27
|
+
|
28
|
+
git fetch -t origin
|
29
|
+
|
30
|
+
(git tag -l | grep -q "$tag") && {
|
31
|
+
echo "Whoops, there's already a '${tag}' tag."
|
32
|
+
exit 1
|
33
|
+
}
|
34
|
+
|
35
|
+
# Tag it and bag it.
|
36
|
+
|
37
|
+
gem push so_far_so_good-*.gem && git tag "$tag" &&
|
38
|
+
git push origin master && git push origin "$tag"
|
data/script/vendor
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
#!/bin/sh
|
2
2
|
|
3
3
|
rm -Rf ./vendor/*
|
4
|
-
wget http://www.gpo.gov/fdsys/pkg/CFR-
|
4
|
+
wget http://www.gpo.gov/fdsys/pkg/CFR-2013-title48-vol2/xml/CFR-2013-title48-vol2-chap1-subchapH.xml -P vendor
|
5
|
+
wget http://www.gpo.gov/fdsys/pkg/CFR-2013-title48-vol3/xml/CFR-2013-title48-vol3-chap2-subchapH.xml -P vendor
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestSoFarSoGoodSubchapter < Minitest::Test
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@subchapter = SoFarSoGood.far
|
7
|
+
end
|
8
|
+
|
9
|
+
should "know the subchapter file" do
|
10
|
+
assert File.exists? @subchapter.send :source_path
|
11
|
+
end
|
12
|
+
|
13
|
+
should "parse the XML" do
|
14
|
+
assert Nokogiri::XML::Document, @subchapter.send(:doc).class
|
15
|
+
end
|
16
|
+
|
17
|
+
should "parse subpart numbers" do
|
18
|
+
assert_equal 626, @subchapter.numbers.count
|
19
|
+
assert_equal "52.200", @subchapter.numbers.first
|
20
|
+
end
|
21
|
+
|
22
|
+
should "parse subpart descriptions" do
|
23
|
+
assert_equal 626, @subchapter.subjects.count
|
24
|
+
assert_equal "Scope of subpart.", @subchapter.subjects.first
|
25
|
+
end
|
26
|
+
|
27
|
+
should "put out valid JSON" do
|
28
|
+
assert !!JSON.parse(@subchapter.subparts.to_json)
|
29
|
+
end
|
30
|
+
|
31
|
+
should "return a particular subpart" do
|
32
|
+
assert_equal "52.202-1", @subchapter["52.202-1"].number
|
33
|
+
end
|
34
|
+
|
35
|
+
should "return all subparts" do
|
36
|
+
assert_equal 626, @subchapter.subparts.count
|
37
|
+
end
|
38
|
+
|
39
|
+
should "filter reserved subparts" do
|
40
|
+
assert_equal 576, @subchapter.subparts(:reserved => false).count
|
41
|
+
end
|
42
|
+
|
43
|
+
should "build the markdown table" do
|
44
|
+
assert_includes @subchapter.to_md, "-|\n| 52.200 | Scope of subpart."
|
45
|
+
end
|
46
|
+
|
47
|
+
should "exclude reserved in markdown table when asked" do
|
48
|
+
refute_includes @subchapter.to_md(:reserved => false), "[Reserved]"
|
49
|
+
end
|
50
|
+
|
51
|
+
should "include links in markdown table when asked" do
|
52
|
+
assert_includes @subchapter.to_md(:links => true), "[52.252-6](http://www.law.cornell.edu/cfr/text/48/52.252-6)"
|
53
|
+
end
|
54
|
+
|
55
|
+
should "output valid CSV" do
|
56
|
+
csv = CSV.parse @subchapter.to_csv
|
57
|
+
assert_equal ["52.200", "Scope of subpart."], csv[1]
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestSoFarSoGoodSubpart < Minitest::Test
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@subchapter = SoFarSoGood.far
|
7
|
+
@nodes = @subchapter.send(:sections)
|
8
|
+
@subpart = SoFarSoGood::Subpart.new(:node => @nodes[6])
|
9
|
+
end
|
10
|
+
|
11
|
+
should "Store the node" do
|
12
|
+
assert Nokogiri::XML::Element, @subpart.node.class
|
13
|
+
end
|
14
|
+
|
15
|
+
should "expose the subpart number" do
|
16
|
+
assert_equal "52.203-5", @subpart.number
|
17
|
+
end
|
18
|
+
|
19
|
+
should "expose the subpart subject" do
|
20
|
+
assert_equal "Covenant Against Contingent Fees.", @subpart.subject
|
21
|
+
end
|
22
|
+
|
23
|
+
should "know the cite" do
|
24
|
+
assert_includes @subpart.citation, "48 FR 42478"
|
25
|
+
end
|
26
|
+
|
27
|
+
should "know the subpart body" do
|
28
|
+
assert_includes @subpart.body, "As prescribed in 3.404,"
|
29
|
+
end
|
30
|
+
|
31
|
+
should "not include the extract in the subpart body" do
|
32
|
+
refute_includes @subpart.body, "The Contractor warrants that no person or agency"
|
33
|
+
end
|
34
|
+
|
35
|
+
should "know the subpart extract" do
|
36
|
+
assert_includes @subpart.extract, "The Contractor warrants that no person or agency"
|
37
|
+
end
|
38
|
+
|
39
|
+
should "know if its reserved" do
|
40
|
+
refute @subchapter["52.203-5"].reserved?
|
41
|
+
assert @subchapter["52.203-1"].reserved?
|
42
|
+
end
|
43
|
+
|
44
|
+
should "convert the body to markdown" do
|
45
|
+
assert_includes @subpart.body(:format => :markdown), "As prescribed in 3.404, insert the following clause:\n\n"
|
46
|
+
end
|
47
|
+
|
48
|
+
should "convert the extract to markdown" do
|
49
|
+
assert_includes @subpart.extract(:format => :markdown), "### Covenant Against Contingent Fees (APR 1984)\n\n(a)"
|
50
|
+
end
|
51
|
+
|
52
|
+
should "build the link" do
|
53
|
+
assert_equal "http://www.law.cornell.edu/cfr/text/48/52.203-5", @subpart.link
|
54
|
+
end
|
55
|
+
|
56
|
+
should "put out valid json" do
|
57
|
+
assert JSON.parse @subchapter["52.203-5"].to_json
|
58
|
+
end
|
59
|
+
end
|
data/test/so_far_so_good_test.rb
CHANGED
@@ -2,15 +2,28 @@ require 'helper'
|
|
2
2
|
|
3
3
|
class TestSoFarSoGood < Minitest::Test
|
4
4
|
should "figure out the vendor directory" do
|
5
|
-
assert File.exists?(SoFarSoGood.vendor_directory)
|
5
|
+
assert File.exists?(SoFarSoGood.send(:vendor_directory))
|
6
6
|
end
|
7
7
|
|
8
|
-
should "
|
9
|
-
assert_equal
|
10
|
-
assert_equal
|
8
|
+
should "know the FAR" do
|
9
|
+
assert_equal SoFarSoGood::Subchapter, SoFarSoGood.far.class
|
10
|
+
assert_equal "FAR", SoFarSoGood.far.name
|
11
11
|
end
|
12
12
|
|
13
|
-
should "
|
14
|
-
assert_equal
|
13
|
+
should "know the DFARs" do
|
14
|
+
assert_equal SoFarSoGood::Subchapter, SoFarSoGood.dfars.class
|
15
|
+
assert_equal "DFARs", SoFarSoGood.dfars.name
|
16
|
+
end
|
17
|
+
|
18
|
+
should "return subchapters" do
|
19
|
+
assert_equal 2, SoFarSoGood.subchapters.count
|
20
|
+
end
|
21
|
+
|
22
|
+
should "return subparts" do
|
23
|
+
assert_equal 981, SoFarSoGood.subparts.count
|
24
|
+
end
|
25
|
+
|
26
|
+
should "accept subpart options" do
|
27
|
+
assert_equal 907, SoFarSoGood.subparts(:reserved => false).count
|
15
28
|
end
|
16
29
|
end
|