Thanks Driven Life

日々是感謝

include_context block 内で example を評価してもらいたかった

Capybara 2.1 の動き確認しようと

shared_context 'Capybara.exact' do |exact|
  before do
    @old_exact = Capybara.exact
    Capybara.exact = exact
  end

  after do
    Capybara.exact = @old_exact
  end
end

describe 'Capybara.exact' do
  describe 'find_button' do
    let :page do
      Capybara.string <<-STRING
        <input type="submit" value="svalue" title="stitle" />
        <button>Input Button</button>
      STRING
    end

    describe 'true' do
      include_context 'Capybara.exact', true
      
      it {
        expect { page.find_button('sva') }.to raise_error Capybara::ElementNotFound
        expect { page.find_button('Input') }.to raise_error Capybara::ElementNotFound
      }
    end
  
    describe 'false' do
      include_context 'Capybara.exact', false

      it {
        expect { page.find_button('sva') }.not_to raise_error
        expect { page.find_button('Input') }.not_to raise_error
      }
    end
  end
end

みたいなコード書いてたんですが、なんとなく

include_context 'Capybara.exact', true do
  it {
    expect { page.find_button('sva') }.to raise_error Capybara::ElementNotFound
    expect { page.find_button('Input') }.to raise_error Capybara::ElementNotFound
  }
end

include_context 'Capybara.exact', false do
  it {
    expect { page.find_button('sva') }.not_to raise_error
    expect { page.find_button('Input') }.not_to raise_error
  }
end

みたいな書き方できないかなーと思ったんですができず。

include_contextブロックは渡せるんですが 、 ↑ の書き方だと

before do
  @old_exact = Capybara.exact
  Capybara.exact = true
end

after do
  Capybara.exact = @old_exact
end

it {
  expect { page.find_button('sva') }.to raise_error Capybara::ElementNotFound
  expect { page.find_button('Input') }.to raise_error Capybara::ElementNotFound
}

before do
  @old_exact = Capybara.exact
  Capybara.exact = false
end

after do
  Capybara.exact = @old_exact
end

it {
  expect { page.find_button('sva') }.not_to raise_error
  expect { page.find_button('Input') }.not_to raise_error
}

と同義になってしまうため、Capybara.exact = true なんて無かった!って状態になる。

仕方なくこんな感じにした。

shared_context 'Capybara.exact' do |exact, proc|
  describe "Capybara.exact = #{exact.inspect}" do
    before do
      @old_exact = Capybara.exact
      Capybara.exact = exact
    end

    module_eval(&proc) if proc # <= add line

    after do
      Capybara.exact = @old_exact
    end
  end
end

describe 'Capybara.exact' do
  describe 'find_button' do
    let :page do
      Capybara.string <<-STRING
        <input type="submit" value="svalue" title="stitle" />
        <button>Input Button</button>
      STRING
    end

    include_context 'Capybara.exact', true, proc {
      it {
        expect { page.find_button('sva') }.to raise_error Capybara::ElementNotFound
        expect { page.find_button('Input') }.to raise_error Capybara::ElementNotFound
      }
    }

    include_context 'Capybara.exact', false, proc {
      it {
        expect { page.find_button('sva') }.not_to raise_error
        expect { page.find_button('Input') }.not_to raise_error
      }
    }
end

Proc 渡して module_eval

実際に動かしてたのは こんな感じ