├── .gitignore
├── Commands
└── Switch to New Canonoical Fork.tmCommand
├── MIT-LICENSE.txt
├── Preferences
├── Comments.tmPreferences
├── Cucumber Plain Text Feature Completions.tmPreferences
├── Symbol list: Scenario.tmPreferences
├── Symbol list: Steps with String.tmPreferences
└── Symbol list: Steps.tmPreferences
├── README.textile
├── Support
├── Rakefile
├── bundle_tasks
│ └── syntax.rake
├── fixtures
│ ├── example_failing_spec.rb
│ ├── example_passing_spec.rb
│ └── features
│ │ ├── additional_basic.feature
│ │ ├── basic.feature
│ │ ├── feature1
│ │ ├── foo.feature
│ │ └── step_definitions
│ │ │ └── foo_steps.rb
│ │ ├── non_standard.feature
│ │ ├── non_standard_dir
│ │ ├── runners
│ │ │ └── non_standard.rb
│ │ └── step_definitions
│ │ │ └── non_standard_steps.rb
│ │ └── step_definitions
│ │ ├── additional_basic_steps.rb
│ │ ├── basic_steps.rb
│ │ ├── global_steps.rb
│ │ └── unconventional_steps.rb
├── lib
│ └── cucumber
│ │ ├── mate.rb
│ │ └── mate
│ │ ├── feature_helper.rb
│ │ ├── files.rb
│ │ ├── files
│ │ ├── base.rb
│ │ ├── feature_file.rb
│ │ ├── step_detector.rb
│ │ └── steps_file.rb
│ │ ├── path_helper.rb
│ │ ├── runner.rb
│ │ ├── table_aligner.rb
│ │ └── text_mate_helper.rb
└── spec
│ ├── cucumber
│ └── mate
│ │ ├── feature_helper_spec.rb
│ │ ├── files
│ │ ├── base_spec.rb
│ │ ├── feature_file_spec.rb
│ │ └── steps_file_spec.rb
│ │ ├── runner_spec.rb
│ │ ├── table_aligner_spec.rb
│ │ └── text_mate_helper_spec.rb
│ ├── spec.opts
│ └── spec_helper.rb
├── Syntaxes
├── Cucumber Plain Text Feature.tmLanguage
├── Cucumber Steps.tmLanguage
└── plaintext_template.erb
└── info.plist
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | *.swp
3 | coverage
4 |
--------------------------------------------------------------------------------
/Commands/Switch to New Canonoical Fork.tmCommand:
--------------------------------------------------------------------------------
1 |
2 |
3 |
25 | cd ~/Library/Application\ Support/TextMate/Bundles 26 | rm -rf Cucumber.tmbundle 27 | git clone git://github.com/cucumber/cucumber-tmbundle.git Cucumber.tmbundle 28 | osascript -e 'tell app "TextMate" to reload bundles' 29 |30 | 31 | -------------------------------------------------------------------------------- /Support/Rakefile: -------------------------------------------------------------------------------- 1 | $:.unshift(File.dirname(__FILE__) + '/../../rspec/lib') 2 | require 'rubygems' 3 | require 'spec/rake/spectask' 4 | 5 | desc "Run all specs" 6 | Spec::Rake::SpecTask.new do |t| 7 | t.rcov = true 8 | t.spec_opts = ['--colour', '--diff'] 9 | t.rcov_opts = ['--exclude', 'rspec\/plugins,rspec\/lib\/spec,spec\/spec,fixtures,bin\/spec'] 10 | end 11 | 12 | 13 | Dir['bundle_tasks/**/*.rake'].each { |rake| load rake } -------------------------------------------------------------------------------- /Support/bundle_tasks/syntax.rake: -------------------------------------------------------------------------------- 1 | class SyntaxGenerator 2 | def generate 3 | require 'erb' 4 | require 'gherkin/i18n' 5 | 6 | template = ERB.new(IO.read(File.dirname(__FILE__) + '/../../Syntaxes/plaintext_template.erb')) 7 | syntax = template.result(binding) 8 | 9 | syntax_file = File.dirname(__FILE__) + '/../../Syntaxes/Cucumber Plain Text Feature.tmLanguage' 10 | File.open(syntax_file, "w") do |io| 11 | io.write(syntax) 12 | end 13 | end 14 | 15 | def escape(s) 16 | s.gsub(/'/, "\\\\'").gsub(/\*/, "\\\\*") 17 | end 18 | end 19 | 20 | desc 'Generates the plain text syntax file for all languages supported by Cucumber' 21 | task :generate do 22 | SyntaxGenerator.new.generate 23 | end 24 | -------------------------------------------------------------------------------- /Support/fixtures/example_failing_spec.rb: -------------------------------------------------------------------------------- 1 | describe "An example failing spec" do 2 | it "should fail" do 3 | true.should be_false 4 | end 5 | 6 | it "should also fail" do 7 | false.should be_true 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /Support/fixtures/example_passing_spec.rb: -------------------------------------------------------------------------------- 1 | describe "An example failing spec" do 2 | it "should pass" do 3 | true.should be_true 4 | end 5 | 6 | it "should pass too" do 7 | false.should be_false 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /Support/fixtures/features/additional_basic.feature: -------------------------------------------------------------------------------- 1 | Feature: Additional Basic 2 | 3 | As a person interested in something 4 | I want to look for something 5 | So that I can do something 6 | 7 | Scenario: do some cool thingy yeah man 8 | Given Basic step (given) 9 | And another basic step 10 | And global step 11 | And unimplemented step 12 | 13 | When Basic when 14 | 15 | Then Basic then 16 | 17 | Scenario: do something else 18 | Given Basic regexp (given) 19 | 20 | When Basic when 21 | 22 | Then Basic then 23 | -------------------------------------------------------------------------------- /Support/fixtures/features/basic.feature: -------------------------------------------------------------------------------- 1 | Feature: Basic 2 | 3 | As a person interested in something 4 | I want to look for something 5 | So that I can do something 6 | 7 | Scenario: do some cool thingy yeah man 8 | Given Basic step (given) 9 | And another basic step 10 | And global step 11 | And unimplemented step 12 | 13 | When Basic when 14 | 15 | Then Basic then 16 | 17 | Scenario: do something else 18 | Given Basic regexp (given) 19 | 20 | When Basic when 21 | 22 | Then Basic then 23 | -------------------------------------------------------------------------------- /Support/fixtures/features/feature1/foo.feature: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bmabey/cucumber-tmbundle/bb89925f54372282e6f7500cc53b746e44dbc31a/Support/fixtures/features/feature1/foo.feature -------------------------------------------------------------------------------- /Support/fixtures/features/feature1/step_definitions/foo_steps.rb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bmabey/cucumber-tmbundle/bb89925f54372282e6f7500cc53b746e44dbc31a/Support/fixtures/features/feature1/step_definitions/foo_steps.rb -------------------------------------------------------------------------------- /Support/fixtures/features/non_standard.feature: -------------------------------------------------------------------------------- 1 | 2 | # rake some_defined_task_in_feature:file 3 | # profile some_defined_profile_in_feature 4 | 5 | Feature: some feature 6 | 7 | As a role 8 | I want feature 9 | So that value 10 | -------------------------------------------------------------------------------- /Support/fixtures/features/non_standard_dir/runners/non_standard.rb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bmabey/cucumber-tmbundle/bb89925f54372282e6f7500cc53b746e44dbc31a/Support/fixtures/features/non_standard_dir/runners/non_standard.rb -------------------------------------------------------------------------------- /Support/fixtures/features/non_standard_dir/step_definitions/non_standard_steps.rb: -------------------------------------------------------------------------------- 1 | Given "non standard step" do 2 | 3 | end -------------------------------------------------------------------------------- /Support/fixtures/features/step_definitions/additional_basic_steps.rb: -------------------------------------------------------------------------------- 1 | Given "additional basic step" do 2 | 3 | end 4 | -------------------------------------------------------------------------------- /Support/fixtures/features/step_definitions/basic_steps.rb: -------------------------------------------------------------------------------- 1 | Given "Basic step (given)" do 2 | Foo.should_not_error 3 | end 4 | 5 | Given "another basic step" do # a comment 6 | 7 | end 8 | 9 | Given %r{Basic regexp (.*) with multiple (.*) groups} do |first, second| 10 | 11 | end 12 | 13 | Given %r{Some quoted regexp "(.*)" and '(.*)'} do |first, second| # a comment 14 | 15 | end 16 | 17 | Given /classic regexp/ do # a comment 18 | 19 | end 20 | 21 | When "Basic when" do 22 | 23 | end 24 | 25 | Then 'Basic then' do 26 | 27 | end 28 | -------------------------------------------------------------------------------- /Support/fixtures/features/step_definitions/global_steps.rb: -------------------------------------------------------------------------------- 1 | Given "global step" do 2 | Foo.should_not_error 3 | end 4 | 5 | Given "another global step" do 6 | 7 | end 8 | -------------------------------------------------------------------------------- /Support/fixtures/features/step_definitions/unconventional_steps.rb: -------------------------------------------------------------------------------- 1 | Given("one liner with comment") { one; liner } # boo 2 | 3 | Given ("one liner with trailing space") { one; line; } 4 | 5 | Given("one liner with no trailing space") { one; liner} 6 | 7 | Given ("braces with a comment") { |boo| # yah! 8 | } 9 | 10 | Given("braces with a trailing space") { |boo| 11 | } 12 | 13 | Given("braces no trailing space") { |boo| 14 | yah! 15 | } 16 | -------------------------------------------------------------------------------- /Support/lib/cucumber/mate.rb: -------------------------------------------------------------------------------- 1 | # This is based on the official RSpec tm-bundle 2 | require 'rubygems' 3 | 4 | if ENV['TM_PROJECT_DIRECTORY'] 5 | rspec_rails_plugin = File.join(ENV['TM_PROJECT_DIRECTORY'],'vendor','plugins','rspec','lib') 6 | rspec_merb_gem = (merb_dir = (Dir["#{ENV['TM_PROJECT_DIRECTORY']}/gems/gems/rspec*"].first || '')) && File.join(merb_dir, "lib") 7 | 8 | if File.directory?(rspec_rails_plugin) 9 | $LOAD_PATH.unshift(rspec_rails_plugin) 10 | elsif File.directory?(rspec_merb_gem) 11 | $LOAD_PATH.unshift(rspec_merb_gem) 12 | elsif ENV['TM_RSPEC_HOME'] 13 | rspec_lib = File.join(ENV['TM_RSPEC_HOME'], 'lib') 14 | unless File.directory?(rspec_lib) 15 | raise "TM_RSPEC_HOME points to a bad location: #{ENV['TM_RSPEC_HOME']}" 16 | end 17 | $LOAD_PATH.unshift(rspec_lib) 18 | end 19 | end 20 | require 'spec' 21 | 22 | $LOAD_PATH.unshift(File.expand_path(File.join(File.dirname(__FILE__), '..'))) 23 | require "cucumber/mate/feature_helper" 24 | require "cucumber/mate/runner" -------------------------------------------------------------------------------- /Support/lib/cucumber/mate/feature_helper.rb: -------------------------------------------------------------------------------- 1 | require File.join(File.dirname(__FILE__), %w[.. mate]) 2 | require File.join(File.dirname(__FILE__), %w[path_helper]) 3 | require File.join(File.dirname(__FILE__), %w[text_mate_helper]) 4 | require File.join(File.dirname(__FILE__), 'files') 5 | 6 | module Cucumber 7 | module Mate 8 | 9 | class FeatureHelper 10 | include PathHelper 11 | 12 | def initialize(full_file_path) 13 | @full_file_path = full_file_path 14 | @file = Files::Base.create_from_file_path(full_file_path) 15 | end 16 | 17 | def run_feature 18 | argv = [] 19 | argv << "FEATURE=#{@file.feature_file_path}" 20 | unless (cucumber_opts = ENV['TM_CUCUMBER_OPTS']) 21 | cucumber_opts = "" 22 | cucumber_opts << '--format' 23 | cucumber_opts << '=html' 24 | end 25 | argv << "CUCUMBER_OPTS=#{cucumber_opts}" 26 | 27 | in_project_directory do 28 | puts `rake features:standard #{argv.join(' ')}` 29 | end 30 | end 31 | 32 | def goto_alternate_file 33 | goto_or_create_file(@file.alternate_file_path) 34 | end 35 | 36 | def choose_alternate_file 37 | alternate_files_and_names = @file.alternate_files_and_names 38 | if (choice = TextMateHelper.display_select_list(alternate_files_and_names.collect{|h| h[:name] || h[:file_path]})) 39 | goto_or_create_file(alternate_files_and_names[choice][:file_path]) 40 | end 41 | end 42 | 43 | def goto_current_step(line_number) 44 | return unless @file.feature_file? && step_info = @file.step_information_for_line(line_number) 45 | if (step_location = @file.location_of_step(step_info)) 46 | TextMateHelper.goto_file(step_location.delete(:file_path), step_location) 47 | else 48 | goto_steps_file_with_new_steps([step_info]) 49 | end 50 | end 51 | 52 | def goto_step_usage(line_number) 53 | 54 | end 55 | 56 | def create_all_undefined_steps 57 | return unless @file.feature_file? && undefined_steps = @file.undefined_steps 58 | goto_steps_file_with_new_steps(undefined_steps) 59 | end 60 | 61 | def autocomplete_step(stdout, current_line) 62 | unless matches = current_line.match(/([\s\t]*(?:given|when|then|and|but)\s+)(.*)/i) 63 | stdout.print current_line 64 | return 65 | end 66 | line_start, step_prefix = matches[1..2] 67 | matching_step_definitions = @file.steps_starting_with(step_prefix) 68 | unless matching_step_definitions && matching_step_definitions.size > 0 69 | stdout.print current_line 70 | return 71 | end 72 | if matching_step_definitions.size > 1 73 | patterns = matching_step_definitions.map { |step| step[:pattern_text] } 74 | if choice = TextMateHelper.display_select_list(patterns) 75 | result = convert_step_definition_regexp_groups_to_snippet_tab_stops(matching_step_definitions[choice]) 76 | stdout.print "#{line_start}#{result}" 77 | return 78 | end 79 | else 80 | result = convert_step_definition_regexp_groups_to_snippet_tab_stops(matching_step_definitions.first) 81 | stdout.print "#{line_start}#{result}" 82 | return 83 | end 84 | stdout.print current_line 85 | end 86 | 87 | protected 88 | def goto_steps_file_with_new_steps(new_steps) 89 | steps_file = Files::StepsFile.new(@file.steps_file_path) 90 | goto_or_create_file(steps_file.full_file_path, 91 | :line => 1, 92 | :column => 1, 93 | :additional_content => Files::StepsFile.create_steps(new_steps, !File.file?(steps_file.full_file_path))) 94 | end 95 | 96 | def request_confirmation_to_create_file(file_path) 97 | TextMateHelper.request_confirmation(:title => "Create new file?", :prompt => "Do you want to create\n#{file_path.gsub(/^(.*?)features/, 'features')}?") 98 | end 99 | 100 | def goto_or_create_file(file_path, options = {}) 101 | options = {:line => 1, :column => 1}.merge(options) 102 | additional_content = options.delete(:additional_content) 103 | 104 | if File.file?(file_path) 105 | TextMateHelper.goto_file(file_path, options) 106 | TextMateHelper.insert_text(additional_content) if additional_content 107 | elsif request_confirmation_to_create_file(file_path) 108 | TextMateHelper.create_and_open_file(file_path) 109 | TextMateHelper.insert_text(default_content(file_path, additional_content)) 110 | end 111 | end 112 | 113 | def silently_create_file(file_path) 114 | TextMateHelper.create_file(file_path) 115 | `echo "#{Files::Base.create_from_file_path(file_path).class.default_content(file_path).gsub('"','\\"')}" > "#{file_path}"` 116 | end 117 | 118 | def default_content(file_path, additional_content) 119 | Files::Base.default_content_for(file_path, additional_content) 120 | end 121 | 122 | def step_regexs 123 | [/^I am on (.+)$/, /I go to (.+)$/, /^I press "(.*)"$/] 124 | end 125 | 126 | def convert_step_definition_regexp_groups_to_snippet_tab_stops(step_def) 127 | tab_stop_count = 1 128 | snippet_text = step_def[:pattern_text] 129 | while snippet_text.match(%r{\(}) 130 | snippet_text.sub!(%r{\(([^)]+)\)}, "${#{tab_stop_count}:\\1}") 131 | tab_stop_count += 1 132 | end 133 | snippet_text 134 | end 135 | end 136 | 137 | end 138 | end 139 | -------------------------------------------------------------------------------- /Support/lib/cucumber/mate/files.rb: -------------------------------------------------------------------------------- 1 | $:.unshift(File.join(File.dirname(__FILE__), 'files')) 2 | require 'base' 3 | require 'feature_file' 4 | require 'steps_file' 5 | require 'step_detector' -------------------------------------------------------------------------------- /Support/lib/cucumber/mate/files/base.rb: -------------------------------------------------------------------------------- 1 | require 'fileutils' 2 | 3 | module Cucumber 4 | module Mate 5 | 6 | module Files 7 | 8 | class InvalidFilePathError < StandardError; end 9 | class Base 10 | attr_accessor :full_file_path 11 | 12 | class << self 13 | def create_from_file_path(file_path) 14 | if klass_from_file_path(file_path) 15 | klass_from_file_path(file_path).new(file_path) 16 | else 17 | raise InvalidFilePathError, "Feature files should have suffix .feature; Step definitions should be _steps.rb" 18 | end 19 | end 20 | 21 | def default_content_for(file_path, additional_content = nil) 22 | klass_from_file_path(file_path).default_content(file_path, additional_content) 23 | end 24 | 25 | def klass_from_file_path(file_path) 26 | case file_path 27 | when /feature$/ then FeatureFile 28 | when /_steps\.rb$/ then StepsFile 29 | end 30 | end 31 | end 32 | 33 | def initialize(full_file_path) 34 | @full_file_path = full_file_path 35 | @options = parse_options 36 | end 37 | 38 | def project_root 39 | @project_root ||= find_project_dir(File.dirname(full_file_path)) 40 | end 41 | 42 | def relative_path 43 | @relative_path ||= full_file_path[project_root.length+1..-1] 44 | end 45 | 46 | def in_project_directory(&block) 47 | result = nil 48 | Dir.chdir(project_root) { result = yield } 49 | result 50 | end 51 | 52 | def default_file_path(kind, name = self.name) 53 | name = @options[kind] if @options[kind] 54 | replacements = { 55 | :steps => "/step_definitions/#{name}_steps.rb", 56 | :feature => "/#{name}.feature" 57 | } 58 | 59 | raise ArgumentError, "passed argument must be one of #{replacements.keys.join(', ')}" unless replacements.has_key?(kind) 60 | full_file_path.gsub(%r<(/#{name}\.(feature|txt))|((/[^/])?(/steps)?/#{name}(_\w*)?\.rb)>, replacements[kind]) 61 | end 62 | 63 | def file_path(kind, name = self.name) 64 | name = @options[kind] if @options[kind] 65 | search_paths = { 66 | :steps => "#{project_root}/features/**/#{name}_steps.rb", 67 | :feature => "#{project_root}/features/**/#{name}.{feature,txt}" 68 | } 69 | 70 | raise ArgumentError, "passed argument must be one of #{search_paths.keys.join(', ')}" unless search_paths.has_key?(kind) 71 | 72 | Dir[search_paths[kind]].first || default_file_path(kind) 73 | end 74 | 75 | def all(kind) 76 | in_project_directory do 77 | case kind.to_sym 78 | when :feature 79 | Dir['features/**/*.feature'].map { |f| FeatureFile.new(File.expand_path(f)) } 80 | when :steps 81 | Dir['features/**/*_steps.rb'].map { |f| StepsFile.new(File.expand_path(f)) } 82 | end 83 | end 84 | end 85 | 86 | def all_path_and_names(kind) 87 | all(kind).map {|file| {:file_path => file.full_file_path, :name => file.name} } 88 | end 89 | 90 | def feature_file_path 91 | file_path(:feature) 92 | end 93 | 94 | def steps_file_path 95 | file_path(:steps) 96 | end 97 | 98 | def name 99 | @name ||= full_file_path.match(%r{/([^/]*)\.\w*$}).captures.first 100 | end 101 | 102 | def feature_file?; false; end 103 | def steps_file?; false; end 104 | 105 | def ==(step_or_feature_file) 106 | step_or_feature_file.is_a?(self.class) && self.full_file_path == step_or_feature_file.full_file_path 107 | end 108 | 109 | private 110 | def parse_options 111 | return {} unless File.file?(full_file_path) 112 | first_line = File.open(full_file_path) {|f| f.readline unless f.eof} || '' 113 | return {} unless first_line.match(/\s*#\s*(.+:.+)/) 114 | $1.split(',').inject({}) do |hash, pair| 115 | k,v = pair.split(':') 116 | hash[k.strip.to_sym] = v.strip if k && v 117 | hash 118 | end 119 | end 120 | 121 | def find_project_dir(current_dir) 122 | return nil unless File.exists?(current_dir) 123 | current_dir = File.expand_path(current_dir) 124 | FileUtils.chdir(current_dir) do 125 | parent_dir = File.expand_path("..") 126 | return nil if parent_dir == current_dir 127 | boot_file = File.join(current_dir, "features") 128 | return File.exists?(boot_file) ? current_dir : find_project_dir(parent_dir) 129 | end 130 | end 131 | 132 | end 133 | 134 | end 135 | 136 | end 137 | end 138 | -------------------------------------------------------------------------------- /Support/lib/cucumber/mate/files/feature_file.rb: -------------------------------------------------------------------------------- 1 | require File.join(File.dirname(__FILE__), %w[.. path_helper]) 2 | module Cucumber 3 | module Mate 4 | 5 | module Files 6 | 7 | class FeatureFile < Base 8 | class << self 9 | include PathHelper 10 | 11 | def default_content(file_path, additional_content = nil) 12 | TextMateHelper.snippet_text_for('Feature') 13 | end 14 | 15 | end 16 | 17 | def feature_file?; true; end 18 | 19 | def alternate_file_path 20 | steps_file_path 21 | end 22 | 23 | def rake_task 24 | content_lines.detect {|line| line =~ /^\s*#\s*rake\s+([\w:]+)/} ? $1 : nil 25 | end 26 | 27 | def profile 28 | content_lines.detect {|line| line =~ /^\s*#\s*profile\s+([\w]+)/} ? $1 : nil 29 | end 30 | 31 | def step_files_and_names 32 | all_path_and_names(:steps) 33 | end 34 | 35 | alias :alternate_files_and_names :step_files_and_names 36 | 37 | # Returns the name of a step at a specific line number 38 | # e.g. if the step on the target line is: Given a logged in user 39 | # then the result would be: { :step_name => "a logged in user" } 40 | def step_information_for_line(line_number) 41 | line_index = line_number.to_i-1 42 | 43 | line_text = content_lines[line_index] 44 | return unless line_text && line_text.strip!.match(/^(given|when|then|and)(.*)/i) 45 | step_type = $1.capitalize 46 | source_step_name = $2.strip 47 | if step_type == "And" 48 | content_lines[0..(line_index - 1)].reverse.detect do |line| 49 | if line.match(/^\s*(given|when|then)(.*)/i) 50 | step_type = $1.capitalize 51 | end 52 | end 53 | end 54 | 55 | return {:step_name => source_step_name, :step_type => step_type} 56 | end 57 | 58 | # Right now will return first matching step 59 | # Ultimately used by TextMateHelper.goto_file 60 | # Returns a hash with keys: :file_path, :line, :pattern, :pattern_text 61 | def location_of_step(step_info) 62 | all_defined_steps.each do |step_def| 63 | if step_def[:pattern].is_a?(Regexp) 64 | pattern = step_def[:pattern] 65 | else 66 | pattern = %r(^#{Regexp.escape(step_def[:pattern].gsub(/\$\w+/, "STRING_MATCHER_TOKEN")).gsub("STRING_MATCHER_TOKEN", "(.+)")}$) 67 | end 68 | return step_def if pattern =~ step_info[:step_name] 69 | end 70 | nil 71 | end 72 | 73 | def steps_starting_with(step_prefix) 74 | step_prefix_regex = /^#{step_prefix}/ 75 | all_defined_steps.select do |step_def| 76 | step_def[:pattern_text] =~ step_prefix_regex 77 | end 78 | end 79 | 80 | def undefined_steps 81 | all_steps_in_file.inject([]) do |undefined_steps, step_info| 82 | unless location_of_step(step_info) || undefined_steps.any?{|s| s[:step_name] == step_info[:step_name] } 83 | undefined_steps << step_info 84 | end 85 | undefined_steps 86 | end 87 | end 88 | 89 | protected 90 | def all_steps_in_file 91 | file_lines = File.read(full_file_path).split("\n").collect{|l| l.strip} 92 | 93 | file_lines.inject([]) do |text_steps, line| 94 | step_type = $1 if line.match(/^(Given|When|Then)\s+/) 95 | text_steps << {:step_type => step_type, :step_name => $2} if line.match(/^(Given|When|Then|And)\s+(.*)$/) 96 | text_steps 97 | end 98 | end 99 | 100 | def content_lines 101 | @content_lines ||= File.read(full_file_path).split("\n") 102 | end 103 | 104 | # Returns an array of hashes, each describing a Given/When/Then step defined in this step file 105 | # Each hash-per-step has the keys: :file_path, :line, :pattern, :pattern_text 106 | def all_defined_steps 107 | @defined_steps ||= step_files_and_names.inject([]) do |mem, step_file_info| 108 | StepsFile.new(step_file_info[:file_path]).step_definitions.each do |step_def| 109 | mem << step_def 110 | end 111 | mem 112 | end 113 | end 114 | end 115 | 116 | end 117 | 118 | end 119 | end 120 | -------------------------------------------------------------------------------- /Support/lib/cucumber/mate/files/step_detector.rb: -------------------------------------------------------------------------------- 1 | module Cucumber 2 | module Mate 3 | 4 | module Files 5 | 6 | class StepDetector 7 | def initialize(path_to_a_feature_file) 8 | @step_files = ( 9 | Dir[File.dirname(path_to_a_feature_file) + "/step_definitions/**/*.rb"] + 10 | Dir[File.dirname(path_to_a_feature_file) + "/**/*_steps.rb"] 11 | ).uniq 12 | end 13 | 14 | # returns [ { :file_path => path, :name => StepFile#name } ] 15 | def step_files_and_names 16 | @step_files.map do |step_file| 17 | { :file_path => File.expand_path(step_file), :name => StepsFile.new(step_file).name } 18 | end 19 | end 20 | end 21 | 22 | end 23 | end 24 | 25 | end 26 | -------------------------------------------------------------------------------- /Support/lib/cucumber/mate/files/steps_file.rb: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | 3 | module Cucumber 4 | module Mate 5 | 6 | module Files 7 | 8 | class StepsFile < Base 9 | class << self 10 | def default_content(file_path, additional_content = create_steps([:step_type => 'Given', :step_name => 'condition'])) 11 | additional_content || "" 12 | end 13 | 14 | def create_steps(steps_to_create, already_included_snippet_selection = true) 15 | sorted_steps = steps_to_create.inject({'Given' => [], 'When' => [], 'Then' => []}) do |steps_so_far, current_step_info| 16 | steps_so_far[current_step_info[:step_type] || 'Then'] << current_step_info[:step_name] 17 | steps_so_far 18 | end 19 | 20 | content = "" 21 | %w(Given When Then).each do |step_type| 22 | sorted_steps[step_type].each do |step_name| 23 | step_name_text = already_included_snippet_selection ? step_name : "${1:#{step_name}}" 24 | content += %Q{ #{step_type} "#{step_name_text}" do\n pending\n end\n \n} 25 | already_included_snippet_selection = true 26 | end 27 | end 28 | content 29 | end 30 | end 31 | 32 | def steps_file?; true; end 33 | 34 | def name 35 | @name ||= super.gsub("_steps", "") 36 | end 37 | 38 | def rake_task 39 | feature_file.rake_task 40 | end 41 | 42 | def profile 43 | feature_file.profile 44 | end 45 | 46 | def alternate_file_path 47 | feature_file_path 48 | end 49 | 50 | def feature_files_and_names 51 | all_path_and_names(:feature) 52 | end 53 | 54 | alias :alternate_files_and_names :feature_files_and_names 55 | 56 | # Returns an array of hashes, each describing a Given/When/Then step defined in this step file 57 | # Each hash-per-step has the keys: :file_path, :line, :pattern, :pattern_text 58 | def step_definitions 59 | if File.file?(full_file_path) 60 | @steps = [] 61 | @file_contents = File.read(full_file_path) 62 | lines = @file_contents.split("\n") 63 | lines.each do |line| 64 | case line 65 | when /\s*(When|Given|Then).+do\s*(\|[^\|]+\|){0,1}\s*(#.+|$)/ 66 | line.gsub!($3, "") if $3 67 | line << "; end" 68 | when /\s*(When|Given|Then)\s*\(.+\)\s*\{\s*.+\s*\}\s*(#.+|$)/ 69 | when /\s*(When|Given|Then)\s*\(.+\)\s*\{\s*(\|[^\|]+\|){0,1}\s*(#.+|$)/ 70 | line.gsub!(/#[^#]+$/, '') if $2 71 | line << "}" 72 | else 73 | line.insert(0, "# ") 74 | end 75 | end 76 | @file_contents = lines * "\n" 77 | instance_eval(@file_contents, full_file_path, 1) 78 | @steps 79 | else 80 | [] 81 | end 82 | end 83 | 84 | protected 85 | # While evaluating step definitions code - This called when a new step has been parse 86 | # We need to save these to be able to match plain text 87 | def add_step(type, pattern) 88 | line_number = caller[1].match(/:(\d+)/).captures.first.to_i 89 | 90 | @steps << {:pattern => pattern, :line => line_number, 91 | :pattern_text => (pattern.is_a?(Regexp) ? pattern.source.gsub('^', '') : pattern), 92 | :file_path => full_file_path} 93 | end 94 | 95 | def steps_for(*args) 96 | yield if block_given? 97 | end 98 | 99 | def feature_file 100 | @feature_file ||= FeatureFile.new(feature_file_path) 101 | end 102 | 103 | def Given(pattern) 104 | add_step('Given', pattern) 105 | end 106 | 107 | def When(pattern) 108 | add_step('When', pattern) 109 | end 110 | 111 | def Then(pattern) 112 | add_step('Then', pattern) 113 | end 114 | 115 | def World(helpers) 116 | end 117 | 118 | def After 119 | end 120 | 121 | def Before 122 | end 123 | 124 | def at_exit 125 | end 126 | end 127 | 128 | end 129 | 130 | end 131 | end 132 | -------------------------------------------------------------------------------- /Support/lib/cucumber/mate/path_helper.rb: -------------------------------------------------------------------------------- 1 | module PathHelper 2 | 3 | def full_project_directory 4 | features_directory = find_project_dir(File.dirname(@full_file_path)) 5 | end 6 | 7 | # Evaluates the block within the full_project_directory 8 | # and returns the result 9 | def in_project_directory(&block) 10 | result = nil 11 | Dir.chdir(full_project_directory) { result = yield } 12 | result 13 | end 14 | 15 | def find_project_dir(current_dir) 16 | return nil unless File.exists?(current_dir) 17 | current_dir = File.expand_path(current_dir) 18 | FileUtils.chdir(current_dir) do 19 | parent_dir = File.expand_path("..") 20 | return nil if parent_dir == current_dir 21 | boot_file = File.join(current_dir, "config", "boot.rb") 22 | return File.exists?(boot_file) ? current_dir : find_project_dir(parent_dir) 23 | end 24 | end 25 | 26 | end 27 | -------------------------------------------------------------------------------- /Support/lib/cucumber/mate/runner.rb: -------------------------------------------------------------------------------- 1 | require File.join(File.dirname(__FILE__), %w[.. mate]) 2 | require File.join(File.dirname(__FILE__), 'files') 3 | 4 | module Cucumber 5 | module Mate 6 | 7 | class Runner 8 | CUCUMBER_BIN = %x{which cucumber}.chomp 9 | RUBY_BIN = ENV['TM_RUBY'] || %x{which ruby}.chomp 10 | RAKE_BIN = %x{which rake}.chomp 11 | 12 | def initialize(output, project_directory, full_file_path, cucumber_bin = nil, cucumber_opts=nil) 13 | @file = Files::Base.create_from_file_path(full_file_path) 14 | @output = output 15 | @project_directory = project_directory 16 | @filename_opts = "" 17 | @cucumber_bin = cucumber_bin || CUCUMBER_BIN 18 | @cucumber_opts = cucumber_opts || "--format=html" 19 | @cucumber_opts << " --profile=#{@file.profile}" if @file.profile 20 | end 21 | 22 | def run_scenario(line_number) 23 | @filename_opts << ":#{line_number}" 24 | run 25 | end 26 | 27 | def run_feature 28 | run 29 | end 30 | 31 | def autoformat_feature 32 | in_project_dir do 33 | Kernel.system("#{cucumber_cmd} --autoformat . #{@file.relative_path}") 34 | end 35 | end 36 | 37 | 38 | protected 39 | 40 | def run 41 | argv = [] 42 | if @file.rake_task 43 | command = RAKE_BIN 44 | argv << "FEATURE=#{@file.full_file_path}" 45 | argv << %Q{CUCUMBER_OPTS="#{@cucumber_opts}"} 46 | else 47 | command = cucumber_cmd 48 | argv << "#{@file.full_file_path}#{@filename_opts}" 49 | argv << @cucumber_opts 50 | end 51 | in_project_dir do 52 | @output << %Q{Running: #{full_command = "#{RUBY_BIN} #{command} #{@file.rake_task} #{argv.join(' ')}"} \n} 53 | @output << Kernel.system(full_command) 54 | end 55 | end 56 | 57 | def cucumber_cmd 58 | File.exists?(script = "#{@project_directory}/script/cucumber") ? script : @cucumber_bin 59 | end 60 | 61 | def in_project_dir(&block) 62 | Dir.chdir(@project_directory, &block) 63 | end 64 | 65 | end 66 | 67 | end 68 | end 69 | -------------------------------------------------------------------------------- /Support/lib/cucumber/mate/table_aligner.rb: -------------------------------------------------------------------------------- 1 | module Cucumber 2 | module Mate 3 | class TableAligner 4 | def align(lines) 5 | group_by_tables(lines).map do |group| 6 | if(group.is_a? Array) 7 | align_table(group) 8 | else 9 | group 10 | end 11 | end.flatten 12 | end 13 | 14 | private 15 | 16 | def group_by_tables(lines) 17 | current_table = [] 18 | groups = [] 19 | 20 | lines.each do |line| 21 | if line.match(/\s*\|/) 22 | current_table << line 23 | else 24 | groups << current_table unless current_table.empty? 25 | groups << line 26 | current_table = [] 27 | end 28 | end 29 | 30 | groups << current_table unless current_table.empty? 31 | groups 32 | end 33 | 34 | def align_table(table) 35 | table_data = table.map{|line| split_line(line).map{|cell| cell.strip}} 36 | max_columns = table_data.inject(0) {|memo, row| memo > row.size ? memo : row.size} 37 | table_data = table_data.map{|row| row.concat([""] * (max_columns - row.size))} 38 | max_lengths = table_data.transpose.map { |col| col.map { |cell| cell.unpack("U*").length }.max }.flatten 39 | initial_space = table.first.match(/(\s*)|/)[1] 40 | 41 | table_data.map do |line| 42 | initial_space[0..-2].to_s + \ 43 | line.zip(max_lengths).map { |cell, max_length| 44 | cell + " " * (max_length - cell.unpack("U*").length) 45 | }.join(' | ') + ' |' 46 | end 47 | end 48 | 49 | def split_line(line) 50 | cells = line.strip.split("|", -1) 51 | 52 | if(cells.last.strip == "") 53 | cells.delete_at(cells.size - 1) if line =~ /\|\s*$/ 54 | end 55 | 56 | cells 57 | end 58 | end 59 | end 60 | end 61 | 62 | -------------------------------------------------------------------------------- /Support/lib/cucumber/mate/text_mate_helper.rb: -------------------------------------------------------------------------------- 1 | require "#{ENV['TM_SUPPORT_PATH']}/lib/textmate" 2 | require "#{ENV['TM_SUPPORT_PATH']}/lib/ui" 3 | require "#{ENV['TM_SUPPORT_PATH']}/lib/exit_codes" 4 | require "tempfile" 5 | 6 | module Cucumber 7 | module Mate 8 | 9 | class TextMateHelper 10 | class << self 11 | # Opens target file_path and sets cursor position 12 | # options: 13 | # :line - line number (default: ENV['TM_LINE_NUMBER']) 14 | # :column - column number (default: 1) 15 | def goto_file(file_path, options = {}) 16 | TextMate.go_to(options.merge(:file => file_path)) 17 | end 18 | 19 | def display_select_list(options) 20 | ninja_search = "/Applications/NinjaSearch.app/Contents/MacOS/NinjaSearch" 21 | list = options 22 | if list.size > too_many_to_select && File.exists?(ninja_search) 23 | data = list.join("\n") # TODO escape single quotes OR store in file 24 | res = nil 25 | Tempfile.open("ninjasearch-cucumber") do |f| 26 | f << data 27 | f.flush 28 | res = %x{NINJA_DATA='#{f.path}' #{e_sh ninja_search} 2>/dev/console} 29 | end 30 | list.index(res.strip) 31 | else 32 | TextMate::UI.menu(list) 33 | end 34 | end 35 | 36 | def alert(options = {}) 37 | options = {:message => options} if options.kind_of?(String) 38 | options = {:style => :informational, :title => 'Alert!', :message => '', :buttons => 'OK'}.merge(options) 39 | TextMate::UI.alert(options[:style], options[:title], options[:message], options[:buttons]) 40 | end 41 | 42 | def request_confirmation(options) 43 | TextMate::UI.request_confirmation(options) 44 | end 45 | 46 | def create_file(file_path) 47 | `mkdir -p "#{File.dirname(file_path)}"` 48 | `touch "#{file_path}"` 49 | end 50 | 51 | def create_and_open_file(file_path) 52 | create_file(file_path) 53 | `osascript &>/dev/null -e 'tell app "SystemUIServer" to activate' -e 'tell app "TextMate" to activate'` 54 | `"$TM_SUPPORT_PATH/bin/mate" "#{file_path}"` 55 | end 56 | 57 | def insert_text(text) 58 | `osascript &>/dev/null -e 'tell app "SystemUIServer" to activate' -e 'tell app "TextMate" to activate'` 59 | escaped_content = text.gsub("\n","\\n").gsub('$','\\$').gsub('"','\\\\\\\\\\\\"') 60 | `osascript &>/dev/null -e "tell app \\"TextMate\\" to insert \\"#{escaped_content}\\" as snippet true"` 61 | end 62 | 63 | def too_many_to_select 64 | 9 65 | end 66 | end 67 | end 68 | 69 | end 70 | end 71 | -------------------------------------------------------------------------------- /Support/spec/cucumber/mate/feature_helper_spec.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../spec_helper' 2 | require File.dirname(__FILE__) + '/../../../lib/cucumber/mate/feature_helper' 3 | 4 | module Cucumber 5 | module Mate 6 | 7 | describe FeatureHelper do 8 | before(:each) do 9 | @fixtures_path = File.expand_path(File.join(File.dirname(__FILE__), %w[.. .. .. fixtures])) 10 | # Default - don't let TextMateHelper actually perform any actions 11 | TextMateHelper.stub!(:goto_file) 12 | TextMateHelper.stub!(:display_select_list) 13 | TextMateHelper.stub!(:request_confirmation) 14 | TextMateHelper.stub!(:create_and_open_file) 15 | TextMateHelper.stub!(:insert_text) 16 | TextMateHelper.stub!(:create_file) 17 | 18 | File.stub!(:file?).and_return(true) 19 | 20 | @helper_file = mock('helper file', 21 | :feature_file? => true, 22 | :feature_file_path => '/path/to/feature/file', 23 | :steps_file_path => '/path/to/step_definitions/file', 24 | :runner_file_path => '/path/to/runner/file', 25 | :alternate_file_path => "/alternate/file/path", 26 | :alternate_files_and_names => [ 27 | {:name => 'one', :file_path => "/path/to/one"}, 28 | {:name => 'two', :file_path => "/path/to/two"} 29 | ]) 30 | 31 | Files::Base.stub!(:create_from_file_path).and_return(@helper_file) 32 | Files::Base.stub!(:default_content_for).and_return('') 33 | @feature_helper = FeatureHelper.new("#{@fixtures_path}/features/basic.feature") 34 | end 35 | 36 | describe "#goto_alternate_file" do 37 | it "should tell textmate to go to the correct file" do 38 | # expects 39 | TextMateHelper.should_receive('goto_file').with('/alternate/file/path', :line => 1, :column => 1) 40 | # when 41 | @feature_helper.goto_alternate_file 42 | end 43 | 44 | describe "when a file doesn't exist" do 45 | before(:each) do 46 | File.stub!(:file?).and_return(false) 47 | end 48 | 49 | it "should ask if the file should be created" do 50 | # expects 51 | TextMateHelper.should_receive('request_confirmation') 52 | # when 53 | @feature_helper.goto_alternate_file 54 | end 55 | 56 | describe "and the user chooses to create the file" do 57 | before(:each) do 58 | TextMateHelper.stub!(:request_confirmation).and_return(true) 59 | end 60 | 61 | it "should create the file and add the default contents" do 62 | # expects 63 | TextMateHelper.should_receive('create_and_open_file').with('/alternate/file/path') 64 | TextMateHelper.should_receive('insert_text') 65 | # when 66 | @feature_helper.goto_alternate_file 67 | end 68 | end 69 | 70 | describe "and the user chooses NOT to create the file" do 71 | before(:each) do 72 | TextMateHelper.stub!(:request_confirmation).and_return(false) 73 | end 74 | 75 | it "should not create the file" do 76 | # expects 77 | TextMateHelper.should_not_receive('create_and_open_file') 78 | # when 79 | @feature_helper.goto_alternate_file 80 | end 81 | end 82 | end 83 | end 84 | 85 | describe "#autocomplete_step" do 86 | describe "with no matches" do 87 | before(:each) do 88 | @helper_file.should_receive(:steps_starting_with).with("xxx").and_return([]) 89 | stdout = StringIO.new 90 | @feature_helper.autocomplete_step(stdout, " Given xxx") 91 | stdout.rewind 92 | @stdout = stdout.read 93 | end 94 | it "should print original current_line" do 95 | @stdout.should == " Given xxx" 96 | end 97 | end 98 | 99 | describe "with 1 match" do 100 | before(:each) do 101 | @helper_file.should_receive(:steps_starting_with).with("weird step"). 102 | and_return([{:pattern_text => 'weird step with (\d+) match in step files'}]) 103 | stdout = StringIO.new 104 | @feature_helper.autocomplete_step(stdout, " Given weird step") 105 | stdout.rewind 106 | @stdout = stdout.read 107 | end 108 | it "should print original current_line" do 109 | @stdout.should == ' Given weird step with ${1:\d+} match in step files' 110 | end 111 | end 112 | 113 | describe "with multiple matches and choose 1" do 114 | before(:each) do 115 | @helper_file.should_receive(:steps_starting_with).with("weird step"). 116 | and_return([ 117 | {:pattern_text => 'weird step (with|without) object in step (.*)'}, 118 | {:pattern_text => "weird step with second match in step files"} 119 | ]) 120 | TextMateHelper.should_receive(:display_select_list).with([ 121 | 'weird step (with|without) object in step (.*)', 'weird step with second match in step files' ]). 122 | and_return(0) 123 | stdout = StringIO.new 124 | @feature_helper.autocomplete_step(stdout, " Given weird step") 125 | stdout.rewind 126 | @stdout = stdout.read 127 | end 128 | it "should print chosen pattern" do 129 | @stdout.should == ' Given weird step ${1:with|without} object in step ${2:.*}' 130 | end 131 | end 132 | end 133 | 134 | describe "#choose_alternate_file" do 135 | it "should prompt the user to choose a step file from those included in the runner" do 136 | # expects 137 | TextMateHelper.should_receive('display_select_list').with(['one', 'two']) 138 | # when 139 | @feature_helper.choose_alternate_file 140 | end 141 | 142 | it "should tell textmate to open the chosen file (after a user has selected)" do 143 | TextMateHelper.stub!(:display_select_list).and_return(0) 144 | 145 | # expects 146 | TextMateHelper.should_receive('goto_file').with("/path/to/one", :line => 1, :column => 1) 147 | # when 148 | @feature_helper.choose_alternate_file 149 | end 150 | end 151 | 152 | describe "#goto_current_step" do 153 | describe "when not on a feature file" do 154 | before(:each) do 155 | @helper_file.stub!(:feature_file?).and_return(false) 156 | end 157 | 158 | it "should not tell textmate to do anything" do 159 | # expects 160 | TextMateHelper.should_not_receive('display_select_list') 161 | TextMateHelper.should_not_receive('goto_file') 162 | # when 163 | @feature_helper.goto_current_step(1) 164 | end 165 | end 166 | 167 | describe "when on a feature file" do 168 | describe "and the current line doesn't contain a step" do 169 | before(:each) do 170 | @helper_file.stub!(:step_information_for_line).and_return(nil) 171 | end 172 | 173 | it "should not tell textmate to do anything" do 174 | # expect 175 | TextMateHelper.should_not_receive('goto_file') 176 | # when 177 | @feature_helper.goto_current_step(1) 178 | end 179 | end 180 | 181 | describe "and the current line contains a step" do 182 | before(:each) do 183 | @helper_file.stub!(:step_information_for_line).and_return({:step_type => 'Given', :step_name => 'blah'}) 184 | end 185 | 186 | describe "when the runner file doesn't exist" do 187 | before(:each) do 188 | File.stub!(:file?).and_return(false) 189 | @helper_file.stub!(:location_of_step) 190 | end 191 | 192 | it "should prompt to create the runner file" do 193 | # expects 194 | TextMateHelper.should_receive('request_confirmation').once # once for the steps file 195 | # when 196 | @feature_helper.goto_current_step(1) 197 | end 198 | end 199 | 200 | describe "and the step exists" do 201 | before(:each) do 202 | @helper_file.stub!(:location_of_step).and_return({:file_path => '/foo/bar', :line => 10, :column => 3}) 203 | end 204 | 205 | it "should tell textmate to goto the file where the step is defined" do 206 | # expects 207 | TextMateHelper.should_receive('goto_file').with('/foo/bar', {:line => 10, :column => 3}) 208 | # when 209 | @feature_helper.goto_current_step(1) 210 | end 211 | end 212 | 213 | describe "and the step doesn't exist" do 214 | before(:each) do 215 | @helper_file.stub!(:location_of_step).and_return(nil) 216 | @helper_file.stub!(:step_information_for_line).and_return(nil) 217 | end 218 | 219 | it "should tell textmate to goto the feature's step file and to insert the step" do 220 | pending "JohnnyT..." 221 | # expects 222 | TextMateHelper.should_receive('goto_file').with('/path/to/step_definitions/file', {:line => 2, :column => 1}) 223 | TextMateHelper.should_receive('insert_text') 224 | 225 | # when 226 | @feature_helper.goto_current_step(1) 227 | end 228 | end 229 | end 230 | end # when on a feature file 231 | end 232 | end 233 | 234 | end 235 | end 236 | -------------------------------------------------------------------------------- /Support/spec/cucumber/mate/files/base_spec.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../../spec_helper' 2 | require File.dirname(__FILE__) + '/../../../../lib/cucumber/mate/files' 3 | 4 | module Cucumber 5 | module Mate 6 | 7 | module Files 8 | 9 | describe Base do 10 | before(:each) do 11 | @fixtures_path = File.expand_path(File.join(File.dirname(__FILE__), %w[.. .. .. .. fixtures])) 12 | @file = Base.new(File.expand_path(File.join(@fixtures_path, %w[features basic.feature]))) 13 | end 14 | 15 | it "should determine the base project path" do 16 | @file.project_root.should == @fixtures_path 17 | end 18 | 19 | it "should determine the relative path (relative to the project_root)" do 20 | @file.relative_path.should == 'features/basic.feature' 21 | end 22 | 23 | it "should determine the name of the file" do 24 | @file.name.should == 'basic' 25 | end 26 | 27 | describe "#create_from_file_path" do 28 | describe "when file name is not valid step nor feature file name" do 29 | it "should throw a descriptive exception" do 30 | lambda { Base.create_from_file_path("/path/to/some_feature.features") }.should raise_error(InvalidFilePathError) 31 | end 32 | end 33 | describe "when file name is .feature" do 34 | before(:each) do 35 | @file = Base.create_from_file_path("/path/to/some_feature.feature") 36 | end 37 | it do 38 | @file.class.should == FeatureFile 39 | end 40 | end 41 | describe "when file name is _steps.rb" do 42 | before(:each) do 43 | @file = Base.create_from_file_path("/path/to/some_steps.rb") 44 | end 45 | it do 46 | @file.class.should == StepsFile 47 | end 48 | end 49 | end 50 | 51 | describe "#default_file_path" do 52 | describe "when the file type is invalid" do 53 | it "should throw a descriptive exception" do 54 | lambda { @file.default_file_path(:blah) }.should raise_error(ArgumentError) 55 | end 56 | end 57 | 58 | it "should determine the default steps file path" do 59 | @file.default_file_path(:steps).should == "#{@fixtures_path}/features/step_definitions/basic_steps.rb" 60 | end 61 | 62 | it "should determine the default feature file path" do 63 | @file.default_file_path(:feature).should == "#{@fixtures_path}/features/basic.feature" 64 | end 65 | end 66 | 67 | describe "#file_path" do 68 | describe "when the file type is invalid" do 69 | it "should throw a descriptive exception" do 70 | lambda { @file.file_path(:blah) }.should raise_error(ArgumentError) 71 | end 72 | end 73 | 74 | describe "when looking for an existing steps file" do 75 | describe "when the file is the standard location" do 76 | it "should return the path to the existing file" do 77 | @file.file_path(:steps).should == "#{@fixtures_path}/features/step_definitions/basic_steps.rb" 78 | end 79 | end 80 | 81 | describe "when the file is in a non-standard location" do 82 | before(:each) do 83 | @file = Base.new(File.expand_path(File.join(@fixtures_path, %w[features non_standard.feature]))) 84 | end 85 | 86 | it "should return the path to the existing file" do 87 | @file.file_path(:steps).should == "#{@fixtures_path}/features/non_standard_dir/step_definitions/non_standard_steps.rb" 88 | end 89 | end 90 | end 91 | 92 | 93 | describe "when looking for an existing feature file" do 94 | describe "when the file is the standard location" do 95 | it "should return the path to the existing file" do 96 | @file.file_path(:feature).should == "#{@fixtures_path}/features/basic.feature" 97 | end 98 | end 99 | 100 | describe "when the file is in a non-standard location" do 101 | before(:each) do 102 | @file = Base.new(File.expand_path(File.join(@fixtures_path, %w[features non_standard_dir runners non_standard.rb]))) 103 | end 104 | 105 | it "should return the path to the existing file" do 106 | @file.file_path(:feature).should == "#{@fixtures_path}/features/non_standard.feature" 107 | end 108 | end 109 | end 110 | 111 | describe "when looking for all existing files" do 112 | it "should find all feature files" do 113 | expected = %w[additional_basic.feature basic.feature feature1/foo.feature non_standard.feature] 114 | expected.map! { |path| FeatureFile.new(File.join(project_root, "features", path)) } 115 | @file.all(:feature).should == expected 116 | end 117 | 118 | it "should find all steps files" do 119 | expected = %w[feature1/step_definitions/foo_steps.rb 120 | non_standard_dir/step_definitions/non_standard_steps.rb 121 | step_definitions/additional_basic_steps.rb 122 | step_definitions/basic_steps.rb 123 | step_definitions/global_steps.rb 124 | step_definitions/unconventional_steps.rb 125 | ] 126 | expected.map! { |path| StepsFile.new(File.join(project_root, "features", path)) } 127 | @file.all(:steps).should == expected 128 | end 129 | end 130 | 131 | 132 | 133 | end # file_path 134 | 135 | end 136 | 137 | end 138 | end 139 | end -------------------------------------------------------------------------------- /Support/spec/cucumber/mate/files/feature_file_spec.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../../spec_helper' 2 | require File.dirname(__FILE__) + '/../../../../lib/cucumber/mate/files' 3 | 4 | module Cucumber 5 | module Mate 6 | module Files 7 | 8 | describe FeatureFile do 9 | 10 | #TODO Get rid of fixtures and create the example files in specs inline (and stub the IO.read call) 11 | 12 | def feature_file_from_fixtures(feature_name) 13 | FeatureFile.new(File.expand_path(File.join(@fixtures_path, "features", "#{feature_name}.feature"))) 14 | end 15 | 16 | before(:each) do 17 | @fixtures_path = File.expand_path(File.join(File.dirname(__FILE__), %w[.. .. .. .. fixtures])) 18 | @feature_file = feature_file_from_fixtures('basic') 19 | end 20 | 21 | it "should be a feature file" do 22 | @feature_file.should be_feature_file 23 | end 24 | 25 | # describe "when a steps file exists on the filesystem (even if not using the assumed directory structure)" do 26 | # before(:each) do 27 | # @feature_file = FeatureFile.new(File.expand_path(File.join(@fixtures_path, %w[features non_standard.feature]))) 28 | # end 29 | # 30 | # it "should return the path to the existing steps file" do 31 | # @feature_file.steps_file_path.should == "#{@fixtures_path}/features/non_standard_dir/step_definitions/non_standard_steps.rb" 32 | # end 33 | # end 34 | # 35 | # describe "when a steps file doesn't exist on the filesystem" do 36 | # it "should determine the path to the new steps file (and assume the proposed directory structure)" do 37 | # @feature_file.steps_file_path.should == "#{@fixtures_path}/features/step_definitions/basic_steps.rb" 38 | # end 39 | # end 40 | 41 | it "should not be a steps file" do 42 | @feature_file.should_not be_steps_file 43 | end 44 | 45 | it "should return the correct step file path" do 46 | @feature_file.alternate_file_path.should == "#{@fixtures_path}/features/step_definitions/basic_steps.rb" 47 | end 48 | 49 | it "should determine the correct alternate file as the step file" do 50 | @feature_file.alternate_file_path.should == @feature_file.steps_file_path 51 | end 52 | 53 | describe "#name" do 54 | it "should return the simple name (based off the file name)" do 55 | @feature_file.name.should == 'basic' 56 | end 57 | end 58 | 59 | describe "#rake_task" do 60 | it "should return nil when none is defined in the file" do 61 | @feature_file.rake_task.should be_nil 62 | end 63 | 64 | it "should return the rake task defined in the features file" do 65 | feature_file = feature_file_from_fixtures('non_standard') 66 | feature_file.rake_task.should == 'some_defined_task_in_feature:file' 67 | end 68 | end 69 | 70 | describe "#profile" do 71 | it "should return nil when none is defined in the file" do 72 | @feature_file.profile.should be_nil 73 | end 74 | 75 | it "should return the rake task defined in the features file" do 76 | feature_file = feature_file_from_fixtures('non_standard') 77 | feature_file.profile.should == 'some_defined_profile_in_feature' 78 | end 79 | end 80 | 81 | describe "#alternate_files_and_names" do 82 | it "should return the list of step files being used in the feature" do 83 | @feature_file.alternate_files_and_names.should == 84 | [ 85 | {:file_path=>"#{@fixtures_path}/features/feature1/step_definitions/foo_steps.rb", :name => 'foo'}, 86 | {:file_path=>"#{@fixtures_path}/features/non_standard_dir/step_definitions/non_standard_steps.rb", :name => 'non_standard'}, 87 | {:file_path=>"#{@fixtures_path}/features/step_definitions/additional_basic_steps.rb", :name => 'additional_basic'}, 88 | {:file_path=>"#{@fixtures_path}/features/step_definitions/basic_steps.rb", :name => 'basic'}, 89 | {:file_path=>"#{@fixtures_path}/features/step_definitions/global_steps.rb", :name => 'global'}, 90 | {:file_path=>"#{@fixtures_path}/features/step_definitions/unconventional_steps.rb", :name => 'unconventional'} 91 | ] 92 | end 93 | end 94 | 95 | describe "#step_information_for_line" do 96 | it "should not return anything if the line doesn't contain a valid step" do 97 | @feature_file.step_information_for_line(5).should == nil 98 | end 99 | 100 | it "should return the step information if the line contains a valid step" do 101 | @feature_file.step_information_for_line(8).should == {:step_name => 'Basic step (given)', :step_type => "Given"} 102 | end 103 | 104 | end 105 | 106 | describe "#location_of_step" do 107 | describe "when the step definition exists" do 108 | it "should return the correct file, line and column for string-based step" do 109 | StepsFile.stub!(:new).and_return(@steps = mock('steps file', :step_definitions => [{:pattern => "string pattern", :pattern_text => "string pattern", :line => 3, :file_path => '/path/to/basic_steps.rb'}], :full_file_path => '/path/to/basic_steps.rb', :name => 'basic')) 110 | @feature_file.location_of_step({:step_name => 'string pattern'}).should == 111 | {:pattern => "string pattern", :pattern_text => "string pattern", :line => 3, :file_path => '/path/to/basic_steps.rb'} 112 | end 113 | 114 | it "should return the correct file, line and column for regexp-based step" do 115 | StepsFile.stub!(:new).and_return(@steps = mock('steps file', :step_definitions => [{:pattern => /string pattern/, :pattern_text => "string pattern", :line => 3, :file_path => '/path/to/basic_steps.rb'}], :full_file_path => '/path/to/basic_steps.rb', :name => 'basic')) 116 | @feature_file.location_of_step({:step_name => 'string pattern'}).should == 117 | {:pattern => /string pattern/, :pattern_text => "string pattern", :line => 3, :file_path => '/path/to/basic_steps.rb'} 118 | end 119 | 120 | it "matches $ tokens in strings" do 121 | step = {:pattern => "it should have $count items", :pattern_text => "it should have $count items", :line => 3, :file_path => '/path/to/basic_steps.rb'} 122 | StepsFile.stub!(:new).and_return(@steps = mock('steps file', :step_definitions => [step], :full_file_path => '/path/to/basic_steps.rb', :name => 'basic')) 123 | @feature_file.location_of_step({:step_name => 'it should have 5 items'}).should == 124 | step 125 | end 126 | 127 | it "enforces beginning and end matching with string steps" do 128 | step = {:pattern => "it should have $count items", :pattern_text => "it should have $count items", :line => 3, :file_path => '/path/to/basic_steps.rb'} 129 | StepsFile.stub!(:new).and_return(@steps = mock('steps file', :step_definitions => [step], :full_file_path => '/path/to/basic_steps.rb', :name => 'basic')) 130 | @feature_file.location_of_step({:step_name => 'it should have 5 items and some cheese'}).should == nil 131 | end 132 | end 133 | end 134 | 135 | describe "#steps_starting_with" do 136 | before(:each) do 137 | StepsFile.stub!(:new).and_return(@steps = mock('steps file', :step_definitions => [ 138 | {:pattern => "matching string", :pattern_text => "matching string", :line => 3, :file_path => '/path/to/steps'}, 139 | {:pattern => /^matching pattern/, :pattern_text => "matching pattern", :line => 3, :file_path => '/path/to/steps'}, 140 | {:pattern => "not matching string", :pattern_text => "not matching string", :line => 3, :file_path => '/path/to/steps'}, 141 | ], :full_file_path => '/path/to/basic_steps.rb', :name => 'basic')) 142 | @feature_file.should_receive(:step_files_and_names).at_least(:once).and_return([{:file_path => '/path/to/steps', :name => 'steps'}]) 143 | end 144 | 145 | describe "when 1 matching string step definition exists" do 146 | before(:each) do 147 | @matching_steps = @feature_file.steps_starting_with('matching s') 148 | end 149 | 150 | it "should return the step definition" do 151 | @matching_steps.size.should == 1 152 | end 153 | end 154 | 155 | describe "when 1 matching regex step definition exists" do 156 | before(:each) do 157 | @matching_steps = @feature_file.steps_starting_with('matching p') 158 | end 159 | 160 | it "should return the step definition" do 161 | @matching_steps.size.should == 1 162 | end 163 | end 164 | 165 | describe "when multiple matching step definitions exists" do 166 | before(:each) do 167 | @matching_steps = @feature_file.steps_starting_with('match') 168 | end 169 | 170 | it "should return the step definition" do 171 | @matching_steps.size.should == 2 172 | end 173 | end 174 | 175 | describe "when no matching step definitions exists" do 176 | before(:each) do 177 | @matching_steps = @feature_file.steps_starting_with('xxx') 178 | end 179 | 180 | it "should return the step definition" do 181 | @matching_steps.size.should == 0 182 | end 183 | end 184 | end 185 | 186 | describe "#undefined_steps" do 187 | it "should return a unique list of steps not defined in the feature" do 188 | @feature_file.stub!(:all_steps_in_file).and_return([ 189 | {:step_name => 'a member named Foo'}, 190 | {:step_name => 'Foo walks into a bar'}, 191 | {:step_name => 'a member named Foo'} 192 | ]) 193 | 194 | @feature_file.stub!(:location_of_step).and_return(nil) 195 | @feature_file.undefined_steps.should == ([ 196 | {:step_name => 'a member named Foo'}, 197 | {:step_name => 'Foo walks into a bar'} 198 | ]) 199 | end 200 | end 201 | end 202 | 203 | end 204 | 205 | end 206 | end -------------------------------------------------------------------------------- /Support/spec/cucumber/mate/files/steps_file_spec.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../../spec_helper' 2 | require File.dirname(__FILE__) + '/../../../../lib/cucumber/mate/files' 3 | 4 | module Cucumber 5 | module Mate 6 | module Files 7 | 8 | describe StepsFile do 9 | before(:each) do 10 | @fixtures_path = File.expand_path(File.join(File.dirname(__FILE__), %w[.. .. .. .. fixtures])) 11 | @steps_file = StepsFile.new(File.expand_path(File.join(@fixtures_path, %w[features step_definitions basic_steps.rb]))) 12 | end 13 | 14 | it "should determine the feature file" do 15 | @steps_file.feature_file_path.should == "#{@fixtures_path}/features/basic.feature" 16 | end 17 | 18 | it "should determine the correct alternate file" do 19 | @steps_file.alternate_file_path.should == @steps_file.feature_file_path 20 | end 21 | 22 | describe "#name" do 23 | it "should return the simple name (based off the file name)" do 24 | @steps_file.name.should == 'basic' 25 | end 26 | end 27 | 28 | describe "#rake_task" do 29 | it "should delegate to the file's feature file" do 30 | FeatureFile.should_receive(:new).with(@steps_file.feature_file_path).and_return(feature_file = mock('feature file')) 31 | feature_file.stub!(:rake_task).and_return("some_rake_task") 32 | 33 | @steps_file.rake_task.should == "some_rake_task" 34 | end 35 | end 36 | 37 | describe "#profile" do 38 | it "should delegate to the file's feature file" do 39 | FeatureFile.should_receive(:new).with(@steps_file.feature_file_path).and_return(feature_file = mock('feature file')) 40 | feature_file.stub!(:profile).and_return("watir") 41 | 42 | @steps_file.profile.should == "watir" 43 | end 44 | end 45 | 46 | describe "#alternate_files_and_names" do 47 | it "should generate a list of feature files (and names) which use this steps file" do 48 | @steps_file.alternate_files_and_names.should == 49 | [ 50 | {:file_path=>"#{@fixtures_path}/features/additional_basic.feature", :name => 'additional_basic'}, 51 | {:file_path=>"#{@fixtures_path}/features/basic.feature", :name => 'basic'}, 52 | {:file_path=>"#{@fixtures_path}/features/feature1/foo.feature", :name => 'foo'}, 53 | {:file_path=>"#{@fixtures_path}/features/non_standard.feature", :name => 'non_standard'} 54 | ] 55 | end 56 | end 57 | 58 | describe "#step_definitions" do 59 | it "should return a list of step definitions included in this file" do 60 | @steps_file.step_definitions.should == 61 | [ 62 | {:pattern => "Basic step (given)", :pattern_text => "Basic step (given)", :line => 1, :file_path => @steps_file.full_file_path}, 63 | {:pattern => "another basic step", :pattern_text => "another basic step", :line => 5, :file_path => @steps_file.full_file_path}, 64 | {:pattern => %r{Basic regexp (.*) with multiple (.*) groups}, :pattern_text => "Basic regexp (.*) with multiple (.*) groups", :line => 9, :file_path => @steps_file.full_file_path}, 65 | {:pattern => /Some quoted regexp "(.*)" and '(.*)'/, :pattern_text => "Some quoted regexp \"(.*)\" and '(.*)'", :line => 13, :file_path => @steps_file.full_file_path}, 66 | {:pattern => /classic regexp/, :pattern_text => "classic regexp", :line => 17, :file_path => @steps_file.full_file_path}, 67 | {:pattern => "Basic when", :pattern_text => "Basic when", :line => 21, :file_path => @steps_file.full_file_path}, 68 | {:pattern => "Basic then", :pattern_text => "Basic then", :line => 25, :file_path => @steps_file.full_file_path}, 69 | ] 70 | end 71 | 72 | it "should parse unconventional step definitions" do 73 | StepsFile.new(File.expand_path(File.join(@fixtures_path, %w[features step_definitions unconventional_steps.rb]))).step_definitions.should == [ 74 | {:pattern_text => "one liner with comment", :pattern => "one liner with comment", :file_path => "#{@fixtures_path}/features/step_definitions/unconventional_steps.rb", :line => 1}, 75 | {:pattern_text => "one liner with trailing space", :pattern => "one liner with trailing space", :file_path => "#{@fixtures_path}/features/step_definitions/unconventional_steps.rb", :line => 3}, 76 | {:pattern_text => "one liner with no trailing space", :pattern => "one liner with no trailing space", :file_path => "#{@fixtures_path}/features/step_definitions/unconventional_steps.rb", :line => 5}, 77 | {:pattern_text => "braces with a comment", :pattern => "braces with a comment", :file_path => "#{@fixtures_path}/features/step_definitions/unconventional_steps.rb", :line => 7}, 78 | {:pattern_text => "braces with a trailing space", :pattern => "braces with a trailing space", :file_path => "#{@fixtures_path}/features/step_definitions/unconventional_steps.rb", :line => 10}, 79 | {:pattern_text => "braces no trailing space", :pattern => "braces no trailing space", :file_path => "#{@fixtures_path}/features/step_definitions/unconventional_steps.rb", :line => 13} 80 | ] 81 | end 82 | end 83 | end 84 | 85 | end 86 | 87 | end 88 | end -------------------------------------------------------------------------------- /Support/spec/cucumber/mate/runner_spec.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../spec_helper' 2 | require File.dirname(__FILE__) + '/../../../lib/cucumber/mate/runner' 3 | 4 | module Cucumber 5 | module Mate 6 | describe "a run command", :shared => true do 7 | it "should run with the cucumber command by default" do 8 | expect_system_call_to_be_made_with(%r[#{Cucumber::Mate::Runner::CUCUMBER_BIN}]) 9 | when_run_is_called 10 | end 11 | 12 | it "should run with the cucumber command passed in" do 13 | expect_system_call_to_be_made_with(%r[/some/path/cucumber ]) 14 | when_run_is_called(nil, "/some/path/cucumber") 15 | end 16 | 17 | it "should run with /project/path/script/cucumber if present" do 18 | File.should_receive(:exists?).with("/project/path/script/cucumber").and_return(true) 19 | expect_system_call_to_be_made_with(%r[/project/path/script/cucumber ]) 20 | when_run_is_called 21 | end 22 | 23 | it "should run the single feature" do 24 | expect_system_call_to_be_made_with(/ #{@file.full_file_path}/) 25 | when_run_is_called 26 | end 27 | 28 | it "should run with the deafult cucumber options when none are passed in" do 29 | expect_system_call_to_be_made_with(/--format=html/) 30 | when_run_is_called 31 | end 32 | 33 | it "should run with the profile defined in the feature file" do 34 | # given 35 | @file.stub!(:profile).and_return('watir') 36 | expect_system_call_to_be_made_with(/--profile=watir/) 37 | when_run_is_called 38 | end 39 | 40 | it "should run with the cucumber options passed in" do 41 | expect_system_call_to_be_made_with(/--format=custom/) 42 | when_run_is_called("--format=custom") 43 | end 44 | 45 | it "should direct the call's output to the passed in output" do 46 | Kernel.stub!(:system).and_return("features html") 47 | output = when_run_is_called 48 | output.string.should =~ /features html/ 49 | end 50 | 51 | it "should output the exact command it is running" do 52 | Kernel.stub!(:system).and_return("features html") 53 | output = when_run_is_called 54 | output.string.should =~ /^Running: .+cucumber / 55 | end 56 | 57 | describe "when the feature file defines a rake task" do 58 | before(:each) do 59 | @file.stub!(:rake_task).and_return('some_task') 60 | end 61 | 62 | it "should run the feature with the defined rake task" do 63 | expect_system_call_to_be_made_with(/#{Cucumber::Mate::Runner::RAKE_BIN} #{@file.rake_task} /) 64 | when_run_is_called 65 | end 66 | 67 | it "should run the single feature with the rake syntax" do 68 | expect_system_call_to_be_made_with(/FEATURE=#{@file.full_file_path}/) 69 | when_run_is_called 70 | end 71 | 72 | it "should run with the deafult cucumber options when none are passed in with the rake syntax" do 73 | expect_system_call_to_be_made_with(/CUCUMBER_OPTS="--format=html/) 74 | when_run_is_called 75 | end 76 | 77 | it "should run with the cucumber options passed in with the rake syntax" do 78 | expect_system_call_to_be_made_with(/CUCUMBER_OPTS="--format=custom/) 79 | when_run_is_called("--format=custom") 80 | end 81 | end 82 | end 83 | 84 | describe Runner do 85 | before(:each) do 86 | Files::Base.stub!(:create_from_file_path).and_return( 87 | @file = mock("feature file", 88 | :rake_task => nil, 89 | :profile => nil, 90 | :feature_file_path => 'path_to_feature.feature', 91 | :relative_path => 'relative_path.feature', 92 | :full_file_path => '/foo/bar/relative_path.feature' 93 | ) 94 | ) 95 | Dir.stub!(:chdir).and_yield 96 | Kernel.stub!(:system) 97 | File.stub!(:exists?).and_return(false) 98 | end 99 | 100 | def expect_system_call_to_be_made_with(regex) 101 | Kernel.should_receive(:system).with(regex) 102 | end 103 | 104 | it "should create a new Files::Base from the passed in file path" do 105 | # expect 106 | Files::Base.should_receive(:create_from_file_path).with("/path/to/file").and_return(stub('file').as_null_object) 107 | # when 108 | Runner.new(nil, "/path","/path/to/file") 109 | end 110 | 111 | describe "#run_feature" do 112 | 113 | def when_run_feature_is_called(cucumber_options=nil, cucumber_bin = nil) 114 | Runner.new(output=StringIO.new, "/project/path", "/project/path/feature_file", cucumber_bin, cucumber_options).run_feature 115 | output 116 | end 117 | alias :when_run_is_called :when_run_feature_is_called 118 | 119 | it_should_behave_like "a run command" 120 | end 121 | 122 | describe "#run_scenario" do 123 | def when_run_scenario_is_called(cucumber_options=nil, cucumber_bin = nil) 124 | Runner.new(output=StringIO.new, "/project/path", "/project/path/feature_file", cucumber_bin, cucumber_options).run_scenario(12) 125 | output 126 | end 127 | alias :when_run_is_called :when_run_scenario_is_called 128 | 129 | it_should_behave_like "a run command" 130 | 131 | it "should pass the line number in the cucumber options" do 132 | # given 133 | runner = Runner.new(output=StringIO.new, "/project/path", @file.full_file_path) 134 | 135 | expect_system_call_to_be_made_with(%r{#{@file.full_file_path}:42 --format=html}) 136 | 137 | # when 138 | runner.run_scenario(42) 139 | end 140 | end 141 | 142 | describe "#format_feature" do 143 | it "should use cucumber's --autoformat on the specified feature file" do 144 | # given 145 | runner = Runner.new(output=StringIO.new, "/project/path", "/project/path/feature_file") 146 | 147 | expect_system_call_to_be_made_with(%r{--autoformat \. relative_path.feature$}) 148 | 149 | # when 150 | runner.autoformat_feature 151 | end 152 | end 153 | end 154 | end 155 | end 156 | -------------------------------------------------------------------------------- /Support/spec/cucumber/mate/table_aligner_spec.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../spec_helper' 2 | require File.dirname(__FILE__) + '/../../../lib/cucumber/mate/table_aligner' 3 | 4 | module Cucumber 5 | module Mate 6 | describe TableAligner do 7 | it "should align a simple table" do 8 | unaligned = [ 9 | " | a |b|", 10 | " |c| d |" 11 | ] 12 | 13 | expected = [ 14 | " | a | b |", 15 | " | c | d |" 16 | ] 17 | 18 | TableAligner.new.align(unaligned).should == expected 19 | end 20 | 21 | it "should align multiple tables" do 22 | unaligned = [ 23 | " | a |b|", 24 | " |c| d |", 25 | "", 26 | " |x | y|zz|", 27 | " |1|2|3|" 28 | ] 29 | 30 | expected = [ 31 | " | a | b |", 32 | " | c | d |", 33 | "", 34 | " | x | y | zz |", 35 | " | 1 | 2 | 3 |" 36 | ] 37 | 38 | TableAligner.new.align(unaligned).should == expected 39 | end 40 | 41 | it "should pad short rows out to the longest row" do 42 | unaligned = [ 43 | "", 44 | " |a|b|", 45 | " |x|y|z", 46 | " |", 47 | "" 48 | ] 49 | 50 | expected = [ 51 | "", 52 | " | a | b | |", 53 | " | x | y | z |", 54 | " | | | |", 55 | "" 56 | ] 57 | 58 | TableAligner.new.align(unaligned).should == expected 59 | end 60 | 61 | it "should align a table with multi-byte UTF8 values" do 62 | unaligned = [ 63 | " | aa |b|", 64 | " |÷| d |" 65 | ] 66 | 67 | expected = [ 68 | " | aa | b |", 69 | " | ÷ | d |" 70 | ] 71 | 72 | TableAligner.new.align(unaligned).should == expected 73 | end 74 | 75 | it "should align a table that has cells with no content" do 76 | unaligned = [ 77 | " |a|b|", 78 | " |||" 79 | ] 80 | 81 | expected = [ 82 | " | a | b |", 83 | " | | |" 84 | ] 85 | 86 | TableAligner.new.align(unaligned).should == expected 87 | end 88 | end 89 | end 90 | end -------------------------------------------------------------------------------- /Support/spec/cucumber/mate/text_mate_helper_spec.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../spec_helper' 2 | require File.dirname(__FILE__) + '/../../../lib/cucumber/mate/text_mate_helper' 3 | 4 | module Cucumber 5 | module Mate 6 | 7 | describe TextMateHelper do 8 | end 9 | 10 | end 11 | end -------------------------------------------------------------------------------- /Support/spec/spec.opts: -------------------------------------------------------------------------------- 1 | --colour 2 | --loadby 3 | mtime 4 | --reverse -------------------------------------------------------------------------------- /Support/spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | require 'spec' 3 | 4 | ENV['TM_SUPPORT_PATH'] = '/Applications/TextMate.app/Contents/SharedSupport/Support' 5 | 6 | module Spec::Example::ExampleMethods 7 | def project_root 8 | @project_root ||= File.expand_path(File.join(File.dirname(__FILE__), '../fixtures')) 9 | end 10 | end -------------------------------------------------------------------------------- /Syntaxes/Cucumber Plain Text Feature.tmLanguage: -------------------------------------------------------------------------------- 1 | 2 | 3 |