diff options
author | Minh Nguyễn <mxn@1ec5.org> | 2017-01-04 12:19:31 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-01-04 12:19:31 -0800 |
commit | 50ae3eb3c0985567a0f86d08337d7cb8bed79a6c (patch) | |
tree | 969dd9b59f7dcbd17fa23e922fcefa5ba5de149c /platform/darwin/test | |
parent | 63b1d652f826d786e7502beb0e2abb6d78e508d2 (diff) | |
download | qtlocation-mapboxgl-50ae3eb3c0985567a0f86d08337d7cb8bed79a6c.tar.gz |
[ios, macos] Insert example code in original headers (#7569)
* [ios, macos] Removed extraneous code fences
* [ios] Streamlined example delimiters
Use test method names as names of example blocks and test method documentation comments as front matter for examples. Set off example blocks using a syntax similar to playground markup syntax. Avoid hard-coding indentation levels. Trigger Xcode build error when an error occurs in the script.
* [ios] Removed platform-specific code from examples
* [ios] Fixed logic error
The comment said 200 while the code said 1,500.
* [ios] Formalize build phase input
* [ios] Insert examples into original source documentation
Rewrote the example code insertion script to work on the original source files and overwrite any existing code examples on the same symbols. The script uses SourceKitten to find the documentation comment for the symbol named by the test method.
Replaced the Run Script build phase that runs the example code insertion script with a make rule that runs the same script. Inlined skeleton examples minus the contents of the code blocks.
* [ios] Fixed syntax error
* [ios] Ran ios-add-examples-to-docs
* [ios] Avoid touching unchanged headers
* [ios] Refactored example insertion script
* [ios] Point jazzy at original sources
* [ios] Invoke SourceKitten only once
* [ios] Look for methods as well as properties
* [ios] Thoroughly search for code blocks in doc comments
Refactored the example code insertion script to index test methods by their names, then recursively search the SourceKitten output for documentation comments that contain Swift code blocks, replacing each code block with the associated test method body.
* [ios, macos] Enabled example insertion for macOS
The example code insertion script is now platform-agnostic.
* [ios, macos] Fixed documentation example tests
Set the map view’s style to a minimal local JSON file. Wait for the style to finish loading before running each test. Corrected CGVector type.
* [ios, macos] Dry run mode
The output of this mode isn’t a good indicator of whether any files would’ve needed to be changed, because the presence of a conditional compilation block in one of the test methods means this script would always change and revert the corresponding comment.
* [ios] Fixed test failure
The iOS implementation of MGLMapView tries to show the Streets style by default even if no access token has been set. Avoid a race condition and frequent test failure by specifying the minimal style on initialization.
* [ios, macos] Ensure SourceKitten is installed before inserting example code
* [ios, macos] Tear down map view after each test
Keep map views from previous tests from hanging around, potentially obscuring the result of a subsequent test. Set the access token to a bogus token upfront for all style layer tests. Unified MGLStyle usage within MGLStyleTests.
* [ios, macos] Reinsert examples after generating runtime styling headers
Diffstat (limited to 'platform/darwin/test')
-rw-r--r-- | platform/darwin/test/MGLDocumentationExampleTests.swift | 209 | ||||
-rw-r--r-- | platform/darwin/test/MGLStyleLayerTests.m | 8 | ||||
-rw-r--r-- | platform/darwin/test/MGLStyleTests.mm | 49 | ||||
-rw-r--r-- | platform/darwin/test/one-liner.json | 1 |
4 files changed, 246 insertions, 21 deletions
diff --git a/platform/darwin/test/MGLDocumentationExampleTests.swift b/platform/darwin/test/MGLDocumentationExampleTests.swift new file mode 100644 index 0000000000..9243924328 --- /dev/null +++ b/platform/darwin/test/MGLDocumentationExampleTests.swift @@ -0,0 +1,209 @@ +import XCTest +import Mapbox +#if os(iOS) + import UIKit +#else + import Cocoa +#endif + +/** + Test cases that ensure the inline examples in the project documentation + compile. + + To add an example: + 1. Add a test case named in the form testMGLClass or testMGLClass$method. + 2. Wrap the code you'd like to appear in the documentation within the + following comment blocks: + ``` + //#-example-code + ... + //#-end-example-code + ``` + 3. Insert an empty Swift code block inside the header file where you'd like the + example code to be inserted. + 4. Run `make darwin-update-examples` to extract example code from the test + method below and insert it into the header. + */ +class MGLDocumentationExampleTests: XCTestCase, MGLMapViewDelegate { + var mapView: MGLMapView! + var styleLoadingExpectation: XCTestExpectation! + + override func setUp() { + super.setUp() + let styleURL = Bundle(for: MGLDocumentationExampleTests.self).url(forResource: "one-liner", withExtension: "json") + mapView = MGLMapView(frame: CGRect(x: 0, y: 0, width: 256, height: 256), styleURL: styleURL) + mapView.delegate = self + styleLoadingExpectation = expectation(description: "Map view should finish loading style") + waitForExpectations(timeout: 1, handler: nil) + } + + override func tearDown() { + mapView = nil + styleLoadingExpectation = nil + super.tearDown() + } + + func mapView(_ mapView: MGLMapView, didFinishLoading style: MGLStyle) { + styleLoadingExpectation.fulfill() + } + + func testMGLShapeSource() { + //#-example-code + var coordinates: [CLLocationCoordinate2D] = [ + CLLocationCoordinate2D(latitude: 37.77, longitude: -122.42), + CLLocationCoordinate2D(latitude: 38.91, longitude: -77.04), + ] + let polyline = MGLPolylineFeature(coordinates: &coordinates, count: UInt(coordinates.count)) + let shape = MGLShapeCollectionFeature(shapes: [polyline]) + let source = MGLShapeSource(identifier: "lines", shape: shape, options: nil) + mapView.style.addSource(source) + //#-end-example-code + + XCTAssertNotNil(mapView.style.source(withIdentifier: "lines")) + } + + func testMGLRasterSource() { + //#-example-code + let source = MGLRasterSource(identifier: "clouds", tileURLTemplates: ["https://example.com/raster-tiles/{z}/{x}/{y}.png"], options: [ + .minimumZoomLevel: 9, + .maximumZoomLevel: 16, + .tileSize: 512, + .attributionInfos: [ + MGLAttributionInfo(title: NSAttributedString(string: "© Mapbox"), url: URL(string: "http://mapbox.com")) + ] + ]) + mapView.style.addSource(source) + //#-end-example-code + + XCTAssertNotNil(mapView.style.source(withIdentifier: "clouds")) + } + + func testMGLVectorSource() { + //#-example-code + let source = MGLVectorSource(identifier: "pois", tileURLTemplates: ["https://example.com/vector-tiles/{z}/{x}/{y}.mvt"], options: [ + .minimumZoomLevel: 9, + .maximumZoomLevel: 16, + .attributionInfos: [ + MGLAttributionInfo(title: NSAttributedString(string: "© Mapbox"), url: URL(string: "http://mapbox.com")) + ] + ]) + mapView.style.addSource(source) + //#-end-example-code + + XCTAssertNotNil(mapView.style.source(withIdentifier: "pois")) + } + + func testMGLCircleStyleLayer() { + let population = MGLVectorSource(identifier: "population", configurationURL: URL(string: "https://example.com/style.json")!) + mapView.style.addSource(population) + + //#-example-code + let layer = MGLCircleStyleLayer(identifier: "circles", source: population) + layer.sourceLayerIdentifier = "population" + layer.circleColor = MGLStyleValue(rawValue: .green) + layer.circleRadius = MGLStyleValue(interpolationBase: 1.75, stops: [ + 12: MGLStyleValue(rawValue: 2), + 22: MGLStyleValue(rawValue: 180) + ]) + layer.circleOpacity = MGLStyleValue(rawValue: 0.7) + layer.predicate = NSPredicate(format: "%K == %@", "marital-status", "married") + mapView.style.addLayer(layer) + //#-end-example-code + + XCTAssertNotNil(mapView.style.layer(withIdentifier: "circles")) + } + + func testMGLLineStyleLayer() { + let trails = MGLVectorSource(identifier: "trails", configurationURL: URL(string: "https://example.com/style.json")!) + mapView.style.addSource(trails) + + //#-example-code + let layer = MGLLineStyleLayer(identifier: "trails-path", source: trails) + layer.sourceLayerIdentifier = "trails" + layer.lineWidth = MGLStyleValue(interpolationBase: 1.5, stops: [ + 14: MGLStyleValue(rawValue: 2), + 18: MGLStyleValue(rawValue: 20), + ]) + layer.lineColor = MGLStyleValue(rawValue: .brown) + layer.lineCap = MGLStyleValue(rawValue: NSValue(mglLineCap: .round)) + layer.predicate = NSPredicate(format: "%K == %@", "trail-type", "mountain-biking") + mapView.style.addLayer(layer) + //#-end-example-code + + XCTAssertNotNil(mapView.style.layer(withIdentifier: "trails-path")) + } + + func testMGLFillStyleLayer() { + let parks = MGLVectorSource(identifier: "parks", configurationURL: URL(string: "https://example.com/style.json")!) + mapView.style.addSource(parks) + + //#-example-code + let layer = MGLFillStyleLayer(identifier: "parks", source: parks) + layer.sourceLayerIdentifier = "parks" + layer.fillColor = MGLStyleValue(rawValue: .green) + layer.predicate = NSPredicate(format: "type == %@", "national-park") + mapView.style.addLayer(layer) + //#-end-example-code + + XCTAssertNotNil(mapView.style.layer(withIdentifier: "parks")) + } + + func testMGLSymbolStyleLayer() { + let pois = MGLVectorSource(identifier: "pois", configurationURL: URL(string: "https://example.com/style.json")!) + mapView.style.addSource(pois) + + //#-example-code + let layer = MGLSymbolStyleLayer(identifier: "coffeeshops", source: pois) + layer.sourceLayerIdentifier = "pois" + layer.iconImageName = MGLStyleValue(rawValue: "coffee") + layer.iconScale = MGLStyleValue(rawValue: 0.5) + layer.textField = MGLStyleValue(rawValue: "{name}") + #if os(macOS) + var vector = CGVector(dx: 10, dy: 0) + layer.textTranslate = MGLStyleValue(rawValue: NSValue(bytes: &vector, objCType: "{CGVector=dd}")) + #else + layer.textTranslate = MGLStyleValue(rawValue: NSValue(cgVector: CGVector(dx: 10, dy: 0))) + #endif + layer.textJustification = MGLStyleValue(rawValue: NSValue(mglTextJustification: .left)) + layer.textAnchor = MGLStyleValue(rawValue: NSValue(mglTextAnchor: .left)) + layer.predicate = NSPredicate(format: "%K == %@", "venue-type", "coffee") + mapView.style.addLayer(layer) + //#-end-example-code + + XCTAssertNotNil(mapView.style.layer(withIdentifier: "coffeeshops")) + } + + func testMGLRasterStyleLayer() { + let source = MGLRasterSource(identifier: "clouds", tileURLTemplates: ["https://example.com/raster-tiles/{z}/{x}/{y}.png"], options: [ + .minimumZoomLevel: 9, + .maximumZoomLevel: 16, + .tileSize: 512, + .attributionInfos: [ + MGLAttributionInfo(title: NSAttributedString(string: "© Mapbox"), url: URL(string: "http://mapbox.com")) + ] + ]) + mapView.style.addSource(source) + + //#-example-code + let layer = MGLRasterStyleLayer(identifier: "clouds", source: source) + layer.rasterOpacity = MGLStyleValue(rawValue: 0.5) + mapView.style.addLayer(layer) + //#-end-example-code + + XCTAssertNotNil(mapView.style.layer(withIdentifier: "clouds")) + } + + func testMGLVectorStyleLayer$predicate() { + let terrain = MGLVectorSource(identifier: "terrain", configurationURL: URL(string: "https://example.com/style.json")!) + mapView.style.addSource(terrain) + + //#-example-code + let layer = MGLLineStyleLayer(identifier: "contour", source: terrain) + layer.sourceLayerIdentifier = "contours" + layer.predicate = NSPredicate(format: "(index == 5 || index == 10) && ele >= 1500.0") + mapView.style.addLayer(layer) + //#-end-example-code + + XCTAssertNotNil(mapView.style.layer(withIdentifier: "contour")) + } +} diff --git a/platform/darwin/test/MGLStyleLayerTests.m b/platform/darwin/test/MGLStyleLayerTests.m index 590d6eda7f..66bdc0df0b 100644 --- a/platform/darwin/test/MGLStyleLayerTests.m +++ b/platform/darwin/test/MGLStyleLayerTests.m @@ -10,6 +10,7 @@ - (void)setUp { [super setUp]; + [MGLAccountManager setAccessToken:@"pk.feedcafedeadbeefbadebede"]; #if TARGET_OS_IPHONE UIApplication *app = [UIApplication sharedApplication]; UIViewController *vc = [[UIViewController alloc] init]; @@ -19,12 +20,17 @@ [vc.view addSubview:_mapView]; _mapView.delegate = self; #else - [MGLAccountManager setAccessToken:@"pk.feedcafedeadbeefbadebede"]; NSWindowController *windowController = [[NSWindowController alloc] initWithWindowNibName:@"MGLStyleLayerTests" owner:self]; [windowController showWindow:nil]; #endif } +- (void)tearDown { + _mapView = nil; + + [super tearDown]; +} + - (void)testPropertyName:(NSString *)name isBoolean:(BOOL)isBoolean { NS_MUTABLE_ARRAY_OF(NSString *) *components = [name componentsSeparatedByString:@"-"].mutableCopy; if (isBoolean) { diff --git a/platform/darwin/test/MGLStyleTests.mm b/platform/darwin/test/MGLStyleTests.mm index 55a5df08ca..bcad7ab508 100644 --- a/platform/darwin/test/MGLStyleTests.mm +++ b/platform/darwin/test/MGLStyleTests.mm @@ -1,3 +1,4 @@ +#import "MGLAccountManager.h" #import "MGLMapView.h" #import "MGLStyle_Private.h" #import "MGLOpenGLStyleLayer.h" @@ -36,9 +37,19 @@ - (void)setUp { [super setUp]; - + + [MGLAccountManager setAccessToken:@"pk.feedcafedeadbeefbadebede"]; self.mapView = [[MGLMapView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; - self.style = [[MGLStyle alloc] initWithMapView:self.mapView]; +} + +- (void)tearDown { + self.mapView = nil; + + [super tearDown]; +} + +- (MGLStyle *)style { + return self.mapView.style; } - (void)testUnversionedStyleURLs { @@ -174,18 +185,18 @@ - (void)testAddingLayersWithDuplicateIdentifiers { //Just some source MGLVectorSource *source = [[MGLVectorSource alloc] initWithIdentifier:@"my-source" configurationURL:[NSURL URLWithString:@"mapbox://mapbox.mapbox-terrain-v2"]]; - [self.mapView.style addSource: source]; + [self.style addSource: source]; //Add initial layer MGLFillStyleLayer *initial = [[MGLFillStyleLayer alloc] initWithIdentifier:@"my-layer" source:source]; - [self.mapView.style addLayer:initial]; + [self.style addLayer:initial]; //Try to add the duplicate - XCTAssertThrowsSpecificNamed([self.mapView.style addLayer:[[MGLFillStyleLayer alloc] initWithIdentifier:@"my-layer" source:source]], NSException, @"MGLRedundantLayerIdentifierException"); - XCTAssertThrowsSpecificNamed([self.mapView.style insertLayer:[[MGLFillStyleLayer alloc] initWithIdentifier:@"my-layer" source:source] belowLayer:initial],NSException, @"MGLRedundantLayerIdentifierException"); - XCTAssertThrowsSpecificNamed([self.mapView.style insertLayer:[[MGLFillStyleLayer alloc] initWithIdentifier:@"my-layer" source:source] aboveLayer:initial], NSException, @"MGLRedundantLayerIdentifierException"); - XCTAssertThrowsSpecificNamed([self.mapView.style insertLayer:[[MGLFillStyleLayer alloc] initWithIdentifier:@"my-layer" source:source] atIndex:0], NSException, @"MGLRedundantLayerIdentifierException"); - XCTAssertThrowsSpecificNamed([self.mapView.style insertLayer:[[MGLOpenGLStyleLayer alloc] initWithIdentifier:@"my-layer"] atIndex:0], NSException, @"MGLRedundantLayerIdentifierException"); + XCTAssertThrowsSpecificNamed([self.style addLayer:[[MGLFillStyleLayer alloc] initWithIdentifier:@"my-layer" source:source]], NSException, @"MGLRedundantLayerIdentifierException"); + XCTAssertThrowsSpecificNamed([self.style insertLayer:[[MGLFillStyleLayer alloc] initWithIdentifier:@"my-layer" source:source] belowLayer:initial],NSException, @"MGLRedundantLayerIdentifierException"); + XCTAssertThrowsSpecificNamed([self.style insertLayer:[[MGLFillStyleLayer alloc] initWithIdentifier:@"my-layer" source:source] aboveLayer:initial], NSException, @"MGLRedundantLayerIdentifierException"); + XCTAssertThrowsSpecificNamed([self.style insertLayer:[[MGLFillStyleLayer alloc] initWithIdentifier:@"my-layer" source:source] atIndex:0], NSException, @"MGLRedundantLayerIdentifierException"); + XCTAssertThrowsSpecificNamed([self.style insertLayer:[[MGLOpenGLStyleLayer alloc] initWithIdentifier:@"my-layer"] atIndex:0], NSException, @"MGLRedundantLayerIdentifierException"); } - (NSString *)stringWithContentsOfStyleHeader { @@ -209,8 +220,8 @@ #endif XCTAssertNotNil(image); - [self.mapView.style setImage:image forName:imageName]; - MGLImage *styleImage = [self.mapView.style imageForName:imageName]; + [self.style setImage:image forName:imageName]; + MGLImage *styleImage = [self.style imageForName:imageName]; XCTAssertNotNil(styleImage); XCTAssertEqual(image.size.width, styleImage.size.width); @@ -218,29 +229,27 @@ } - (void)testLayersOrder { - [self.mapView setStyleURL:[MGLStyle streetsStyleURLWithVersion:8]]; - NSString *filePath = [[NSBundle bundleForClass:self.class] pathForResource:@"amsterdam" ofType:@"geojson"]; NSURL *url = [NSURL fileURLWithPath:filePath]; MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"sourceID" URL:url options:nil]; - [self.mapView.style addSource:source]; + [self.style addSource:source]; MGLCircleStyleLayer *layer1 = [[MGLCircleStyleLayer alloc] initWithIdentifier:@"layer1" source:source]; - [self.mapView.style addLayer:layer1]; + [self.style addLayer:layer1]; MGLCircleStyleLayer *layer3 = [[MGLCircleStyleLayer alloc] initWithIdentifier:@"layer3" source:source]; - [self.mapView.style addLayer:layer3]; + [self.style addLayer:layer3]; MGLCircleStyleLayer *layer2 = [[MGLCircleStyleLayer alloc] initWithIdentifier:@"layer2" source:source]; - [self.mapView.style insertLayer:layer2 aboveLayer:layer1]; + [self.style insertLayer:layer2 aboveLayer:layer1]; MGLCircleStyleLayer *layer4 = [[MGLCircleStyleLayer alloc] initWithIdentifier:@"layer4" source:source]; - [self.mapView.style insertLayer:layer4 aboveLayer:layer3]; + [self.style insertLayer:layer4 aboveLayer:layer3]; MGLCircleStyleLayer *layer0 = [[MGLCircleStyleLayer alloc] initWithIdentifier:@"layer0" source:source]; - [self.mapView.style insertLayer:layer0 belowLayer:layer1]; + [self.style insertLayer:layer0 belowLayer:layer1]; - NSArray<MGLStyleLayer *> *layers = [self.mapView.style layers]; + NSArray<MGLStyleLayer *> *layers = [self.style layers]; XCTAssert([[layers[0] identifier] isEqualToString:layer0.identifier]); XCTAssert([[layers[1] identifier] isEqualToString:layer1.identifier]); diff --git a/platform/darwin/test/one-liner.json b/platform/darwin/test/one-liner.json new file mode 100644 index 0000000000..23c546181f --- /dev/null +++ b/platform/darwin/test/one-liner.json @@ -0,0 +1 @@ +{"version":8,"sources":{},"layers":[]}
\ No newline at end of file |