wally 0.0.22 → 0.0.24
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.
- data/.gitignore +1 -0
- data/README.md +25 -12
- data/features/feature_page.feature +61 -0
- data/features/home_page.feature +0 -10
- data/features/search_features.feature +18 -0
- data/features/step_definitions/search_features_steps.rb +4 -0
- data/lib/wally/application.rb +14 -0
- data/lib/wally/public/skin.css +4 -0
- data/lib/wally/version.rb +1 -1
- data/lib/wally/views/progress.haml +3 -3
- data/lib/wally/views/search.haml +17 -14
- data/spec/wally/search_features_spec.rb +6 -6
- data/wally.gemspec +1 -0
- metadata +39 -26
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -1,18 +1,31 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# Wally
|
2
|
+
Wally is a web-based Cucumber viewer and navigator.
|
3
3
|
|
4
|
-
|
5
|
-
|
4
|
+
## About
|
5
|
+
The first cut of a feature is collabatively written; but it then seems to become the property of developers, who commit it to a version control system.
|
6
6
|
|
7
|
-
|
8
|
-
-------------------------
|
7
|
+
The product owner or business analyst usually does not want to use an IDE or VCS client to view requiements. They also want to search or group features and scenarios.
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
* Tags can be made more useful - Eg, cuts of all tags marked '@touch'
|
13
|
-
* I can't hyperlink my step definitions
|
9
|
+
## What's wrong with Relish?
|
10
|
+
Many of the ideas have been borrowed from Matt Wynne's Relish product, but we;
|
14
11
|
|
15
|
-
|
16
|
-
|
12
|
+
### Didn't want
|
13
|
+
* To sign-in
|
17
14
|
|
15
|
+
### Wanted to
|
16
|
+
* Use it through mobile devices
|
17
|
+
* Easily group features and scenarios by tags
|
18
|
+
* Count features and tags
|
19
|
+
* Include a project progress bar (based on tags)
|
20
|
+
|
21
|
+
### Installation
|
22
|
+
* Install [mongodb](http://www.mongodb.org/display/DOCS/Quickstart "mongodb") (> v. 2.0.0) and ensure it is running
|
23
|
+
* gem install wally
|
24
|
+
* wally server
|
25
|
+
* http://localhost:4567/
|
26
|
+
* create a '.wally' file and enter any authentication text you like
|
27
|
+
* wally push http://localhost:4567/ feature_dir
|
28
|
+
|
29
|
+
|
30
|
+
## Wally?
|
18
31
|
If you walk in to a British fish shop and ask for a wally you'll receive a [pickled gherkin](https://github.com/cucumber/cucumber/wiki/Gherkin).
|
@@ -0,0 +1,61 @@
|
|
1
|
+
Feature: Feature Page
|
2
|
+
In order to view a feature and its intent
|
3
|
+
As a stakeholder
|
4
|
+
I want a page that displays the feature's name,
|
5
|
+
free-form narrative and scenario titles
|
6
|
+
|
7
|
+
Scenario: Feature Content
|
8
|
+
Given a feature file named "sample.feature" with the contents:
|
9
|
+
"""
|
10
|
+
Feature: Sample Feature
|
11
|
+
In order to get some value
|
12
|
+
As a person
|
13
|
+
I want to create value
|
14
|
+
"""
|
15
|
+
When I visit the sample feature page
|
16
|
+
Then I should see the feature free-form narrative
|
17
|
+
|
18
|
+
Scenario: View Scenario Links
|
19
|
+
Given a feature file named "sample.feature" with the contents:
|
20
|
+
"""
|
21
|
+
Feature: Sample Feature
|
22
|
+
In order to get some value
|
23
|
+
As a person
|
24
|
+
I want to create value
|
25
|
+
|
26
|
+
Scenario: Sample Aidy
|
27
|
+
Given my name is "Aidy"
|
28
|
+
When I drink alcohol
|
29
|
+
Then I go nuts
|
30
|
+
|
31
|
+
Scenario: Sample Andrew
|
32
|
+
Given my name is 'Andrew'
|
33
|
+
When I drink alcohol
|
34
|
+
Then I go happy
|
35
|
+
"""
|
36
|
+
When I visit the sample feature page
|
37
|
+
Then I should see Scenario headers as links
|
38
|
+
|
39
|
+
Scenario: Sort Scenario Links in Alphabetical Order
|
40
|
+
Given a feature file named "sample.feature" with the contents:
|
41
|
+
"""
|
42
|
+
Feature: Sample Feature
|
43
|
+
Scenario: V
|
44
|
+
Scenario: C
|
45
|
+
Scenario: I
|
46
|
+
Scenario: N
|
47
|
+
"""
|
48
|
+
When I visit the sample feature page
|
49
|
+
Then the scenario links are sorted
|
50
|
+
|
51
|
+
Scenario: View Scenario Tags - Feature Page
|
52
|
+
Given a feature file named "sample.feature" with the contents:
|
53
|
+
"""
|
54
|
+
Feature: Sample Feature
|
55
|
+
|
56
|
+
@tag1 @tag2
|
57
|
+
Scenario: Sample Aidy
|
58
|
+
"""
|
59
|
+
When I visit the sample feature page
|
60
|
+
Then I should see "tag1"
|
61
|
+
And I should see "tag2"
|
data/features/home_page.feature
CHANGED
@@ -34,15 +34,5 @@ Feature: Home Page
|
|
34
34
|
When I visit the sample feature page
|
35
35
|
Then I should see "sample_tag"
|
36
36
|
|
37
|
-
Scenario: Feature Content
|
38
|
-
Given a feature file named "sample.feature" with the contents:
|
39
|
-
"""
|
40
|
-
Feature: Sample Feature
|
41
|
-
In order to get some value
|
42
|
-
As a person
|
43
|
-
I want to create value
|
44
|
-
"""
|
45
|
-
When I visit the sample feature page
|
46
|
-
Then I should see the feature free-form narrative
|
47
37
|
|
48
38
|
|
@@ -75,3 +75,21 @@ Feature: Search features
|
|
75
75
|
When I search for "Batman"
|
76
76
|
Then I should see "feature_tag" in the search results
|
77
77
|
And I should see "scenario_tag" in the search results
|
78
|
+
|
79
|
+
Scenario: Higlighted search result
|
80
|
+
Given a feature file named "sample.feature" with the contents:
|
81
|
+
"""
|
82
|
+
@feature_tag
|
83
|
+
Feature: Some long WORD feature word name
|
84
|
+
Scenario: Some long WORD scenario word name
|
85
|
+
"""
|
86
|
+
And I am on the search page
|
87
|
+
When I search for "word"
|
88
|
+
Then I should see the html:
|
89
|
+
"""
|
90
|
+
Some long <span class="search-result">WORD</span> feature <span class="search-result">word</span> name
|
91
|
+
"""
|
92
|
+
And I should see the html:
|
93
|
+
"""
|
94
|
+
Some long <span class="search-result">WORD</span> scenario <span class="search-result">word</span> name
|
95
|
+
"""
|
data/lib/wally/application.rb
CHANGED
@@ -34,6 +34,20 @@ def scenario_count
|
|
34
34
|
lists_features.features.to_s.scan(/scenario/).length
|
35
35
|
end
|
36
36
|
|
37
|
+
def highlighted_search_result_blurb search_result
|
38
|
+
offset = 0
|
39
|
+
highlighted = search_result.object.text
|
40
|
+
span_start = "<span class=\"search-result\">"
|
41
|
+
span_end = "</span>"
|
42
|
+
search_result.matches.each do |match|
|
43
|
+
highlighted.insert(match.index + offset, span_start)
|
44
|
+
offset += span_start.length
|
45
|
+
highlighted.insert(match.index + match.text.length + offset, span_end)
|
46
|
+
offset += span_end.length
|
47
|
+
end
|
48
|
+
highlighted
|
49
|
+
end
|
50
|
+
|
37
51
|
put '/features/?' do
|
38
52
|
if File.exist?(".wally") && params[:authentication_code] == File.read(".wally").strip
|
39
53
|
Wally::Feature.delete_all
|
data/lib/wally/public/skin.css
CHANGED
data/lib/wally/version.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
%h2
|
2
2
|
Progress
|
3
3
|
- #{@scenario_count}
|
4
|
-
- if
|
4
|
+
- if tag_count
|
5
5
|
%p
|
6
6
|
This project has #{@scenario_count} scenarios, of which :-
|
7
7
|
%ul{:class => 'chartlist'}
|
8
|
-
-
|
8
|
+
- tag_count.each do |tag, count|
|
9
9
|
- ratio = (count.to_f / @scenario_count) * 100
|
10
10
|
%li
|
11
11
|
%a{:href => "/search?q=#{tag}"}
|
@@ -13,4 +13,4 @@
|
|
13
13
|
%span{:class => "count #{tag}"}
|
14
14
|
= ratio.ceil
|
15
15
|
%span{:class => 'index', :style => "width: #{ratio.ceil}%"}
|
16
|
-
= ratio
|
16
|
+
= ratio
|
data/lib/wally/views/search.haml
CHANGED
@@ -8,23 +8,26 @@
|
|
8
8
|
%a{:href => "/search?q=#{@search_results.suggestion}"}
|
9
9
|
= @search_results.suggestion
|
10
10
|
%ul
|
11
|
-
- @search_results.items.map {|i| i.feature["id"] }.uniq.each do |current_feature_id|
|
12
|
-
- root_search_result = @search_results.items.find { |r| r.feature["id"] == current_feature_id }
|
11
|
+
- @search_results.items.map {|i| i.object.feature["id"] }.uniq.each do |current_feature_id|
|
12
|
+
- root_search_result = @search_results.items.find { |r| r.object.feature["id"] == current_feature_id }
|
13
13
|
%li
|
14
|
-
%a{:href => "/features/#{root_search_result.feature["id"]}"}
|
15
|
-
= root_search_result.feature["name"]
|
16
|
-
|
17
|
-
|
18
|
-
|
14
|
+
%a{:href => "/features/#{root_search_result.object.feature["id"]}"}
|
15
|
+
= root_search_result.object.feature["name"]
|
16
|
+
%p
|
17
|
+
!= highlighted_search_result_blurb root_search_result
|
18
|
+
- if root_search_result.object.feature["tags"]
|
19
|
+
= haml :tag_links, {:locals => {:tags => root_search_result.object.feature["tags"]}, :layout => false}
|
19
20
|
%ul
|
20
|
-
- @search_results.items.select { |r| r.feature["id"] == current_feature_id }.each do |search_result|
|
21
|
-
- if search_result.scenario && search_result.scenario["id"]
|
21
|
+
- @search_results.items.select { |r| r.object.feature["id"] == current_feature_id }.each do |search_result|
|
22
|
+
- if search_result.object.scenario && search_result.object.scenario["id"]
|
22
23
|
%li
|
23
|
-
%a{:href => "/features/#{search_result.scenario["id"].gsub(";", "/scenario/")}"}
|
24
|
-
= search_result.scenario["name"]
|
25
|
-
|
26
|
-
|
27
|
-
|
24
|
+
%a{:href => "/features/#{search_result.object.scenario["id"].gsub(";", "/scenario/")}"}
|
25
|
+
= search_result.object.scenario["name"]
|
26
|
+
%p
|
27
|
+
!= highlighted_search_result_blurb(search_result)
|
28
|
+
- if search_result.object.scenario["tags"]
|
29
|
+
= haml :tag_links, {:locals => {:tags => search_result.object.scenario["tags"]}, :layout => false}
|
30
|
+
- if @search_results.items.empty?
|
28
31
|
%p{:class => 'alert-message error'}
|
29
32
|
Where's Wally? This search returned no results.
|
30
33
|
|
@@ -23,14 +23,14 @@ module Wally
|
|
23
23
|
|
24
24
|
results = SearchFeatures.new(lists_features).find(:query => "Meh")
|
25
25
|
results.items.size.should == 1
|
26
|
-
results.items.first.feature["name"].should == "Meh"
|
26
|
+
results.items.first.object.feature["name"].should == "Meh"
|
27
27
|
end
|
28
28
|
|
29
29
|
it "finds features by narrative" do
|
30
30
|
create_feature("sample1.feature", "Feature: bla\nIn order to bananas")
|
31
31
|
results = SearchFeatures.new(lists_features).find(:query => "bananas")
|
32
32
|
results.items.size.should == 1
|
33
|
-
results.items.first.feature["name"].should == "bla"
|
33
|
+
results.items.first.object.feature["name"].should == "bla"
|
34
34
|
end
|
35
35
|
|
36
36
|
it "has a suggestion" do
|
@@ -61,13 +61,13 @@ module Wally
|
|
61
61
|
it "finds scenarios containing text" do
|
62
62
|
results = SearchFeatures.new(lists_features).find(:query => "MATCHED")
|
63
63
|
results.items.size.should == 1
|
64
|
-
results.items.first.scenario["name"].should == "Matched Scenario"
|
64
|
+
results.items.first.object.scenario["name"].should == "Matched Scenario"
|
65
65
|
end
|
66
66
|
|
67
67
|
it "finds scenario steps" do
|
68
68
|
results = SearchFeatures.new(lists_features).find(:query => "DOUGHNUTS")
|
69
69
|
results.items.size.should == 1
|
70
|
-
results.items.first.scenario["name"].should == "Matched Scenario"
|
70
|
+
results.items.first.object.scenario["name"].should == "Matched Scenario"
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
@@ -75,13 +75,13 @@ module Wally
|
|
75
75
|
it "finds features by tag" do
|
76
76
|
create_feature("example-feature.feature", "@tag_name\nFeature: Example Feature")
|
77
77
|
results = SearchFeatures.new(lists_features).find(:query => "@tag_NAME")
|
78
|
-
results.items.first.feature["name"].should == "Example Feature"
|
78
|
+
results.items.first.object.feature["name"].should == "Example Feature"
|
79
79
|
end
|
80
80
|
|
81
81
|
it "finds scenarios by tag" do
|
82
82
|
create_feature("example-feature.feature", "Feature: Example Feature\n@scenario_tag\nScenario: Example Scenario")
|
83
83
|
results = SearchFeatures.new(lists_features).find(:query => "@scenario_TAG")
|
84
|
-
results.items.first.scenario["name"].should == "Example Scenario"
|
84
|
+
results.items.first.object.scenario["name"].should == "Example Scenario"
|
85
85
|
end
|
86
86
|
end
|
87
87
|
end
|
data/wally.gemspec
CHANGED
@@ -25,6 +25,7 @@ Gem::Specification.new do |s|
|
|
25
25
|
s.add_runtime_dependency "komainu"
|
26
26
|
s.add_runtime_dependency "mongoid"
|
27
27
|
s.add_runtime_dependency "bson_ext"
|
28
|
+
s.add_runtime_dependency "rest-client"
|
28
29
|
|
29
30
|
s.add_development_dependency "cucumber"
|
30
31
|
s.add_development_dependency "capybara"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wally
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.24
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-
|
12
|
+
date: 2011-12-02 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: sinatra
|
16
|
-
requirement: &
|
16
|
+
requirement: &70108116103100 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70108116103100
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: haml
|
27
|
-
requirement: &
|
27
|
+
requirement: &70108116102080 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70108116102080
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: rdiscount
|
38
|
-
requirement: &
|
38
|
+
requirement: &70108116101440 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70108116101440
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: gherkin
|
49
|
-
requirement: &
|
49
|
+
requirement: &70108116100100 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70108116100100
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: komainu
|
60
|
-
requirement: &
|
60
|
+
requirement: &70108116098780 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ! '>='
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: '0'
|
66
66
|
type: :runtime
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *70108116098780
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: mongoid
|
71
|
-
requirement: &
|
71
|
+
requirement: &70108116096040 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :runtime
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *70108116096040
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: bson_ext
|
82
|
-
requirement: &
|
82
|
+
requirement: &70108116095560 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ! '>='
|
@@ -87,10 +87,21 @@ dependencies:
|
|
87
87
|
version: '0'
|
88
88
|
type: :runtime
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *70108116095560
|
91
|
+
- !ruby/object:Gem::Dependency
|
92
|
+
name: rest-client
|
93
|
+
requirement: &70108116095100 !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ! '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
type: :runtime
|
100
|
+
prerelease: false
|
101
|
+
version_requirements: *70108116095100
|
91
102
|
- !ruby/object:Gem::Dependency
|
92
103
|
name: cucumber
|
93
|
-
requirement: &
|
104
|
+
requirement: &70108116094600 !ruby/object:Gem::Requirement
|
94
105
|
none: false
|
95
106
|
requirements:
|
96
107
|
- - ! '>='
|
@@ -98,10 +109,10 @@ dependencies:
|
|
98
109
|
version: '0'
|
99
110
|
type: :development
|
100
111
|
prerelease: false
|
101
|
-
version_requirements: *
|
112
|
+
version_requirements: *70108116094600
|
102
113
|
- !ruby/object:Gem::Dependency
|
103
114
|
name: capybara
|
104
|
-
requirement: &
|
115
|
+
requirement: &70108116093920 !ruby/object:Gem::Requirement
|
105
116
|
none: false
|
106
117
|
requirements:
|
107
118
|
- - ! '>='
|
@@ -109,10 +120,10 @@ dependencies:
|
|
109
120
|
version: '0'
|
110
121
|
type: :development
|
111
122
|
prerelease: false
|
112
|
-
version_requirements: *
|
123
|
+
version_requirements: *70108116093920
|
113
124
|
- !ruby/object:Gem::Dependency
|
114
125
|
name: rspec
|
115
|
-
requirement: &
|
126
|
+
requirement: &70108116093320 !ruby/object:Gem::Requirement
|
116
127
|
none: false
|
117
128
|
requirements:
|
118
129
|
- - ! '>='
|
@@ -120,10 +131,10 @@ dependencies:
|
|
120
131
|
version: '0'
|
121
132
|
type: :development
|
122
133
|
prerelease: false
|
123
|
-
version_requirements: *
|
134
|
+
version_requirements: *70108116093320
|
124
135
|
- !ruby/object:Gem::Dependency
|
125
136
|
name: fakefs
|
126
|
-
requirement: &
|
137
|
+
requirement: &70108116086420 !ruby/object:Gem::Requirement
|
127
138
|
none: false
|
128
139
|
requirements:
|
129
140
|
- - ! '>='
|
@@ -131,10 +142,10 @@ dependencies:
|
|
131
142
|
version: '0'
|
132
143
|
type: :development
|
133
144
|
prerelease: false
|
134
|
-
version_requirements: *
|
145
|
+
version_requirements: *70108116086420
|
135
146
|
- !ruby/object:Gem::Dependency
|
136
147
|
name: launchy
|
137
|
-
requirement: &
|
148
|
+
requirement: &70108116085900 !ruby/object:Gem::Requirement
|
138
149
|
none: false
|
139
150
|
requirements:
|
140
151
|
- - ! '>='
|
@@ -142,7 +153,7 @@ dependencies:
|
|
142
153
|
version: '0'
|
143
154
|
type: :development
|
144
155
|
prerelease: false
|
145
|
-
version_requirements: *
|
156
|
+
version_requirements: *70108116085900
|
146
157
|
description: ''
|
147
158
|
email:
|
148
159
|
- andrew.vos@gmail.com
|
@@ -164,6 +175,7 @@ files:
|
|
164
175
|
- example-features/generic/multiple-scenarios.feature
|
165
176
|
- example-features/too-many-wip-tags/too-many-wip-tags.feature
|
166
177
|
- features/counts.feature
|
178
|
+
- features/feature_page.feature
|
167
179
|
- features/home_page.feature
|
168
180
|
- features/list_tags.feature
|
169
181
|
- features/notifications.feature
|
@@ -226,6 +238,7 @@ specification_version: 3
|
|
226
238
|
summary: ''
|
227
239
|
test_files:
|
228
240
|
- features/counts.feature
|
241
|
+
- features/feature_page.feature
|
229
242
|
- features/home_page.feature
|
230
243
|
- features/list_tags.feature
|
231
244
|
- features/notifications.feature
|