require 'spec_helper' describe 'DocString, Integration' do let(:clazz) { CukeModeler::DocString } describe 'common behavior' do it_should_behave_like 'a model, integration' end describe 'unique behavior' do it 'can be instantiated with the minimum viable Gherkin' do source = "\"\"\"\n\"\"\"" expect { clazz.new(source) }.to_not raise_error end it 'provides a descriptive filename when being parsed from stand alone text' do source = 'bad doc string text' expect { clazz.new(source) }.to raise_error(/'cuke_modeler_stand_alone_doc_string\.feature'/) end it 'stores the original data generated by the parsing adapter', :gherkin4 => true do doc_string = clazz.new("\"\"\" content type\nsome doc string\n\"\"\"") data = doc_string.parsing_data expect(data.keys).to match_array([:type, :location, :content, :contentType]) expect(data[:type]).to eq(:DocString) end it 'stores the original data generated by the parsing adapter', :gherkin3 => true do doc_string = clazz.new("\"\"\" content type\nsome doc string\n\"\"\"") data = doc_string.parsing_data expect(data.keys).to match_array([:type, :location, :content, :contentType]) expect(data[:type]).to eq(:DocString) end it 'stores the original data generated by the parsing adapter', :gherkin2 => true do doc_string = clazz.new("\"\"\" content type\nsome doc string\n\"\"\"") data = doc_string.parsing_data expect(data.keys).to match_array(['value', 'content_type', 'line']) expect(data['value']).to eq('some doc string') end it 'stores its content as a String' do source = "\"\"\"\nsome text\nsome more text\n\"\"\"" doc_string = clazz.new(source) content = doc_string.content expect(content).to be_a(String) end describe 'getting ancestors' do before(:each) do source = ['Feature: Test feature', '', ' Scenario: Test test', ' * a big step:', ' """', ' a', ' doc', ' string', ' """'] source = source.join("\n") file_path = "#{@default_file_directory}/doc_string_test_file.feature" File.open(file_path, 'w') { |file| file.write(source) } end let(:directory) { CukeModeler::Directory.new(@default_file_directory) } let(:doc_string) { directory.feature_files.first.feature.tests.first.steps.first.block } it 'can get its directory' do ancestor = doc_string.get_ancestor(:directory) expect(ancestor).to equal(directory) end it 'can get its feature file' do ancestor = doc_string.get_ancestor(:feature_file) expect(ancestor).to equal(directory.feature_files.first) end it 'can get its feature' do ancestor = doc_string.get_ancestor(:feature) expect(ancestor).to equal(directory.feature_files.first.feature) end context 'a doc string that is part of a scenario' do before(:each) do source = 'Feature: Test feature Scenario: Test test * a big step: """ a doc string """' file_path = "#{@default_file_directory}/doc_string_test_file.feature" File.open(file_path, 'w') { |file| file.write(source) } end let(:directory) { CukeModeler::Directory.new(@default_file_directory) } let(:doc_string) { directory.feature_files.first.feature.tests.first.steps.first.block } it 'can get its scenario' do ancestor = doc_string.get_ancestor(:scenario) expect(ancestor).to equal(directory.feature_files.first.feature.tests.first) end end context 'a doc string that is part of an outline' do before(:each) do source = 'Feature: Test feature Scenario Outline: Test outline * a big step: """ a doc string """ Examples: | param | | value |' file_path = "#{@default_file_directory}/doc_string_test_file.feature" File.open(file_path, 'w') { |file| file.write(source) } end let(:directory) { CukeModeler::Directory.new(@default_file_directory) } let(:doc_string) { directory.feature_files.first.feature.tests.first.steps.first.block } it 'can get its outline' do ancestor = doc_string.get_ancestor(:outline) expect(ancestor).to equal(directory.feature_files.first.feature.tests.first) end end context 'a doc string that is part of a background' do before(:each) do source = 'Feature: Test feature Background: Test background * a big step: """ a doc string """' file_path = "#{@default_file_directory}/doc_string_test_file.feature" File.open(file_path, 'w') { |file| file.write(source) } end let(:directory) { CukeModeler::Directory.new(@default_file_directory) } let(:doc_string) { directory.feature_files.first.feature.background.steps.first.block } it 'can get its background' do ancestor = doc_string.get_ancestor(:background) expect(ancestor).to equal(directory.feature_files.first.feature.background) end end it 'can get its step' do ancestor = doc_string.get_ancestor(:step) expect(ancestor).to equal(directory.feature_files.first.feature.tests.first.steps.first) end it 'returns nil if it does not have the requested type of ancestor' do ancestor = doc_string.get_ancestor(:example) expect(ancestor).to be_nil end end describe 'model population' do context 'from source text' do context 'a filled doc string' do let(:source_text) { ['""" type foo', 'bar', '"""'].join("\n") } let(:doc_string) { clazz.new(source_text) } it "models the doc string's content type" do expect(doc_string.content_type).to eq('type foo') end it "models the doc_string's content" do expect(doc_string.content).to eq('bar') end end context 'an empty doc_string' do let(:source_text) { '""" """' } let(:doc_string) { clazz.new(source_text) } it "models the doc_string's content type" do expect(doc_string.content_type).to be_nil end it "models the doc_string's content" do expect(doc_string.content).to eq('') end end it "models the doc string's source line" do source_text = 'Feature: Scenario: * step """ foo """' doc_string = CukeModeler::Feature.new(source_text).tests.first.steps.first.block expect(doc_string.source_line).to eq(5) end end end describe 'doc string output' do it 'can be remade from its own output' do source = ['"""" the type', '* a step', ' \"\"\"', ' that also has a doc string', ' \"\"\"', '"""'] source = source.join("\n") doc_string = clazz.new(source) doc_string_output = doc_string.to_s remade_doc_string_output = clazz.new(doc_string_output).to_s expect(remade_doc_string_output).to eq(doc_string_output) end context 'from source text' do it 'can output an empty doc string' do source = ['"""', '"""'] source = source.join("\n") doc_string = clazz.new(source) doc_string_output = doc_string.to_s.split("\n") expect(doc_string_output).to eq(['"""', '"""']) end it 'can output a doc string that has a content type' do source = ['""" foo', '"""'] source = source.join("\n") doc_string = clazz.new(source) doc_string_output = doc_string.to_s.split("\n") expect(doc_string_output).to eq(['""" foo', '"""']) end it 'can output a doc_string that has contents' do source = ['"""', 'foo', '"""'] source = source.join("\n") doc_string = clazz.new(source) doc_string_output = doc_string.to_s.split("\n") expect(doc_string_output).to eq(['"""', 'foo', '"""']) end # Since triple double quotes mark the beginning and end of a doc string, any triple # double quotes inside of the doc string (which would have had to have been escaped # to get inside in the first place) will be escaped when outputted so as to # retain the quality of being able to use the output directly as gherkin. it 'can output a doc_string that has triple double quotes in the contents' do source = ['"""', 'a \"\"\"', '\"\"\" again', '"""'] source = source.join("\n") doc_string = clazz.new(source) doc_string_output = doc_string.to_s.split("\n") expect(doc_string_output).to eq(['"""', 'a \"\"\"', '\"\"\" again', '"""']) end # Double quotes that are not three (or more) in a row do not seem to need and special escaping when # used in Gherkin. Therefore they should be left alone. it 'only escapes triple double quotes' do source = ['"""', 'change these \"\"\"\"\"\"', 'but leave " and "" alone', '"""'] source = source.join("\n") doc_string = clazz.new(source) doc_string_output = doc_string.to_s.split("\n") expect(doc_string_output).to eq(['"""', 'change these \"\"\"\"\"\"', 'but leave " and "" alone', '"""']) end it 'can output a doc string that has everything' do source = ['""" type foo', '\"\"\"', 'bar', '\"\"\"', '"""'] source = source.join("\n") doc_string = clazz.new(source) doc_string_output = doc_string.to_s.split("\n") expect(doc_string_output).to eq(['""" type foo', '\"\"\"', 'bar', '\"\"\"', '"""']) end end end end end