Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 89 additions & 17 deletions core/matchdata/offset_spec.rb
Original file line number Diff line number Diff line change
@@ -1,30 +1,102 @@
# -*- encoding: utf-8 -*-

require_relative '../../spec_helper'

describe "MatchData#offset" do
it "returns a two element array with the begin and end of the nth match" do
match_data = /(.)(.)(\d+)(\d)/.match("THX1138.")
match_data.offset(0).should == [1, 7]
match_data.offset(4).should == [6, 7]
it "returns beginning and ending character offset of whole matched substring for 0 element" do
m = /(.)(.)(\d+)(\d)/.match("THX1138.")
m.offset(0).should == [1, 7]
end

it "returns beginning and ending character offset of n-th match, all the subsequent elements are capturing groups" do
m = /(.)(.)(\d+)(\d)/.match("THX1138.")

m.offset(2).should == [2, 3]
m.offset(3).should == [3, 6]
m.offset(4).should == [6, 7]
end

it "accepts String as a reference to a named capture" do
m = /(?<f>foo)(?<b>bar)/.match("foobar")

m.offset("f").should == [0, 3]
m.offset("b").should == [3, 6]
end

it "accepts Symbol as a reference to a named capture" do
m = /(?<f>foo)(?<b>bar)/.match("foobar")

m.offset(:f).should == [0, 3]
m.offset(:b).should == [3, 6]
end

it "returns [nil, nil] when the nth match isn't found" do
match_data = /something is( not)? (right)/.match("something is right")
match_data.offset(1).should == [nil, nil]
it "returns [nil, nil] if a capturing group is optional and doesn't match" do
m = /(?<x>q..)?/.match("foobarbaz")

m.offset("x").should == [nil, nil]
m.offset(1).should == [nil, nil]
end

it "returns the offset for multi byte strings" do
match_data = /(.)(.)(\d+)(\d)/.match("TñX1138.")
match_data.offset(0).should == [1, 7]
match_data.offset(4).should == [6, 7]
it "returns correct beginning and ending character offset for multi-byte strings" do
m = /\A\u3042(.)(.)?(.)\z/.match("\u3042\u3043\u3044")

m.offset(1).should == [1, 2]
m.offset(3).should == [2, 3]
end

not_supported_on :opal do
it "returns the offset for multi byte strings with unicode regexp" do
match_data = /(.)(.)(\d+)(\d)/u.match("TñX1138.")
match_data.offset(0).should == [1, 7]
match_data.offset(4).should == [6, 7]
it "returns correct character offset for multi-byte strings with unicode regexp" do
m = /\A\u3042(.)(.)?(.)\z/u.match("\u3042\u3043\u3044")

m.offset(1).should == [1, 2]
m.offset(3).should == [2, 3]
end
end

it "returns [nil, nil] if a capturing group is optional and doesn't match for multi-byte string" do
m = /\A\u3042(.)(.)?(.)\z/.match("\u3042\u3043\u3044")

m.offset(2).should == [nil, nil]
end

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose all the regexps with Unicode codepoints in it (like /\A\u3042..) have UTF-8 encoding and are not supported by Opal. So it makes sense at least to add a version guard for such cases.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, the similar test cases for #byteoffset aren't guarded. Nevermind.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, true. Spec for #byteoffset doesn't have any guards however, so I'm not sure what is the point here exactly.


it "converts argument into integer if is not String nor Symbol" do
m = /(?<f>foo)(?<b>bar)/.match("foobar")

obj = Object.new
def obj.to_int; 2; end

m.offset(1r).should == [0, 3]
m.offset(1.1).should == [0, 3]
m.offset(obj).should == [3, 6]
end

it "raises IndexError if there is no group with the provided name" do
m = /(?<f>foo)(?<b>bar)/.match("foobar")

-> {
m.offset("y")
}.should raise_error(IndexError, "undefined group name reference: y")

-> {
m.offset(:y)
}.should raise_error(IndexError, "undefined group name reference: y")
end

it "raises IndexError if index is out of bounds" do
m = /(?<f>foo)(?<b>bar)/.match("foobar")

-> {
m.offset(-1)
}.should raise_error(IndexError, "index -1 out of matches")

-> {
m.offset(3)
}.should raise_error(IndexError, "index 3 out of matches")
end

it "raises TypeError if can't convert argument into Integer" do
m = /(?<f>foo)(?<b>bar)/.match("foobar")

-> {
m.offset([])
}.should raise_error(TypeError, "no implicit conversion of Array into Integer")
end
end