Skip to content

Commit

Permalink
NSDateFormatter + NSNumberFormatter sanity checks
Browse files Browse the repository at this point in the history
  • Loading branch information
groue committed Feb 13, 2013
1 parent 2a25782 commit 18e25c6
Show file tree
Hide file tree
Showing 3 changed files with 239 additions and 13 deletions.
1 change: 0 additions & 1 deletion TODO.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
1.6.4:
- update obsolete sample code
- fix #warnings

Nice to have:
- document migration path from all previous versions to latest version
Expand Down
23 changes: 11 additions & 12 deletions src/classes/NSFormatter+GRMustache.m
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,14 @@ @implementation NSFormatter (GRMustache)
*/
- (id)transformedValue:(id)object
{
#warning What about nil?
#warning What about [NSNull null]?
// [NSNumberFormatter stringForObjectValue:] and
// [NSDateFormatter stringForObjectValue:] return nil or an empty string for
// nil, [NSNull null], and other off-topic values.
//
// Since nil and empty strings do not render anything, and are false when
// controlling boolean sections, we can safely say that formatters do not
// have surprising behavior: just use the plain straight
// stringForObjectValue: without any special care.
return [self stringForObjectValue:object];
}

Expand Down Expand Up @@ -78,16 +84,9 @@ - (id)mustacheTag:(GRMustacheTag *)tag willRenderObject:(id)object
// Process {{ value }}, if and only if the value is processable
if (tag.type == GRMustacheTagTypeVariable) {

// Preserve nil values
#warning Is this such a good idea to force nil preservation?
#warning What about [NSNull null]?
if (object == nil) {
return nil;
}

NSString *result = [self stringForObjectValue:object];
NSString *formatted = [self stringForObjectValue:object];

if (result == nil) {
if (formatted == nil) {
// NSFormatter documentation for stringForObjectValue: states:
//
// > First test the passed-in object to see if it’s of the correct
Expand All @@ -100,7 +99,7 @@ - (id)mustacheTag:(GRMustacheTag *)tag willRenderObject:(id)object
return object;
}

return result;
return formatted;
}

// Don't process {{# value }}, {{^ value }}, {{$ value }}
Expand Down
228 changes: 228 additions & 0 deletions src/tests/Public/v6.4/GRMustacheNSFormatterTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -150,4 +150,232 @@ - (void)testFormatterRendersSelfAsSomething
STAssertTrue(rendering.length > 0, @"");
}

- (void)testNumberFormatterRendersNothingForNil
{
// Check that NSNumberFormatter does not have surprising behavior, and
// does not format nil.
NSNumberFormatter *formatter = [[[NSNumberFormatter alloc] init] autorelease];
formatter.numberStyle = NSNumberFormatterPercentStyle;

id data = @{ @"format":formatter };

{
GRMustacheTemplate *template = [GRMustacheTemplate templateFromString:@"<{{format(value)}}>" error:NULL];
NSString *rendering = [template renderObject:data error:NULL];
STAssertEqualObjects(rendering, @"<>", @"");
}
{
GRMustacheTemplate *template = [GRMustacheTemplate templateFromString:@"{{#format(value)}}YES{{/}}{{^format(value)}}NO{{/}}" error:NULL];
NSString *rendering = [template renderObject:data error:NULL];
STAssertEqualObjects(rendering, @"NO", @"");
}
}

- (void)testNumberFormatterRendersNothingForNSNull
{
// Check that NSNumberFormatter does not have surprising behavior, and
// does not format NSNull.
NSNumberFormatter *formatter = [[[NSNumberFormatter alloc] init] autorelease];
formatter.numberStyle = NSNumberFormatterPercentStyle;

id data = @{ @"format":formatter, @"value": [NSNull null] };

{
GRMustacheTemplate *template = [GRMustacheTemplate templateFromString:@"<{{format(value)}}>" error:NULL];
NSString *rendering = [template renderObject:data error:NULL];
STAssertEqualObjects(rendering, @"<>", @"");
}
{
GRMustacheTemplate *template = [GRMustacheTemplate templateFromString:@"{{#format(value)}}YES{{/}}{{^format(value)}}NO{{/}}" error:NULL];
NSString *rendering = [template renderObject:data error:NULL];
STAssertEqualObjects(rendering, @"NO", @"");
}
}

