diff --git a/.travis.yml b/.travis.yml index 273f0a9c1..e29696cf7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ env: global: - - NODE_VERSION=6.11.1 + - NODE_VERSION=8.9.0 - EMULATOR_API_LEVEL=19 - ANDROID_VERSION=25 - ANDROID_BUILD_TOOLS_VERSION=25.0.2 diff --git a/CHANGELOG.md b/CHANGELOG.md index 2976d0082..4a35240ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,15 @@ + +# [5.0.0-rc.0](https://github.com/NativeScript/nativescript-angular/compare/4.4.1...5.0.0-rc.0) (2017-11-06) + +### Features + +* Initial Angular 5.0 support ([#1073](https://github.com/NativeScript/nativescript-angular/issues/1073)) + + + # [4.4.1](https://github.com/NativeScript/nativescript-angular/compare/4.4.0...4.4.1) (2017-10-13) - +> This is the last version of NativeScript Angular that supports Angular 4. ### Bug Fixes diff --git a/PULL_REQUEST_TESTS.md b/PULL_REQUEST_TESTS.md new file mode 100644 index 000000000..db4207541 --- /dev/null +++ b/PULL_REQUEST_TESTS.md @@ -0,0 +1,24 @@ +### Pull Requests Checks + +Builds distributed between Travis CI and internal Jenkins CI execute on pull requests. By default, Travis CI builds trigger on community pull requests and both Travis CI and Jenkins CI builds trigger on core team pull requests. Only NativeScript members have rights to trigger internal Jenkins CI builds. In long term, we aim to migrate all the builds in a public cloud environment. + +### Travis + +This builds the `nativescript-angular` package and the [tests](https://github.com/NativeScript/nativescript-angular/tree/master/tests) app for Android. Please, refer to the [.travis.yml](https://github.com/NativeScript/nativescript-angular/blob/master/.travis.yml) config file for complete information. + +### Jenkins + +More extensive tests execute in Jenkins CI. As it is an internal environment, these builds cannot be triggered from people outside the NativeScript organization. In order to trigger a build mannually, you need to comment inside the pull request. The table below describes the comment messages and the locations of the app/tests of all builds available to execute tests on pull requests. + +|Comment |Description| +|:------------------:|:---------:| +|`run ci` |Executes all described below.| +|`renderer-android` |Executes [renderer](https://github.com/NativeScript/nativescript-angular/tree/master/e2e/renderer) tests app for Android.| +|`renderer-ios` |Executes [renderer](https://github.com/NativeScript/nativescript-angular/tree/master/e2e/renderer) tests app for iOS.| +|`router-android` |Executes [router](https://github.com/NativeScript/nativescript-angular/tree/master/e2e/router) tests app for Android.| +|`router-ios` |Executes [router](https://github.com/NativeScript/nativescript-angular/tree/master/e2e/router) tests app for iOS.| +|`sdkwebpack` |Webpacks [SDK](https://github.com/NativeScript/nativescript-sdk-examples-ng) examples app for both Android and iOS.| +|`tests-android` |Executes [tests](https://github.com/NativeScript/nativescript-angular/tree/master/tests) app for Android.| +|`tests-ios` |Executes [tests](https://github.com/NativeScript/nativescript-angular/tree/master/tests) app for iOS.| +|`testsappng-android`|Executes [TestsAppNg](https://github.com/NativeScript/tests-app-ng) app for Android.| +|`testsappng-ios` |Executes [TestsAppNg](https://github.com/NativeScript/tests-app-ng) app for iOS.| diff --git a/e2e/renderer/e2e/ngforof.e2e-spec.ts b/e2e/renderer/e2e/ngforof.e2e-spec.ts index 23f6b0eee..e82406777 100644 --- a/e2e/renderer/e2e/ngforof.e2e-spec.ts +++ b/e2e/renderer/e2e/ngforof.e2e-spec.ts @@ -12,7 +12,8 @@ interface ElementTuple { button: UIElement, } -describe("ngForOf scenario", () => { +describe("ngForOf scenario", function () { + this.retries(2); let driver: AppiumDriver; let addButton: UIElement; let removeButton: UIElement; @@ -94,7 +95,11 @@ describe("ngForOf scenario", () => { await button.click(); } else { index = elements.length - 1; - await removeButton.click(); + if (driver.platformName.toLowerCase().includes("ios")) { + await removeButton.tap(); + } else { + await removeButton.click(); + } } elements.splice(index, 1); @@ -135,11 +140,22 @@ describe("ngForOf scenario", () => { }; const getElement = async (id: number) => { - const label = await driver.findElementByText( - "label: " + id.toString(), SearchOptions.exact); + let label = null; + let button = null; + + if (driver.platformName.toLowerCase().includes("ios")) { + label = await driver.findElementByAccessibilityId( + "label: " + id.toString()); + + button = await driver.findElementByAccessibilityId( + id.toString()); + } else { + label = await driver.findElementByText( + "label: " + id.toString(), SearchOptions.exact); - const button = await driver.findElementByText( - id.toString(), SearchOptions.exact); + button = await driver.findElementByText( + id.toString(), SearchOptions.exact); + } return { label, button }; }; diff --git a/e2e/renderer/package.json b/e2e/renderer/package.json index 94403d63c..5edac50fa 100644 --- a/e2e/renderer/package.json +++ b/e2e/renderer/package.json @@ -10,20 +10,20 @@ } }, "dependencies": { - "@angular/animations": "~4.4.1", - "@angular/common": "~4.4.1", - "@angular/compiler": "~4.4.1", - "@angular/core": "~4.4.1", - "@angular/forms": "~4.4.1", - "@angular/http": "~4.4.1", - "@angular/platform-browser": "~4.4.1", - "@angular/router": "~4.4.1", + "@angular/common": "~5.0.0", + "@angular/compiler": "~5.0.0", + "@angular/core": "~5.0.0", + "@angular/forms": "~5.0.0", + "@angular/http": "~5.0.0", + "@angular/platform-browser": "~5.0.0", + "@angular/platform-browser-dynamic": "~5.0.0", + "@angular/router": "~5.0.0", "nativescript-angular": "file:../../nativescript-angular", "nativescript-intl": "^3.0.0", "reflect-metadata": "~0.1.8", - "rxjs": "~5.3.0", + "rxjs": "^5.5.0", "tns-core-modules": "next", - "zone.js": "~0.8.2" + "zone.js": "^0.8.4" }, "devDependencies": { "@types/chai": "^4.0.2", @@ -42,10 +42,11 @@ "nativescript-dev-appium": "next", "nativescript-dev-typescript": "~0.4.0", "tslib": "^1.7.1", - "typescript": "~2.2.1" + "typescript": "~2.4.2" }, "scripts": { "e2e": "tsc -p e2e && mocha --opts ./e2e/config/mocha.opts", - "compile-tests-w": "tsc -p e2e --watch" + "compile-tests-w": "tsc -p e2e --watch", + "update-app-ng-deps": "update-app-ng-deps" } } diff --git a/e2e/router/package.json b/e2e/router/package.json index e99f48117..04c9aa423 100644 --- a/e2e/router/package.json +++ b/e2e/router/package.json @@ -6,27 +6,28 @@ "nativescript": { "id": "org.nativescript.router", "tns-android": { - "version": "3.2.0-2017-9-4-1" + "version": "next" }, "tns-ios": { - "version": "3.2.0" + "version": "next" } }, "dependencies": { "@angular/animations": "~4.4.1", - "@angular/common": "~4.4.1", - "@angular/compiler": "~4.4.1", - "@angular/core": "~4.4.1", - "@angular/forms": "~4.4.1", - "@angular/http": "~4.4.1", - "@angular/platform-browser": "~4.4.1", - "@angular/router": "~4.4.1", + "@angular/common": "~5.0.0", + "@angular/compiler": "~5.0.0", + "@angular/core": "~5.0.0", + "@angular/forms": "~5.0.0", + "@angular/http": "~5.0.0", + "@angular/platform-browser": "~5.0.0", + "@angular/router": "~5.0.0", "nativescript-angular": "file:../../nativescript-angular", "nativescript-intl": "^3.0.0", "reflect-metadata": "~0.1.8", - "rxjs": "~5.3.0", + "rxjs": "^5.5.0", "tns-core-modules": "next", - "zone.js": "~0.8.2" + "zone.js": "^0.8.4", + "@angular/platform-browser-dynamic": "~5.0.0" }, "devDependencies": { "@types/chai": "^4.0.2", @@ -45,10 +46,11 @@ "nativescript-dev-appium": "next", "nativescript-dev-typescript": "~0.4.0", "tslib": "^1.7.1", - "typescript": "~2.2.1" + "typescript": "~2.4.2" }, "scripts": { "e2e": "tsc -p e2e && mocha --opts ./e2e/config/mocha.opts", - "compile-tests-w": "tsc -p e2e --watch" + "compile-tests-w": "tsc -p e2e --watch", + "update-app-ng-deps": "update-app-ng-deps" } -} +} \ No newline at end of file diff --git a/nativescript-angular/animations/animation-driver.ts b/nativescript-angular/animations/animation-driver.ts index 369450208..29eae6f9e 100644 --- a/nativescript-angular/animations/animation-driver.ts +++ b/nativescript-angular/animations/animation-driver.ts @@ -68,6 +68,10 @@ class Selector { } export class NativeScriptAnimationDriver implements AnimationDriver { + validateStyleProperty(prop: string): boolean { + throw new Error("Not implemented!"); + } + matchesElement(element: NgView, rawSelector: string): boolean { traceLog( `NativeScriptAnimationDriver.matchesElement ` + diff --git a/nativescript-angular/bin/remove-polyfills-metadata.js b/nativescript-angular/bin/remove-polyfills-metadata.js new file mode 100644 index 000000000..4c1d4af30 --- /dev/null +++ b/nativescript-angular/bin/remove-polyfills-metadata.js @@ -0,0 +1,5 @@ +const { unlinkSync } = require("fs"); + +unlinkSync("./polyfills/console.metadata.json"); +unlinkSync("./polyfills/array.metadata.json"); + diff --git a/nativescript-angular/bin/update-app-ng-deps b/nativescript-angular/bin/update-app-ng-deps index 7676e3313..1cf6786ce 100644 --- a/nativescript-angular/bin/update-app-ng-deps +++ b/nativescript-angular/bin/update-app-ng-deps @@ -11,47 +11,34 @@ const pluginPackageJson = JSON.parse(fs.readFileSync(pluginPackageJsonPath, "utf const isNgDependency = name => name.startsWith("@angular") || name === "rxjs" || - name === "zone.js"; + name === "zone.js" || + name === "typescript"; -function updateDeps(deps, newDeps) { - // set app dependencies to ones required from plugin +function updateDeps(deps, devDeps, newDeps) { Object.keys(newDeps) .filter(isNgDependency) - .filter(dependencyName => deps.hasOwnProperty(dependencyName)) .map(dependencyName => ({ dependencyName, - version: pluginPackageJson.peerDependencies[dependencyName] + version: newDeps[dependencyName] })) - .filter(({ dependencyName, version }) => deps[dependencyName] !== version) .forEach(({ dependencyName, version }) => { - deps[dependencyName] = version; + if (devDeps[dependencyName]) { + devDeps[dependencyName] = version; + } else { + deps[dependencyName] = version; + } + console.log(`Updated dependency ${dependencyName} to version: ${version}.`); }); - - // remove platform-browser-dynamic if present - if (deps.hasOwnProperty(browserDynamicDependency)) { - delete deps[browserDynamicDependency]; - console.log(`Removed ${browserDynamicDependency}`); - } - - - return deps; } -let pluginDeps = pluginPackageJson.peerDependencies; -Object.keys(pluginPackageJson.devDependencies) - .filter(isNgDependency) - .filter(depName => !pluginDeps.hasOwnProperty(depName)) - .forEach(depName => { - pluginDeps[depName] = pluginPackageJson.devDependencies[depName]; - }); - -const projectPath = path.dirname(path.dirname(pluginPath)); +const pluginDeps = pluginPackageJson.peerDependencies; +const projectPath = process.env.INIT_CWD || path.dirname(path.dirname(pluginPath)); const appPackageJsonPath = path.join(projectPath, "package.json"); const appPackageJson = JSON.parse(fs.readFileSync(appPackageJsonPath, "utf8")); -appPackageJson.dependencies = updateDeps(appPackageJson.dependencies, pluginDeps); -appPackageJson.devDependencies = updateDeps(appPackageJson.devDependencies, pluginDeps); +const { dependencies, devDependencies } = appPackageJson; +updateDeps(dependencies, devDependencies, pluginDeps); fs.writeFileSync(appPackageJsonPath, JSON.stringify(appPackageJson, null, 2)); diff --git a/nativescript-angular/directives/list-view-comp.ts b/nativescript-angular/directives/list-view-comp.ts index 351441cce..a04f244b4 100644 --- a/nativescript-angular/directives/list-view-comp.ts +++ b/nativescript-angular/directives/list-view-comp.ts @@ -1,7 +1,6 @@ import { AfterContentInit, ChangeDetectionStrategy, - ChangeDetectorRef, Component, ContentChild, Directive, @@ -88,15 +87,14 @@ export class ListViewComponent implements DoCheck, OnDestroy, AfterContentInit { } if (needDiffer && !this._differ && isListLikeIterable(value)) { this._differ = this._iterableDiffers.find(this._items) - .create(this._cdr, (_index, item) => { return item; }); + .create((_index, item) => { return item; }); } this.listView.items = this._items; } constructor(_elementRef: ElementRef, - private _iterableDiffers: IterableDiffers, - private _cdr: ChangeDetectorRef) { + private _iterableDiffers: IterableDiffers) { this.listView = _elementRef.nativeElement; this.listView.on("itemLoading", this.onItemLoading, this); diff --git a/nativescript-angular/dom-adapter.ts b/nativescript-angular/dom-adapter.ts index e228f92a5..2a112782f 100644 --- a/nativescript-angular/dom-adapter.ts +++ b/nativescript-angular/dom-adapter.ts @@ -143,6 +143,7 @@ export class NativeScriptDomAdapter implements ɵDomAdapter { templateAwareRoot(_el: any /** TODO #9100 */): any /** TODO #9100 */ { throw new Error("Not implemented!") } createHtmlDocument(): HTMLDocument { throw new Error("Not implemented!") } defaultDoc(): HTMLDocument { throw new Error("Not implemented!") } + getDefaultDocument(): Document { throw new Error("Not implemented!") } getBoundingClientRect(_el: any /** TODO #9100 */): any /** TODO #9100 */ { throw new Error("Not implemented!") } getTitle(): string { throw new Error("Not implemented!") } setTitle(_doc: Document, _newTitle: string): any /** TODO #9100 */ { throw new Error("Not implemented!") } diff --git a/nativescript-angular/package.json b/nativescript-angular/package.json index adce98011..a60458968 100644 --- a/nativescript-angular/package.json +++ b/nativescript-angular/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "nativescript-angular", - "version": "4.4.1", + "version": "5.0.0", "description": "An Angular renderer that lets you build mobile apps with NativeScript.", "homepage": "https://www.nativescript.org/", "bugs": "https://github.com/NativeScript/nativescript-angular/issues", @@ -33,7 +33,7 @@ "postinstall": "node postinstall.js", "tsc": "tsc -p tsconfig.json", "ngc": "ngc -p tsconfig.json", - "prepublish": "npm run tsc && npm run ngc" + "prepare": "npm run ngc && node ./bin/remove-polyfills-metadata.js" }, "bin": { "update-app-ng-deps": "./bin/update-app-ng-deps" @@ -43,32 +43,35 @@ "reflect-metadata": "^0.1.8" }, "peerDependencies": { - "@angular/common": "~4.4.1", - "@angular/compiler": "~4.4.1", - "@angular/core": "~4.4.1", - "@angular/forms": "~4.4.1", - "@angular/http": "~4.4.1", - "@angular/platform-browser": "~4.4.1", - "@angular/router": "~4.4.1", - "rxjs": "^5.0.1", - "tns-core-modules": "^3.1.0 || >3.3.0-", - "zone.js": "^0.8.4" + "@angular/platform-browser-dynamic": "~5.0.0", + "@angular/common": "~5.0.0", + "@angular/compiler": "~5.0.0", + "@angular/core": "~5.0.0", + "@angular/forms": "~5.0.0", + "@angular/http": "~5.0.0", + "@angular/platform-browser": "~5.0.0", + "@angular/router": "~5.0.0", + "rxjs": "^5.5.0", + "tns-core-modules": "^3.1.0 || >3.4.0-", + "zone.js": "^0.8.4", + "typescript": "~2.4.2" }, "devDependencies": { - "@angular/animations": "~4.4.1", - "@angular/common": "~4.4.1", - "@angular/compiler": "~4.4.1", - "@angular/compiler-cli": "~4.4.1", - "@angular/core": "~4.4.1", - "@angular/forms": "~4.4.1", - "@angular/http": "~4.4.1", - "@angular/platform-browser": "~4.4.1", - "@angular/router": "~4.4.1", - "codelyzer": "^3.1.2", - "rxjs": "^5.4.2", + "@angular/platform-browser-dynamic": "~5.0.0", + "@angular/animations": "~5.0.0", + "@angular/common": "~5.0.0", + "@angular/compiler": "~5.0.0", + "@angular/compiler-cli": "~5.0.0", + "@angular/core": "~5.0.0", + "@angular/forms": "~5.0.0", + "@angular/http": "~5.0.0", + "@angular/platform-browser": "~5.0.0", + "@angular/router": "~5.0.0", + "codelyzer": "^4.0.0", + "rxjs": "^5.5.0", "tns-core-modules": "next", "tslint": "^5.5.0", - "typescript": "^2.5.1", + "typescript": "~2.4.2", "zone.js": "^0.8.12" } } diff --git a/nativescript-angular/platform-common.ts b/nativescript-angular/platform-common.ts index a5fbb67e1..19bd05efc 100644 --- a/nativescript-angular/platform-common.ts +++ b/nativescript-angular/platform-common.ts @@ -6,7 +6,7 @@ import "./zone-js/dist/zone-nativescript"; import "reflect-metadata"; import "./polyfills/array"; import "./polyfills/console"; -import { profile } from "tns-core-modules/profiling"; +import { profile, log, uptime } from "tns-core-modules/profiling"; import { Type, @@ -16,9 +16,9 @@ import { NgModuleFactory, NgModuleRef, EventEmitter, - Provider, Sanitizer, - InjectionToken + InjectionToken, + StaticProvider } from "@angular/core"; import { DOCUMENT } from "@angular/common"; @@ -54,7 +54,7 @@ export interface AppOptions { startPageActionBarHidden?: boolean; } -export type PlatformFactory = (extraProviders?: Provider[]) => PlatformRef; +export type PlatformFactory = (extraProviders?: StaticProvider[]) => PlatformRef; export class NativeScriptSanitizer extends Sanitizer { sanitize(_context: any, value: string): string { @@ -70,8 +70,8 @@ export class NativeScriptDocument { export const COMMON_PROVIDERS = [ defaultPageFactoryProvider, - { provide: Sanitizer, useClass: NativeScriptSanitizer }, - { provide: DOCUMENT, useClass: NativeScriptDocument }, + { provide: Sanitizer, useClass: NativeScriptSanitizer, deps: [] }, + { provide: DOCUMENT, useClass: NativeScriptDocument, deps: [] }, ]; export class NativeScriptPlatformRef extends PlatformRef { @@ -187,7 +187,7 @@ export class NativeScriptPlatformRef extends PlatformRef { "nativescript-angular/platform-common.postBootstrapAction"; bootstrapAction().then(profile(bootstrapMethodName, moduleRef => { // profiling.stop("ng-bootstrap"); - rendererLog("ANGULAR BOOTSTRAP DONE."); + log(`ANGULAR BOOTSTRAP DONE. ${uptime()}`); lastBootstrappedModule = new WeakRef(moduleRef); if (resolve) { diff --git a/nativescript-angular/platform.ts b/nativescript-angular/platform.ts index f1a6ad80b..03633089f 100644 --- a/nativescript-angular/platform.ts +++ b/nativescript-angular/platform.ts @@ -9,17 +9,24 @@ import { import { ElementSchemaRegistry, ResourceLoader, - COMPILER_PROVIDERS, - platformCoreDynamic } from "@angular/compiler"; +import { + ɵplatformCoreDynamic as platformCoreDynamic +} from "@angular/platform-browser-dynamic"; + +import { + ɵINTERNAL_BROWSER_PLATFORM_PROVIDERS as INTERNAL_BROWSER_PLATFORM_PROVIDERS +} from "@angular/platform-browser"; + import { COMPILER_OPTIONS, PlatformRef, InjectionToken, ViewEncapsulation, createPlatformFactory, - MissingTranslationStrategy + MissingTranslationStrategy, + StaticProvider, } from "@angular/core"; // Work around a TS bug requiring an imports of @@ -35,18 +42,16 @@ if ((global).___TS_UNUSED) { import "./dom-adapter"; import { NativeScriptElementSchemaRegistry } from "./schema-registry"; -import { NSFileSystem } from "./file-system/ns-file-system"; import { FileSystemResourceLoader } from "./resource-loader"; -export const NS_COMPILER_PROVIDERS = [ - COMPILER_PROVIDERS, +export const NS_COMPILER_PROVIDERS: StaticProvider[] = [ + INTERNAL_BROWSER_PLATFORM_PROVIDERS, { provide: COMPILER_OPTIONS, useValue: { providers: [ - NSFileSystem, - { provide: ResourceLoader, useClass: FileSystemResourceLoader }, - { provide: ElementSchemaRegistry, useClass: NativeScriptElementSchemaRegistry }, + { provide: ResourceLoader, useClass: FileSystemResourceLoader, deps: [] }, + { provide: ElementSchemaRegistry, useClass: NativeScriptElementSchemaRegistry, deps: [] }, ] }, multi: true diff --git a/nativescript-angular/resource-loader.ts b/nativescript-angular/resource-loader.ts index 43a5091bc..10c1ee759 100644 --- a/nativescript-angular/resource-loader.ts +++ b/nativescript-angular/resource-loader.ts @@ -12,8 +12,12 @@ const extensionsFallbacks = [ @Injectable() export class FileSystemResourceLoader extends ResourceLoader { - constructor(private fs: NSFileSystem) { + fs: NSFileSystem; + + constructor() { super(); + + this.fs = new NSFileSystem(); } get(url: string): Promise { @@ -57,7 +61,7 @@ export class FileSystemResourceLoader extends ResourceLoader { const candidates = extensionsFallbacks .filter(([extension]) => url.endsWith(extension)) .map(([extension, fallback]) => - this.replaceExtension(url, extension, fallback)); + this.replaceExtension(url, extension, fallback)); const resource = candidates.find(candidate => this.fs.fileExists(candidate)); diff --git a/nativescript-angular/router/page-router-outlet.ts b/nativescript-angular/router/page-router-outlet.ts index 2695026c4..3737dd7d5 100644 --- a/nativescript-angular/router/page-router-outlet.ts +++ b/nativescript-angular/router/page-router-outlet.ts @@ -359,13 +359,11 @@ export class PageRouterOutlet implements OnDestroy, OnInit { // tslint:disable-l log("Activated route marked as page: " + routeToString(nodeToMark)); } - // NOTE: Using private APIs - potential break point! private getComponentFactory( - activatedRoute: any, + activatedRoute: ActivatedRoute, loadedResolver: ComponentFactoryResolver ): ComponentFactory { - const snapshot = activatedRoute._futureSnapshot; - const component = snapshot._routeConfig.component; + const { component } = activatedRoute.routeConfig; return loadedResolver ? loadedResolver.resolveComponentFactory(component) : diff --git a/tests/app/base.component.ts b/tests/app/base.component.ts index 6909d5921..2ca048204 100644 --- a/tests/app/base.component.ts +++ b/tests/app/base.component.ts @@ -1,5 +1,5 @@ -import { OpaqueToken, OnInit, OnDestroy } from "@angular/core"; -export const HOOKS_LOG = new OpaqueToken("Hooks log"); +import { InjectionToken, OnInit, OnDestroy } from "@angular/core"; +export const HOOKS_LOG = new InjectionToken("Hooks log"); import { BehaviorSubject } from "rxjs/BehaviorSubject"; export class BaseComponent implements OnInit, OnDestroy { diff --git a/tests/app/logo.png b/tests/app/logo.png new file mode 100644 index 000000000..add1ce15d Binary files /dev/null and b/tests/app/logo.png differ diff --git a/tests/app/main.ts b/tests/app/main.ts index ce33b3f50..f5c652ff7 100644 --- a/tests/app/main.ts +++ b/tests/app/main.ts @@ -24,7 +24,7 @@ import { SinglePageMain, routes as singlePageRoutes } from "./single-page-main.c import { LazyLoadMain, routes as lazyLoadRoutes } from "./lazy-load-main"; import { FirstComponent } from "./first.component"; import { SecondComponent } from "./second.component"; -import { OpaqueToken, NgModule, NgModuleFactoryLoader } from "@angular/core"; +import { InjectionToken, NgModule, NgModuleFactoryLoader } from "@angular/core"; import { PageNavigationApp } from "./snippets/navigation/page-outlet"; import { NavigationApp } from "./snippets/navigation/router-outlet"; diff --git a/tests/app/tests/renderer-tests.ts b/tests/app/tests/renderer-tests.ts index 3c2ccd506..ebb9091ee 100644 --- a/tests/app/tests/renderer-tests.ts +++ b/tests/app/tests/renderer-tests.ts @@ -1,6 +1,6 @@ // make sure you import mocha-config before @angular/core import { assert } from "./test-config"; -import { Component, ElementRef, Renderer2, NgZone } from "@angular/core"; +import { Component, ElementRef, Renderer2, NgZone, ViewChild } from "@angular/core"; import { ProxyViewContainer } from "ui/proxy-view-container"; import { Red } from "color/known-colors"; import { dumpView } from "./test-utils"; @@ -10,6 +10,9 @@ import { StackLayout } from "ui/layouts/stack-layout"; import { ContentView } from "ui/content-view"; import { Button } from "ui/button"; import { NgView } from "nativescript-angular/element-registry"; +import { registerElement } from "nativescript-angular/element-registry"; +import * as button from "tns-core-modules/ui/button"; +import * as view from "tns-core-modules/ui/core/view"; @Component({ template: `` @@ -169,6 +172,60 @@ export class NgIfThenElseComponent { } } +export class ButtonCounter extends button.Button { + nativeBackgroundRedraws = 0; + backgroundInternalSetNativeCount = 0; + fontInternalSetNativeCount = 0; + + [view.backgroundInternalProperty.setNative](value) { + this.backgroundInternalSetNativeCount++; + return super[view.backgroundInternalProperty.setNative](value); + } + [view.fontInternalProperty.setNative](value) { + this.fontInternalSetNativeCount++; + return super[view.fontInternalProperty.setNative](value); + } + _redrawNativeBackground(value: any): void { + this.nativeBackgroundRedraws++; + super["_redrawNativeBackground"](value); + } +} +registerElement("ButtonCounter", () => ButtonCounter); + +@Component({ + selector: "ng-control-setters-count", + template: ` + + + + + + + `, + styles: [` + #btn2, #btn3, #btn4 { + border-width: 2; + border-color: teal; + border-radius: 20; + font-weight: 400; + font-size: 32; + }`] +}) +export class NgControlSettersCount { + @ViewChild("btn1") btn1: ElementRef; + @ViewChild("btn2") btn2: ElementRef; + @ViewChild("btn3") btn3: ElementRef; + @ViewChild("btn3") btn4: ElementRef; + + get buttons(): ElementRef[] { return [this.btn1, this.btn2, this.btn3, this.btn4]; } + + isAfterViewInit: boolean = false; + + ngAfterViewInit() { + this.isAfterViewInit = true; + } +} + @Component({ selector: "ng-for-label", template: `` @@ -488,7 +545,6 @@ describe("Renderer createElement", () => { }); }); - describe("Renderer attach/detach", () => { let testApp: TestApp = null; let renderer: Renderer2 = null; @@ -545,3 +601,36 @@ describe("Renderer attach/detach", () => { }); }); +describe("Renderer lifecycle", () => { + let testApp: TestApp = null; + let renderer: Renderer2 = null; + + before(() => { + return TestApp.create([], [NgControlSettersCount]).then((app) => { + testApp = app; + renderer = testApp.renderer; + }); + }); + + after(() => { + testApp.dispose(); + }); + + afterEach(() => { + testApp.disposeComponents(); + }); + + it("view native setters are called once on startup", () => { + return testApp.loadComponent(NgControlSettersCount).then((componentRef) => { + assert.isTrue(componentRef.instance.isAfterViewInit, "Expected the NgControlSettersCount to have passed its ngAfterViewInit."); + componentRef.instance.buttons.map(btn => btn.nativeElement).forEach(btn => { + assert.isTrue(btn.isLoaded, `Expected ${btn.id} to be allready loaded.`); + assert.isFalse(btn.isLayoutValid, `Expected ${btn.id}'s layout to be invalid.`); + + assert.equal(btn.backgroundInternalSetNativeCount, 1, `Expected ${btn.id} backgroundInternalSetNativeCount to be called just once.`); + assert.equal(btn.fontInternalSetNativeCount, 1, `Expected ${btn.id} fontInternalSetNativeCount to be called just once.`); + assert.equal(btn.nativeBackgroundRedraws, 0, `Expected ${btn.id} nativeBackgroundRedraws to be called after its layout pass.`); + }); + }); + }); +}); diff --git a/tests/app/tests/test-app.ts b/tests/app/tests/test-app.ts index 33399903a..fd481c67c 100644 --- a/tests/app/tests/test-app.ts +++ b/tests/app/tests/test-app.ts @@ -30,7 +30,7 @@ export class TestApp { registerTestApp(TestApp, this, appRef); } - public loadComponent(componentType: Type): Promise> { + public loadComponent(componentType: Type): Promise> { const factory = this.resolver.resolveComponentFactory(componentType); const componentRef = this.containerRef.createComponent( factory, this.containerRef.length, this.containerRef.parentInjector); diff --git a/tests/app/tests/xhr-paths.ts b/tests/app/tests/xhr-paths.ts index c3de6a6dc..818d59e17 100644 --- a/tests/app/tests/xhr-paths.ts +++ b/tests/app/tests/xhr-paths.ts @@ -25,7 +25,8 @@ const fsMock = new NSFileSystemMock(); describe("XHR name resolution", () => { let resourceLoader: FileSystemResourceLoader; before(() => { - resourceLoader = new FileSystemResourceLoader(new NSFileSystemMock()); + resourceLoader = new FileSystemResourceLoader(); + resourceLoader.fs = new NSFileSystemMock(); }); it("resolves relative paths from app root", () => { diff --git a/tests/package.json b/tests/package.json index 9cfb0bb66..38bef7bb7 100644 --- a/tests/package.json +++ b/tests/package.json @@ -27,19 +27,19 @@ "homepage": "http://nativescript.org", "dependencies": { "@angular/animations": "~4.4.1", - "@angular/common": "~4.4.1", - "@angular/compiler": "~4.4.1", - "@angular/core": "~4.4.1", - "@angular/forms": "~4.4.1", - "@angular/http": "~4.4.1", - "@angular/platform-browser": "~4.4.1", - "@angular/platform-browser-dynamic": "~4.4.1", - "@angular/router": "~4.4.1", + "@angular/common": "~5.0.0", + "@angular/compiler": "~5.0.0", + "@angular/core": "~5.0.0", + "@angular/forms": "~5.0.0", + "@angular/http": "~5.0.0", + "@angular/platform-browser": "~5.0.0", + "@angular/platform-browser-dynamic": "~5.0.0", + "@angular/router": "~5.0.0", "nativescript-angular": "../nativescript-angular", "nativescript-unit-test-runner": "^0.3.4", - "rxjs": "^5.2.0", + "rxjs": "^5.5.0", "tns-core-modules": "next", - "zone.js": "^0.8.2" + "zone.js": "^0.8.4" }, "devDependencies": { "@types/chai": "^4.0.2", @@ -66,11 +66,12 @@ "socket.io-client": "1.4.8", "tslib": "^1.7.1", "tslint": "^4.5.1", - "typescript": "~2.5.0", + "typescript": "~2.4.2", "mocha": "~3.5.0" }, "scripts": { "e2e": "tsc -p e2e && mocha --opts ./e2e/config/mocha.opts", - "compile-tests-w": "tsc -p e2e --watch" + "compile-tests-w": "tsc -p e2e --watch", + "update-app-ng-deps": "update-app-ng-deps" } }