Skip to content
This repository was archived by the owner on Feb 2, 2023. It is now read-only.

Commit 72fca53

Browse files
committed
Inject an ASDataController class to ASTableView, for testing purposes
- Injection can be done via a new internal initializer. The class will be used by ASTableView to create (and configure) a new data controller. - ASTableViewTests now injects its own type of ASDataController. This facilitates new ways for testing ASTableView-specific behaviours. The first application is counting the number of times relayoutAllNodes is called on the data controller.
1 parent 048566a commit 72fca53

File tree

4 files changed

+93
-15
lines changed

4 files changed

+93
-15
lines changed

AsyncDisplayKit.xcodeproj/project.pbxproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,8 @@
254254
AC47D9451B3BB41900AAEE9D /* ASRelativeSize.h in Headers */ = {isa = PBXBuildFile; fileRef = AC47D9431B3BB41900AAEE9D /* ASRelativeSize.h */; settings = {ATTRIBUTES = (Public, ); }; };
255255
AC47D9461B3BB41900AAEE9D /* ASRelativeSize.mm in Sources */ = {isa = PBXBuildFile; fileRef = AC47D9441B3BB41900AAEE9D /* ASRelativeSize.mm */; };
256256
AC6456091B0A335000CF11B8 /* ASCellNode.m in Sources */ = {isa = PBXBuildFile; fileRef = AC6456071B0A335000CF11B8 /* ASCellNode.m */; };
257+
AC7A2C171BDE11DF0093FE1A /* ASTableViewInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = AC7A2C161BDE11DF0093FE1A /* ASTableViewInternal.h */; };
258+
AC7A2C181BDE11DF0093FE1A /* ASTableViewInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = AC7A2C161BDE11DF0093FE1A /* ASTableViewInternal.h */; };
257259
ACC945A91BA9E7A0005E1FB8 /* ASViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = ACC945A81BA9E7A0005E1FB8 /* ASViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
258260
ACC945AB1BA9E7C1005E1FB8 /* ASViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = ACC945AA1BA9E7C1005E1FB8 /* ASViewController.m */; };
259261
ACF6ED1A1B17843500DA7C62 /* ASBackgroundLayoutSpec.h in Headers */ = {isa = PBXBuildFile; fileRef = ACF6ED011B17843500DA7C62 /* ASBackgroundLayoutSpec.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -617,6 +619,7 @@
617619
AC47D9431B3BB41900AAEE9D /* ASRelativeSize.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASRelativeSize.h; path = AsyncDisplayKit/Layout/ASRelativeSize.h; sourceTree = "<group>"; };
618620
AC47D9441B3BB41900AAEE9D /* ASRelativeSize.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ASRelativeSize.mm; path = AsyncDisplayKit/Layout/ASRelativeSize.mm; sourceTree = "<group>"; };
619621
AC6456071B0A335000CF11B8 /* ASCellNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASCellNode.m; sourceTree = "<group>"; };
622+
AC7A2C161BDE11DF0093FE1A /* ASTableViewInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASTableViewInternal.h; sourceTree = "<group>"; };
620623
ACC945A81BA9E7A0005E1FB8 /* ASViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASViewController.h; sourceTree = "<group>"; };
621624
ACC945AA1BA9E7C1005E1FB8 /* ASViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASViewController.m; sourceTree = "<group>"; };
622625
ACF6ED011B17843500DA7C62 /* ASBackgroundLayoutSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASBackgroundLayoutSpec.h; path = AsyncDisplayKit/Layout/ASBackgroundLayoutSpec.h; sourceTree = "<group>"; };
@@ -803,6 +806,7 @@
803806
D785F6611A74327E00291744 /* ASScrollNode.m */,
804807
055F1A3219ABD3E3004DAFF1 /* ASTableView.h */,
805808
055F1A3319ABD3E3004DAFF1 /* ASTableView.mm */,
809+
AC7A2C161BDE11DF0093FE1A /* ASTableViewInternal.h */,
806810
0574D5E119C110610097DC25 /* ASTableViewProtocols.h */,
807811
058D09DF195D050800B7D73C /* ASTextNode.h */,
808812
058D09E0195D050800B7D73C /* ASTextNode.mm */,
@@ -1128,6 +1132,7 @@
11281132
058D0A4C195D05CB00B7D73C /* ASDisplayNode+Subclasses.h in Headers */,
11291133
058D0A4A195D05CB00B7D73C /* ASDisplayNode.h in Headers */,
11301134
058D0A84195D060300B7D73C /* ASDisplayNodeExtraIvars.h in Headers */,
1135+
AC7A2C171BDE11DF0093FE1A /* ASTableViewInternal.h in Headers */,
11311136
058D0A4D195D05CB00B7D73C /* ASDisplayNodeExtras.h in Headers */,
11321137
058D0A7B195D05F900B7D73C /* ASDisplayNodeInternal.h in Headers */,
11331138
0587F9BD1A7309ED00AFF0BA /* ASEditableTextNode.h in Headers */,
@@ -1243,6 +1248,7 @@
12431248
B350625B1B010F070018CF92 /* ASEqualityHelpers.h in Headers */,
12441249
B350621B1B010EFD0018CF92 /* ASFlowLayoutController.h in Headers */,
12451250
B350621D1B010EFD0018CF92 /* ASHighlightOverlayLayer.h in Headers */,
1251+
AC7A2C181BDE11DF0093FE1A /* ASTableViewInternal.h in Headers */,
12461252
B35062531B010EFD0018CF92 /* ASImageNode+CGExtras.h in Headers */,
12471253
B35062021B010EFD0018CF92 /* ASImageNode.h in Headers */,
12481254
B350621F1B010EFD0018CF92 /* ASImageProtocols.h in Headers */,

AsyncDisplayKit/ASTableView.mm

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
*/
88

99
#import "ASTableView.h"
10+
#import "ASTableViewInternal.h"
1011

1112
#import "ASAssert.h"
1213
#import "ASChangeSetDataController.h"
@@ -155,7 +156,6 @@ @interface ASTableView () <ASRangeControllerDelegate, ASDataControllerSource, _A
155156
_ASTableViewProxy *_proxyDataSource;
156157
_ASTableViewProxy *_proxyDelegate;
157158

158-
ASDataController *_dataController;
159159
ASFlowLayoutController *_layoutController;
160160

161161
ASRangeController *_rangeController;
@@ -174,6 +174,7 @@ @interface ASTableView () <ASRangeControllerDelegate, ASDataControllerSource, _A
174174
}
175175