- (void)testNumberFormatterRendersNothingForNSString
{
// Check that NSNumberFormatter does not have surprising behavior, and
// does not format NSString.
NSNumberFormatter *formatter = [[[NSNumberFormatter alloc] init] autorelease];
formatter.numberStyle = NSNumberFormatterPercentStyle;

{
id data = @{ @"format":formatter, @"value":@"1" };

{
GRMustacheTemplate *template = [GRMustacheTemplate templateFromString:@"<{{format(value)}}>" error:NULL];
NSString *rendering = [template renderObject:data error:NULL];
STAssertEqualObjects(rendering, @"<>", @"");
}
{
GRMustacheTemplate *template = [GRMustacheTemplate templateFromString:@"{{#format(value)}}YES{{/}}{{^format(value)}}NO{{/}}" error:NULL];
NSString *rendering = [template renderObject:data error:NULL];
STAssertEqualObjects(rendering, @"NO", @"");
}
}
{
id data = @{ @"format":formatter, @"value":@"YES" };

{
GRMustacheTemplate *template = [GRMustacheTemplate templateFromString:@"<{{format(value)}}>" error:NULL];
NSString *rendering = [template renderObject:data error:NULL];
STAssertEqualObjects(rendering, @"<>", @"");
}
{
GRMustacheTemplate *template = [GRMustacheTemplate templateFromString:@"{{#format(value)}}YES{{/}}{{^format(value)}}NO{{/}}" error:NULL];
NSString *rendering = [template renderObject:data error:NULL];
STAssertEqualObjects(rendering, @"NO", @"");
}
}
{
id data = @{ @"format":formatter, @"value":@"foo" };

{
GRMustacheTemplate *template = [GRMustacheTemplate templateFromString:@"<{{format(value)}}>" error:NULL];
NSString *rendering = [template renderObject:data error:NULL];
STAssertEqualObjects(rendering, @"<>", @"");
}
{
GRMustacheTemplate *template = [GRMustacheTemplate templateFromString:@"{{#format(value)}}YES{{/}}{{^format(value)}}NO{{/}}" error:NULL];
NSString *rendering = [template renderObject:data error:NULL];
STAssertEqualObjects(rendering, @"NO", @"");
}
}
}

- (void)testNumberFormatterRendersNothingForNSDate
{
// Check that NSNumberFormatter does not have surprising behavior, and
// does not format NSDate.
NSNumberFormatter *formatter = [[[NSNumberFormatter alloc] init] autorelease];
formatter.numberStyle = NSNumberFormatterPercentStyle;

id data = @{ @"format":formatter, @"value": [NSDate date] };

{
GRMustacheTemplate *template = [GRMustacheTemplate templateFromString:@"<{{format(value)}}>" error:NULL];
NSString *rendering = [template renderObject:data error:NULL];
STAssertEqualObjects(rendering, @"<>", @"");
}
{
GRMustacheTemplate *template = [GRMustacheTemplate templateFromString:@"{{#format(value)}}YES{{/}}{{^format(value)}}NO{{/}}" error:NULL];
NSString *rendering = [template renderObject:data error:NULL];
STAssertEqualObjects(rendering, @"NO", @"");
}
}

- (void)testDateFormatterRendersNothingForNil
{
// Check that NSDateFormatter does not have surprising behavior, and
// does not format nil.
NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
formatter.dateStyle = NSDateFormatterFullStyle;

id data = @{ @"format":formatter };

{
GRMustacheTemplate *template = [GRMustacheTemplate templateFromString:@"<{{format(value)}}>" error:NULL];
NSString *rendering = [template renderObject:data error:NULL];
STAssertEqualObjects(rendering, @"<>", @"");
}
{
GRMustacheTemplate *template = [GRMustacheTemplate templateFromString:@"{{#format(value)}}YES{{/}}{{^format(value)}}NO{{/}}" error:NULL];
NSString *rendering = [template renderObject:data error:NULL];
STAssertEqualObjects(rendering, @"NO", @"");
}
}

