lutra 0.0.3 → 0.1.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.
- checksums.yaml +4 -4
- data/LICENSE +1 -1
- data/README.md +1 -1
- data/lib/lutra/formatter.rb +12 -15
- data/lib/lutra/formatter_entry.rb +3 -0
- data/lib/lutra/formatters/base.rb +12 -1
- data/lib/lutra/formatters/default.rb +4 -4
- data/lib/lutra/note.rb +1 -1
- data/lib/lutra/scanner.rb +13 -18
- data/lib/lutra/version.rb +1 -1
- data/lib/lutra.rb +5 -8
- data/lutra.gemspec +0 -3
- data/spec/{example → fixtures/sample} +0 -0
- data/spec/lib/formatter_spec.rb +48 -0
- data/spec/lib/formatters/base_spec.rb +7 -0
- data/spec/lib/formatters/default_spec.rb +16 -0
- data/spec/lib/scanner_spec.rb +50 -0
- data/spec/spec_helper.rb +10 -2
- data/spec/support/data_support.rb +9 -0
- data/spec/support/std_support.rb +10 -0
- metadata +19 -46
- data/spec/formatter_spec.rb +0 -50
- data/spec/formatters/base_spec.rb +0 -11
- data/spec/formatters/default_spec.rb +0 -7
- data/spec/lutra_spec.rb +0 -4
- data/spec/note_spec.rb +0 -23
- data/spec/scanner_spec.rb +0 -35
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7f8c765a1000685a3016a70883f677a1b04f2d8e
|
4
|
+
data.tar.gz: 28ebafeccba7985f66f792eb95147612458df62a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9033f3b86c5bd1faf8c709a02397995420b7f35e36652b8d8cb523af488e818a316a6235470de8458cbf0d01e9ff76f4d1fa54a4ca5e791525838364c795ce6e
|
7
|
+
data.tar.gz: 910a84648c31d3ae93d903f50c625e52302a4d77ebd2ae44ed36064331244da48efd8d6234ec705387f5a236dccdd18694aa80053f58275aebc094593458854e
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
### lutra [](https://rubygems.org/gems/lutra) [](https://travis-ci.org/artemeff/lutra) [](https://codeclimate.com/github/artemeff/lutra)
|
2
2
|
|
3
3
|
---
|
4
4
|
|
data/lib/lutra/formatter.rb
CHANGED
@@ -1,19 +1,19 @@
|
|
1
|
+
require 'lutra/formatter_entry'
|
2
|
+
|
1
3
|
module Lutra
|
2
4
|
class Formatter
|
3
5
|
attr_reader :formatters, :current
|
4
6
|
|
5
7
|
def initialize(options = {})
|
6
|
-
@options =
|
8
|
+
@options = options
|
7
9
|
@current = :default
|
8
|
-
@formatters = [
|
9
|
-
{ name: :default, short: :d, class: Lutra::Formatters::Default }
|
10
|
-
]
|
10
|
+
@formatters = [default_formatter]
|
11
11
|
end
|
12
12
|
|
13
13
|
def get(name)
|
14
|
-
@formatters.
|
15
|
-
f
|
16
|
-
end
|
14
|
+
@formatters.find do |f|
|
15
|
+
f.name == name || f.short == name
|
16
|
+
end
|
17
17
|
end
|
18
18
|
|
19
19
|
def set(name)
|
@@ -26,25 +26,22 @@ module Lutra
|
|
26
26
|
|
27
27
|
def add(name, short_name, class_name)
|
28
28
|
if formatter?(class_name)
|
29
|
-
@formatters <<
|
29
|
+
@formatters << FormatterEntry.new(name, short_name, class_name)
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
33
|
def display(notes)
|
34
|
-
get(@current)
|
34
|
+
get(@current).class_name.new(@options).display(notes)
|
35
35
|
end
|
36
36
|
|
37
37
|
private
|
38
38
|
|
39
39
|
def formatter?(class_name)
|
40
|
-
class_name.new.respond_to?(:
|
40
|
+
class_name.new.respond_to?(:display)
|
41
41
|
end
|
42
42
|
|
43
|
-
def
|
44
|
-
|
45
|
-
display_tags: true,
|
46
|
-
text_size: 55
|
47
|
-
}
|
43
|
+
def default_formatter
|
44
|
+
FormatterEntry.new(:default, :d, Lutra::Formatters::Default)
|
48
45
|
end
|
49
46
|
end
|
50
47
|
end
|
@@ -1,13 +1,24 @@
|
|
1
1
|
module Lutra
|
2
2
|
module Formatters
|
3
3
|
class Base
|
4
|
+
attr_reader :options
|
5
|
+
|
4
6
|
def initialize(options = {})
|
5
|
-
@options = options
|
7
|
+
@options = default_options.merge(options)
|
6
8
|
end
|
7
9
|
|
8
10
|
def display(notes)
|
9
11
|
raise NotImplementedError
|
10
12
|
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def default_options
|
17
|
+
{
|
18
|
+
display_tags: true,
|
19
|
+
text_size: 55
|
20
|
+
}
|
21
|
+
end
|
11
22
|
end
|
12
23
|
end
|
13
24
|
end
|
@@ -14,10 +14,10 @@ module Lutra
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def prepare(note, indent)
|
17
|
-
s = "[#{note
|
18
|
-
s << "[#{note
|
19
|
-
s << note
|
20
|
-
s <<
|
17
|
+
s = "[#{note.line.to_s.rjust(indent)}] "
|
18
|
+
s << "[#{note.tag}] " if options[:display_tags]
|
19
|
+
s << note.text[0..options[:text_size]].strip.chomp
|
20
|
+
s << '...' if note.text.size > options[:text_size]
|
21
21
|
s
|
22
22
|
end
|
23
23
|
|
data/lib/lutra/note.rb
CHANGED
data/lib/lutra/scanner.rb
CHANGED
@@ -1,14 +1,16 @@
|
|
1
|
+
require 'lutra/note'
|
2
|
+
|
1
3
|
module Lutra
|
2
4
|
class Scanner
|
3
5
|
attr_accessor :tags, :comments
|
4
6
|
attr_reader :notes
|
5
7
|
|
6
|
-
def initialize(tags
|
7
|
-
|
8
|
-
|
9
|
-
@notes = []
|
8
|
+
def initialize(tags: Lutra::TAGS, comments: Lutra::COMMENTS)
|
9
|
+
raise EmptyTagListError if tags.empty?
|
10
|
+
raise EmptyCommentListError if comments.empty?
|
10
11
|
|
11
|
-
|
12
|
+
@tags, @comments = tags, comments
|
13
|
+
@notes = []
|
12
14
|
end
|
13
15
|
|
14
16
|
def scan_file(path)
|
@@ -18,24 +20,17 @@ module Lutra
|
|
18
20
|
private
|
19
21
|
|
20
22
|
def extract(source, path)
|
21
|
-
|
23
|
+
regexp = compile_regexp(@comments, @tags)
|
24
|
+
|
22
25
|
source.each_with_index do |line, i|
|
23
|
-
if
|
24
|
-
@notes << Note.new(
|
26
|
+
if result = regexp.match(line)
|
27
|
+
@notes << Note.new(result[:tag], result[:comment], result[:text], i + 1, path)
|
25
28
|
end
|
26
29
|
end
|
27
30
|
end
|
28
31
|
|
29
|
-
def
|
30
|
-
|
31
|
-
end
|
32
|
-
|
33
|
-
def check_comments
|
34
|
-
raise EmptyCommentListError if @comments.empty?
|
35
|
-
end
|
36
|
-
|
37
|
-
def regexp
|
38
|
-
/(#{@comments.join('|')})\s*(?<tag>#{@tags.join('|')})[\s|\:]*(?<text>.*)/
|
32
|
+
def compile_regexp(comments, tags)
|
33
|
+
/(?<comment>#{comments.join('|')})\s*(?<tag>#{tags.join('|')})[\s|\:]*(?<text>.*)/
|
39
34
|
end
|
40
35
|
end
|
41
36
|
end
|
data/lib/lutra/version.rb
CHANGED
data/lib/lutra.rb
CHANGED
@@ -1,17 +1,14 @@
|
|
1
|
-
require 'lutra/note'
|
2
1
|
require 'lutra/scanner'
|
3
2
|
require 'lutra/formatter'
|
4
3
|
require 'lutra/formatters/base'
|
5
4
|
require 'lutra/formatters/default'
|
6
|
-
require 'lutra/version'
|
7
5
|
|
8
6
|
module Lutra
|
9
7
|
TAGS = %w[TODO FIXME OPTIMIZE]
|
10
|
-
|
8
|
+
COMMENTS = %w[# % ; // --]
|
11
9
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
class FormatterNotFound < Exception; end
|
10
|
+
NotImplementedError = Class.new(StandardError)
|
11
|
+
EmptyTagListError = Class.new(StandardError)
|
12
|
+
EmptyCommentListError = Class.new(StandardError)
|
13
|
+
FormatterNotFound = Class.new(StandardError)
|
17
14
|
end
|
data/lutra.gemspec
CHANGED
File without changes
|
@@ -0,0 +1,48 @@
|
|
1
|
+
describe Lutra::Formatter do
|
2
|
+
context '.new' do
|
3
|
+
it 'have one formatter' do
|
4
|
+
expect(subject.formatters.size).to eq(1)
|
5
|
+
end
|
6
|
+
|
7
|
+
it 'have default formatter' do
|
8
|
+
expect(subject.formatters.first[:name]).to eq(:default)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
context '#add' do
|
13
|
+
it 'adds new formatter' do
|
14
|
+
expect(subject.add(:new, :n, Lutra::Formatters::Default).size).to eq(2)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context '#get' do
|
19
|
+
it 'finds formatter by name' do
|
20
|
+
expect(subject.get(:default)[:name]).to eq(:default)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'finds formatter short name' do
|
24
|
+
expect(subject.get(:d)[:name]).to eq(:default)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context '#set' do
|
29
|
+
it 'sets default formatter' do
|
30
|
+
subject.set(:default)
|
31
|
+
expect(subject.current).to eq(:default)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'raise error when formatter dont exist' do
|
35
|
+
expect {
|
36
|
+
subject.set(:poke)
|
37
|
+
}.to raise_error(Lutra::FormatterNotFound)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context '#display' do
|
42
|
+
let(:out) { capture_stdout { subject.display([]) } }
|
43
|
+
|
44
|
+
it 'prints notes with selected formatter' do
|
45
|
+
expect(out).to eq('')
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
describe Lutra::Formatters::Default do
|
2
|
+
let(:note) { Lutra::Note.new('TODO', '#', 'test', 113, '.././app/lib/test.rb') }
|
3
|
+
|
4
|
+
context '#display' do
|
5
|
+
let(:out) { capture_stdout { subject.display([note]) } }
|
6
|
+
let(:lines) { out.split("\n") }
|
7
|
+
|
8
|
+
it 'has filename in first line' do
|
9
|
+
expect(lines[0]).to eq('app/lib/test.rb:')
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'has todo entry in seconds line' do
|
13
|
+
expect(lines[1]).to eq(' * [113] [TODO] test')
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
|
3
|
+
describe Lutra::Scanner do
|
4
|
+
context '.new' do
|
5
|
+
subject { described_class }
|
6
|
+
|
7
|
+
it 'default tags' do
|
8
|
+
expect(subject.new.tags).to eq(['TODO', 'FIXME', 'OPTIMIZE'])
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'custom tags' do
|
12
|
+
expect(subject.new(tags: ['X']).tags).to eq(['X'])
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'default comments' do
|
16
|
+
expect(subject.new.comments).to eq(['#', '%', ';', '//', '--'])
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'custom comments' do
|
20
|
+
expect(subject.new(comments: ['#']).comments).to eq(['#'])
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context '#scan_file' do
|
25
|
+
let(:filename) { data_file('sample') }
|
26
|
+
let(:notes) { subject.notes }
|
27
|
+
|
28
|
+
before { subject.scan_file(filename) }
|
29
|
+
|
30
|
+
it 'have todo, fixme and optimize' do
|
31
|
+
expect(notes.map(&:tag)).to eq(['TODO', 'FIXME', 'OPTIMIZE'])
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'with custom tags' do
|
35
|
+
subject { described_class.new(tags: ['TODO']) }
|
36
|
+
|
37
|
+
it 'returns notes with only specified tag' do
|
38
|
+
expect(notes.map(&:tag)).to eq(['TODO'])
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'with custom comments' do
|
43
|
+
subject { described_class.new(comments: ['#']) }
|
44
|
+
|
45
|
+
it 'returns notes with only specified comments' do
|
46
|
+
expect(notes.map(&:comment)).to eq(['#'])
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
require 'lutra'
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
if ENV.fetch('CODECLIMATE_REPO_TOKEN', nil)
|
4
|
+
require 'codeclimate-test-reporter'
|
5
|
+
CodeClimate::TestReporter.start
|
6
|
+
end
|
7
|
+
|
8
|
+
Dir.glob('./spec/support/**/*.rb') { |file| require file }
|
9
|
+
|
10
|
+
RSpec.configure do |config|
|
11
|
+
include STDSupport
|
12
|
+
include DataSupport
|
5
13
|
end
|
metadata
CHANGED
@@ -1,43 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lutra
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yuri Artemev
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
12
|
-
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: rake
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ">="
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '0'
|
20
|
-
type: :development
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - ">="
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '0'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: rspec
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - ">="
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '2.1'
|
34
|
-
type: :development
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - ">="
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '2.1'
|
11
|
+
date: 2015-08-07 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
41
13
|
description: Parse tags (todo, fixme, optimize) in your source code
|
42
14
|
email:
|
43
15
|
- i@artemeff.com
|
@@ -51,20 +23,21 @@ files:
|
|
51
23
|
- bin/lutra
|
52
24
|
- lib/lutra.rb
|
53
25
|
- lib/lutra/formatter.rb
|
26
|
+
- lib/lutra/formatter_entry.rb
|
54
27
|
- lib/lutra/formatters/base.rb
|
55
28
|
- lib/lutra/formatters/default.rb
|
56
29
|
- lib/lutra/note.rb
|
57
30
|
- lib/lutra/scanner.rb
|
58
31
|
- lib/lutra/version.rb
|
59
32
|
- lutra.gemspec
|
60
|
-
- spec/
|
61
|
-
- spec/formatter_spec.rb
|
62
|
-
- spec/formatters/base_spec.rb
|
63
|
-
- spec/formatters/default_spec.rb
|
64
|
-
- spec/
|
65
|
-
- spec/note_spec.rb
|
66
|
-
- spec/scanner_spec.rb
|
33
|
+
- spec/fixtures/sample
|
34
|
+
- spec/lib/formatter_spec.rb
|
35
|
+
- spec/lib/formatters/base_spec.rb
|
36
|
+
- spec/lib/formatters/default_spec.rb
|
37
|
+
- spec/lib/scanner_spec.rb
|
67
38
|
- spec/spec_helper.rb
|
39
|
+
- spec/support/data_support.rb
|
40
|
+
- spec/support/std_support.rb
|
68
41
|
homepage: http://github.com/artemeff/lutra
|
69
42
|
licenses:
|
70
43
|
- MIT
|
@@ -85,17 +58,17 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
85
58
|
version: '0'
|
86
59
|
requirements: []
|
87
60
|
rubyforge_project:
|
88
|
-
rubygems_version: 2.4.
|
61
|
+
rubygems_version: 2.4.8
|
89
62
|
signing_key:
|
90
63
|
specification_version: 4
|
91
64
|
summary: In source annotaions parser
|
92
65
|
test_files:
|
93
|
-
- spec/
|
94
|
-
- spec/formatter_spec.rb
|
95
|
-
- spec/formatters/base_spec.rb
|
96
|
-
- spec/formatters/default_spec.rb
|
97
|
-
- spec/
|
98
|
-
- spec/note_spec.rb
|
99
|
-
- spec/scanner_spec.rb
|
66
|
+
- spec/fixtures/sample
|
67
|
+
- spec/lib/formatter_spec.rb
|
68
|
+
- spec/lib/formatters/base_spec.rb
|
69
|
+
- spec/lib/formatters/default_spec.rb
|
70
|
+
- spec/lib/scanner_spec.rb
|
100
71
|
- spec/spec_helper.rb
|
72
|
+
- spec/support/data_support.rb
|
73
|
+
- spec/support/std_support.rb
|
101
74
|
has_rdoc:
|
data/spec/formatter_spec.rb
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Lutra::Formatter do
|
4
|
-
subject { described_class }
|
5
|
-
|
6
|
-
context ".new" do
|
7
|
-
it "have one formatter" do
|
8
|
-
expect(subject.new.formatters.size).to eq(1)
|
9
|
-
end
|
10
|
-
|
11
|
-
it "have default formatter" do
|
12
|
-
expect(subject.new.formatters.first[:name]).to eq(:default)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
context "#add" do
|
17
|
-
it "adds new formatter" do
|
18
|
-
expect(subject.new.add(:new, :n, Lutra::Formatters::Default).size).to eq(2)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
context "#get" do
|
23
|
-
subject { described_class.new }
|
24
|
-
|
25
|
-
it "finds formatter by name" do
|
26
|
-
expect(subject.get(:default)[:name]).to eq(:default)
|
27
|
-
end
|
28
|
-
|
29
|
-
it "finds formatter short name" do
|
30
|
-
expect(subject.get(:d)[:name]).to eq(:default)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
context "#set" do
|
35
|
-
subject { described_class.new }
|
36
|
-
|
37
|
-
it "sets default formatter" do
|
38
|
-
subject.set(:default)
|
39
|
-
expect(subject.current).to eq(:default)
|
40
|
-
end
|
41
|
-
|
42
|
-
it "raise error when formatter dont exist" do
|
43
|
-
expect {
|
44
|
-
subject.set(:poke)
|
45
|
-
}.to raise_error(Lutra::FormatterNotFound)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
it "#print"
|
50
|
-
end
|
data/spec/lutra_spec.rb
DELETED
data/spec/note_spec.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Lutra::Note do
|
4
|
-
subject do
|
5
|
-
described_class.new('X', 'text', 1, 'ex.rb')
|
6
|
-
end
|
7
|
-
|
8
|
-
it "#tag" do
|
9
|
-
expect(subject.tag).to eq 'X'
|
10
|
-
end
|
11
|
-
|
12
|
-
it "#line" do
|
13
|
-
expect(subject.line).to eq 1
|
14
|
-
end
|
15
|
-
|
16
|
-
it "#file" do
|
17
|
-
expect(subject.file).to eq 'ex.rb'
|
18
|
-
end
|
19
|
-
|
20
|
-
it "#text" do
|
21
|
-
expect(subject.text).to eq 'text'
|
22
|
-
end
|
23
|
-
end
|
data/spec/scanner_spec.rb
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Lutra::Scanner do
|
4
|
-
subject { described_class }
|
5
|
-
|
6
|
-
context ".new" do
|
7
|
-
it "with default tags" do
|
8
|
-
expect(subject.new.tags).to eq ['TODO', 'FIXME', 'OPTIMIZE']
|
9
|
-
end
|
10
|
-
|
11
|
-
it "with custom tags" do
|
12
|
-
expect(subject.new(['X']).tags).to eq ['X']
|
13
|
-
end
|
14
|
-
|
15
|
-
it "with default comments" do
|
16
|
-
expect(subject.new.comments).to eq ["#", "%", ";", "//", "--"]
|
17
|
-
end
|
18
|
-
|
19
|
-
it "with custom comments" do
|
20
|
-
expect(subject.new(['X'], ['#']).comments).to eq ["#"]
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
context "#scan_file" do
|
25
|
-
let(:notes) do
|
26
|
-
scanner = subject.new
|
27
|
-
scanner.scan_file("#{File.dirname(__FILE__)}/example")
|
28
|
-
scanner.notes
|
29
|
-
end
|
30
|
-
|
31
|
-
it "have todo, fixme and optimize" do
|
32
|
-
expect(notes.map(&:tag)).to eq ['TODO', 'FIXME', 'OPTIMIZE']
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|