176176
@property (atomic, assign) BOOL asyncDataSourceLocked;
177+
@property (nonatomic, retain, readwrite) ASDataController *dataController;
177178

178179
@end
179180

@@ -199,24 +200,29 @@ void ASPerformBlockWithoutAnimation(BOOL withoutAnimation, void (^block)()) {
199200
}
200201
}
201202

203+
+ (Class)dataControllerClass
204+
{
205+
return [ASChangeSetDataController class];
206+
}
207+
202208
#pragma mark -
203209
#pragma mark Lifecycle
204210

205-
- (void)configureWithAsyncDataFetching:(BOOL)asyncDataFetchingEnabled
211+
- (void)configureWithDataControllerClass:(Class)dataControllerClass asyncDataFetching:(BOOL)asyncDataFetching
206212
{
207213
_layoutController = [[ASFlowLayoutController alloc] initWithScrollOption:ASFlowLayoutDirectionVertical];
208214

209215
_rangeController = [[ASRangeController alloc] init];
210216
_rangeController.layoutController = _layoutController;
211217
_rangeController.delegate = self;
212-
213-
_dataController = [[ASChangeSetDataController alloc] initWithAsyncDataFetching:asyncDataFetchingEnabled];
218+
219+
_dataController = [[dataControllerClass alloc] initWithAsyncDataFetching:asyncDataFetching];
214220
_dataController.dataSource = self;
215221
_dataController.delegate = _rangeController;
216222

217223
_layoutController.dataSource = _dataController;
218224

219-
_asyncDataFetchingEnabled = asyncDataFetchingEnabled;
225+
_asyncDataFetchingEnabled = asyncDataFetching;
220226
_asyncDataSourceLocked = NO;
221227

222228
_leadingScreensForBatching = 1.0;
@@ -236,6 +242,11 @@ - (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style
236242
}
237243

238244
- (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style asyncDataFetching:(BOOL)asyncDataFetchingEnabled
245+
{
246+
return [self initWithFrame:frame style:style dataControllerClass:[self.class dataControllerClass] asyncDataFetching:asyncDataFetchingEnabled];
247+
}
248+
249+
- (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style dataControllerClass:(Class)dataControllerClass asyncDataFetching:(BOOL)asyncDataFetchingEnabled
239250
{
240251
if (!(self = [super initWithFrame:frame style:style]))
241252
return nil;
@@ -244,8 +255,8 @@ - (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style asyncD
244255
// https://github.com/facebook/AsyncDisplayKit/issues/385
245256
asyncDataFetchingEnabled = NO;
246257

247-
[self configureWithAsyncDataFetching:asyncDataFetchingEnabled];
248-
258+
[self configureWithDataControllerClass:dataControllerClass asyncDataFetching:asyncDataFetchingEnabled];
259+
249260
return self;
250261
}
251262

@@ -254,7 +265,7 @@ - (instancetype)initWithCoder:(NSCoder *)aDecoder
254265
if (!(self = [super initWithCoder:aDecoder]))
255266
return nil;
256267

257-
[self configureWithAsyncDataFetching:NO];
268+
[self configureWithDataControllerClass:[self.class dataControllerClass] asyncDataFetching:NO];
258269

259270
return self;
260271
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//
2+
// ASTableViewInternal.h
3+
// AsyncDisplayKit
4+
//
5+
// Created by Huy Nguyen on 26/10/15.
6+
// Copyright (c) 2015 Facebook. All rights reserved.
7+
//
8+
9+
#import "ASTableView.h"
10+
11+
@class ASDataController;
12+
13+
@interface ASTableView (Internal)
14+
15+
@property (nonatomic, retain, readonly) ASDataController *dataController;
16+
17+
/**
18+
* Initializer.
19+
*
20+
* @param frame A rectangle specifying the initial location and size of the table view in its superview’€™s coordinates.
21+
* The frame of the table view changes as table cells are added and deleted.
22+
*
23+
* @param style A constant that specifies the style of the table view. See UITableViewStyle for descriptions of valid constants.
24+
*
25+
* @param dataControllerClass A controller class injected to and used to create a data controller for the table view.
26+
*
27+
* @param asyncDataFetchingEnabled This option is reserved for future use, and currently a no-op.
28+
*/
29+
- (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style dataControllerClass:(Class)dataControllerClass asyncDataFetching:(BOOL)asyncDataFetchingEnabled;
30+
31+
@end

AsyncDisplayKitTests/ASTableViewTests.m

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,44 @@
99
#import <XCTest/XCTest.h>
1010

1111
#import "ASTableView.h"
12+
#import "ASTableViewInternal.h"
1213
#import "ASDisplayNode+Subclasses.h"
14+
#import "ASChangeSetDataController.h"
1315

1416
#define NumberOfSections 10
1517
#define NumberOfRowsPerSection 20
1618
#define NumberOfReloadIterations 50
1719

20+
@interface ASTestDataController : ASChangeSetDataController
21+
@property (atomic) int numberOfAllNodesRelayouts;
22+
@end
23+
24+
@implementation ASTestDataController
25+
26+
- (void)relayoutAllNodes
27+
{
28+
_numberOfAllNodesRelayouts++;
29+
[super relayoutAllNodes];
30+
}
31+
32+
@end
33+
1834
@interface ASTestTableView : ASTableView
1935
@property (atomic, copy) void (^willDeallocBlock)(ASTableView *tableView);
2036
@end
2137

2238
@implementation ASTestTableView
2339

40+
- (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style asyncDataFetching:(BOOL)asyncDataFetchingEnabled
41+
{
42+
return [super initWithFrame:frame style:style dataControllerClass:[ASTestDataController class] asyncDataFetching:asyncDataFetchingEnabled];
43+
}
44+
45+
- (ASTestDataController *)testDataController
46+
{
47+
return (ASTestDataController *)self.dataController;
48+
}
49+
2450
- (void)dealloc
2551
{
2652
if (_willDeallocBlock) {
@@ -219,7 +245,7 @@ - (void)testReloadData
219245
}
220246
}
221247

222-
- (void)testRelayoutAllRowsWithNonZeroSizeInitially
248+
- (void)testRelayoutAllNodesWithNonZeroSizeInitially
223249
{
224250
// Initial width of the table view is non-zero and all nodes are measured with this size.
225251
// Any subsequence size change must trigger a relayout.
@@ -233,12 +259,14 @@ - (void)testRelayoutAllRowsWithNonZeroSizeInitially
233259

234260
tableView.asyncDelegate = dataSource;
235261
tableView.asyncDataSource = dataSource;
262+
263+
[tableView layoutIfNeeded];
236264

237-
[self triggerFirstLayoutMeasurementForTableView:tableView];
238-
[self triggerSizeChangeAndAssertRelayoutAllRowsForTableView:tableView newSize:tableViewFinalSize];
265+
XCTAssertEqual(tableView.testDataController.numberOfAllNodesRelayouts, 0);
266+
[self triggerSizeChangeAndAssertRelayoutAllNodesForTableView:tableView newSize:tableViewFinalSize];
239267
}
240268

241-
- (void)testRelayoutAllRowsWithZeroSizeInitially
269+
- (void)testRelayoutAllNodesWithZeroSizeInitially
242270
{
243271
// Initial width of the table view is 0. The first size change is part of the initial config.
244272
// Any subsequence size change after that must trigger a relayout.
@@ -256,10 +284,10 @@ - (void)testRelayoutAllRowsWithZeroSizeInitially
256284
[superview addSubview:tableView];
257285
// Width and height are swapped so that a later size change will simulate a rotation
258286
tableView.frame = CGRectMake(0, 0, tableViewFinalSize.height, tableViewFinalSize.width);
259-
// Trigger layout measurement on all nodes
260287
[tableView layoutIfNeeded];
261288

262-
[self triggerSizeChangeAndAssertRelayoutAllRowsForTableView:tableView newSize:tableViewFinalSize];
289+
XCTAssertEqual(tableView.testDataController.numberOfAllNodesRelayouts, 0);
290+
[self triggerSizeChangeAndAssertRelayoutAllNodesForTableView:tableView newSize:tableViewFinalSize];
263291
}
264292

265293
- (void)testRelayoutVisibleRowsWhenEditingModeIsChanged
@@ -407,7 +435,7 @@ - (void)triggerFirstLayoutMeasurementForTableView:(ASTableView *)tableView{
407435
}];
408436
}
409437

410-
- (void)triggerSizeChangeAndAssertRelayoutAllRowsForTableView:(ASTableView *)tableView newSize:(CGSize)newSize
438+
- (void)triggerSizeChangeAndAssertRelayoutAllNodesForTableView:(ASTestTableView *)tableView newSize:(CGSize)newSize
411439
{
412440
XCTestExpectation *nodesMeasuredUsingNewConstrainedSizeExpectation = [self expectationWithDescription:@"nodesMeasuredUsingNewConstrainedSize"];
413441

@@ -419,6 +447,8 @@ - (void)triggerSizeChangeAndAssertRelayoutAllRowsForTableView:(ASTableView *)tab
419447
[tableView layoutIfNeeded];
420448

421449
[tableView endUpdatesAnimated:NO completion:^(BOOL completed) {
450+
XCTAssertEqual(tableView.testDataController.numberOfAllNodesRelayouts, 1);
451+
422452
for (int section = 0; section < NumberOfSections; section++) {
423453
for (int row = 0; row < NumberOfRowsPerSection; row++) {
424454
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:section];

0 commit comments

Comments
 (0)