- (void)testDateFormatterRendersNothingForNSNull
{
// Check that NSDateFormatter does not have surprising behavior, and
// does not format NSNull.
NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
formatter.dateStyle = NSDateFormatterFullStyle;

id data = @{ @"format":formatter, @"value": [NSNull null] };

{
GRMustacheTemplate *template = [GRMustacheTemplate templateFromString:@"<{{format(value)}}>" error:NULL];
NSString *rendering = [template renderObject:data error:NULL];
STAssertEqualObjects(rendering, @"<>", @"");
}
{
GRMustacheTemplate *template = [GRMustacheTemplate templateFromString:@"{{#format(value)}}YES{{/}}{{^format(value)}}NO{{/}}" error:NULL];
NSString *rendering = [template renderObject:data error:NULL];
STAssertEqualObjects(rendering, @"NO", @"");
}
}

- (void)testDateFormatterRendersNothingForNSString
{
// Check that NSDateFormatter does not have surprising behavior, and
// does not format NSString.
NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
formatter.dateStyle = NSDateFormatterFullStyle;

{
id data = @{ @"format":formatter, @"value":@"1" };

{
GRMustacheTemplate *template = [GRMustacheTemplate templateFromString:@"<{{format(value)}}>" error:NULL];
NSString *rendering = [template renderObject:data error:NULL];
STAssertEqualObjects(rendering, @"<>", @"");
}
{
GRMustacheTemplate *template = [GRMustacheTemplate templateFromString:@"{{#format(value)}}YES{{/}}{{^format(value)}}NO{{/}}" error:NULL];
NSString *rendering = [template renderObject:data error:NULL];
STAssertEqualObjects(rendering, @"NO", @"");
}
}
{
id data = @{ @"format":formatter, @"value":@"YES" };

{
GRMustacheTemplate *template = [GRMustacheTemplate templateFromString:@"<{{format(value)}}>" error:NULL];
NSString *rendering = [template renderObject:data error:NULL];
STAssertEqualObjects(rendering, @"<>", @"");
}
{
GRMustacheTemplate *template = [GRMustacheTemplate templateFromString:@"{{#format(value)}}YES{{/}}{{^format(value)}}NO{{/}}" error:NULL];
NSString *rendering = [template renderObject:data error:NULL];
STAssertEqualObjects(rendering, @"NO", @"");
}
}
{
id data = @{ @"format":formatter, @"value":@"foo" };

{
GRMustacheTemplate *template = [GRMustacheTemplate templateFromString:@"<{{format(value)}}>" error:NULL];
NSString *rendering = [template renderObject:data error:NULL];
STAssertEqualObjects(rendering, @"<>", @"");
}
{
GRMustacheTemplate *template = [GRMustacheTemplate templateFromString:@"{{#format(value)}}YES{{/}}{{^format(value)}}NO{{/}}" error:NULL];
NSString *rendering = [template renderObject:data error:NULL];
STAssertEqualObjects(rendering, @"NO", @"");
}
}
}

- (void)testDateFormatterRendersNothingForNSNumber
{
// Check that NSDateFormatter does not have surprising behavior, and
// does not format NSNumber.
NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
formatter.dateStyle = NSDateFormatterFullStyle;

id data = @{ @"format":formatter, @"value": [NSNumber numberWithInteger:0] };

{
GRMustacheTemplate *template = [GRMustacheTemplate templateFromString:@"<{{format(value)}}>" error:NULL];
NSString *rendering = [template renderObject:data error:NULL];
STAssertEqualObjects(rendering, @"<>", @"");
}
{
GRMustacheTemplate *template = [GRMustacheTemplate templateFromString:@"{{#format(value)}}YES{{/}}{{^format(value)}}NO{{/}}" error:NULL];
NSString *rendering = [template renderObject:data error:NULL];
STAssertEqualObjects(rendering, @"NO", @"");
}
}

@end

0 comments on commit 18e25c6

Please sign in to comment.