require File.expand_path(File.dirname(__FILE__) + '/spec_helper')

require 'hx/path'

describe Hx::Path::Pattern do
  it "should include Hx::Path::Selector" do
    Hx::Path::Pattern.should < Hx::Path::Selector
  end

  it "should indicate literal paths as singletons" do
    pattern = Hx::Path.literal("foo/bar")
    pattern.literal?.should be_true
  end

  it "should not indicate patterns as singletons" do
    pattern = Hx::Path.parse_pattern('foo/*')
    pattern.literal?.should be_false
  end

  it "should accept or reject literal paths" do
    pattern = Hx::Path.literal("foo/bar")
    pattern.should accept_path("foo/bar")
    pattern.should_not accept_path("foo/baz")
  end

  it "should match single path components with stars" do
    pattern = Hx::Path.parse_pattern("foo/*")
    pattern.should_not accept_path("baz/eek")
    pattern.should accept_path("foo/bar")
    pattern.should_not accept_path("foo/bar/baz")
  end

  it "should match multiple path components with double stars" do
    pattern = Hx::Path.parse_pattern("foo/**")
    pattern.should_not accept_path("baz/eek")
    pattern.should accept_path("foo/bar")
    pattern.should accept_path("foo/bar/baz")
  end
end

describe "Hx::Path::Selector disjunctions" do
  it "should be possible" do
    filters = ["foo/bar", "abcdefg"].map { |p| Hx::Path.parse_pattern(p) }
    filter = filters.inject { |a, b| a | b }
    filter.should be_a_kind_of(Hx::Path::Selector)
  end

  it "should accept and reject the right paths" do
    filters = ["foo/bar", "abcdefg"].map { |p| Hx::Path.parse_pattern(p) }
    filter = filters.inject { |a, b| a | b }
    filter.should accept_path("foo/bar")
    filter.should accept_path("abcdefg")
    filter.should_not accept_path("hoge")
  end
end

describe "negated Hx::Path::Selectors" do
  before :each do
    @pattern = ~Hx::Path.parse_pattern("foo*bar")
  end

  it "should be possible" do
    @pattern.should be_a_kind_of(Hx::Path::Selector)
  end

  it "should reject what they match" do
    @pattern.should_not accept_path("foobar")
    @pattern.should accept_path("hoge")
  end
end

describe "Hx::Path::Selector conjunctions" do
  it "should be possible" do
    filters = ["foo*", "*bar"].map { |p| Hx::Path.parse_pattern(p) }
    filter = filters.inject { |a, b| a & b }
    filter.should be_a_kind_of(Hx::Path::Selector)
  end

  it "should accept only paths matching both filters" do
    filters = ["foo*", "*bar"].map { |p| Hx::Path.parse_pattern(p) }
    filter = filters.inject { |a, b| a & b }
    filter.should accept_path("foobar")
    filter.should accept_path("fooxbar")
    filter.should_not accept_path("lemur")
    filter.should_not accept_path("foobear")
    filter.should_not accept_path("rebar")
  end

  it "should optimize use of ALL" do
    filter = Hx::Path.parse_pattern("foo")
    (filter & Hx::Path::ALL).should equal(filter)
    (Hx::Path::ALL & filter).should equal(filter)
    (Hx::Path::ALL & Hx::Path::ALL).should equal(Hx::Path::ALL)
  end
end

describe Hx::Path::Selector do
  it "should define a default literal? method which returns false" do
    o = Object.new
    o.extend Hx::Path::Selector
    o.literal?.should be_false
  end

  it "should be able to elide specific circumfixes" do
    filter = Hx::Path.parse_pattern("foo").elide_circumfix("XXX", "YYY")
    filter.should accept_path("XXXfooYYY")
    filter.should_not accept_path("foo")
    filter.should_not accept_path("XXXfoo")
    filter.should_not accept_path("fooYYY")
  end

  it "should be able to assume specific circumfixes" do
    filter = Hx::Path.parse_pattern("XXXfooYYY").assume_circumfix("XXX", "YYY")
    filter.should accept_path("foo")
    filter.should_not accept_path("XXXfoo")
    filter.should_not accept_path("fooYYY")
    filter.should_not accept_path("XXXfooYYY")
  end
end