tj / should.js

BDD style assertions for node.js -- test framework agnostic
MIT License
2.75k stars 194 forks source link

Sane way to count match length? #134

Closed leeola closed 11 years ago

leeola commented 11 years ago

In the following example, is there a way for Should.js to handle this cleanly?

foo.should.match(/some pattern/g).length.should.eql 5

The goal is to match the pattern, but also count the pattern matches, ensuring it is as expected.

The only workaround i can think of is simply checking it twice:

pattern = /some pattern/g
foo.should.match(pattern)
foo.match(pattern).length.should.eql(5)

But that is a bit ugly, mainly due to the pattern assignment and checking for a match in two different ways.

Thoughts?

leeola commented 11 years ago

Actually, i think the sanest way would be to not check them both. Simply checking the number would suffice.

I retract my issue, and blame the beer.

leeola commented 11 years ago

Actually it's not insane, perhaps. foo.match(/zero matches/) returns null, so you can't cleanly write foo.match(/pattern/g).length.should.equal(5), you have to get even more cryptic and write should.equal(5, foo.match(pattern/g).length)

Is there any way this can be supported better? Or should i just suck it up :)

btd commented 11 years ago

We can add second optional argument for #match(regex[, count]). What do you think? I cannot say i like this solution, i would like to have way to use <, <=, =>, =, > for number of matches.

leeola commented 11 years ago

No idea about the best syntax, but on your example, #match(regex[, count]) with #match(regex[, lowrange, upperrange]) might be a way to get close.

It seems to be against the wordy style of Shouldjs though. Eg, match(regex).and.count.within(5,7) or something reads better.. though the implementation might be a nightmare.

travisjeffery commented 11 years ago

so far i'm -1 on changing. separate checks is best so far.

leeola commented 11 years ago

I'm fine with separate checks, but is there a way we could clean the syntax at all? Is should.equal(5, foo.match(pattern/g).length) really the best way Should can offer?

travisjeffery commented 11 years ago

use this:

it.match(pattern).should.have.length(3);

and if you don't like it would fail with message: TypeError: Cannot read property 'should' of null then put this line above: it.should.match(pattern);

and you'll get: AssertionError: expected 'foofoofoo' to match /bar/g.

So altogether:

it.should.match(pattern);
it.match(pattern).should.have.length(3)

is clear and is what you want.

leeola commented 11 years ago

Yea, as i said in my original message i dislike matching the pattern twice. It seems needlessly verbose, and duplication of code needlessly is always a bit of an annoyance, in my opinion.

3 lines per pattern match seems crazy (one to store the pattern, one to test the pattern, one to count the pattern), and seems to go against the chained design of Should.js (again, imo).

At any rate, if duplication is the only way Should.js can handle this scenario, then so be it