diff --git a/.gitignore b/.gitignore index c664afff9..34972675d 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,4 @@ src/ui_ng/aot/**/*.json **/*ngsummary.json **/*ngfactory.ts +**/aot diff --git a/src/ui_ng/lib/angular-cli.json b/src/ui_ng/lib/angular-cli.json index 6c2a4b6a1..cb506228f 100644 --- a/src/ui_ng/lib/angular-cli.json +++ b/src/ui_ng/lib/angular-cli.json @@ -4,28 +4,24 @@ "name": "harbor-ui" }, "apps": [{ - "root": ".", - "outDir": "../dist", - "assets": [ - "images", - "favicon.ico" - ], - "index": "index.html", - "main": "index.ts", + "root": "src", + "outDir": "dist", + "index": "index.ts", + "main": "main.ts", "test": "test.ts", "tsconfig": "tsconfig.json", "prefix": "", "mobile": false, "styles": [ - "node_modules/clarity-icons/clarity-icons.min.css", - "node_modules/clarity-ui/clarity-ui.min.css" + "../node_modules/clarity-icons/clarity-icons.min.css", + "../node_modules/clarity-ui/clarity-ui.min.css" ], "scripts": [ - "node_modules/core-js/client/shim.min.js", - "node_modules/mutationobserver-shim/dist/mutationobserver.min.js", - "node_modules/@webcomponents/custom-elements/custom-elements.min.js", - "node_modules/clarity-icons/clarity-icons.min.js", - "node_modules/web-animations-js/web-animations.min.js" + "../node_modules/core-js/client/shim.min.js", + "../node_modules/mutationobserver-shim/dist/mutationobserver.min.js", + "../node_modules/@webcomponents/custom-elements/custom-elements.min.js", + "../node_modules/clarity-icons/clarity-icons.min.js", + "../node_modules/web-animations-js/web-animations.min.js" ], "environmentSource": "environments/environment.ts", "environments": { diff --git a/src/ui_ng/lib/karma.conf.js b/src/ui_ng/lib/karma.conf.js new file mode 100644 index 000000000..755f19f9f --- /dev/null +++ b/src/ui_ng/lib/karma.conf.js @@ -0,0 +1,44 @@ +// Karma configuration file, see link for more information +// https://karma-runner.github.io/0.13/config/configuration-file.html + +module.exports = function (config) { + config.set({ + basePath: '', + frameworks: ['jasmine', '@angular/cli'], + plugins: [ + require('karma-jasmine'), + require('karma-phantomjs-launcher'), + require('karma-mocha-reporter'), + require('karma-remap-istanbul'), + require('@angular/cli/plugins/karma') + ], + files: [ + {pattern: './src/test.ts', watched: false} + ], + preprocessors: { + './src/test.ts': ['@angular/cli'] + }, + mime: { + 'text/x-typescript': ['ts', 'tsx'] + }, + remapIstanbulReporter: { + reports: { + html: 'coverage', + lcovonly: './coverage/coverage.lcov' + } + }, + angularCli: { + config: './angular-cli.json', + environment: 'dev' + }, + reporters: config.angularCli && config.angularCli.codeCoverage + ? ['mocha', 'karma-remap-istanbul'] + : ['mocha'], + port: 9876, + colors: true, + logLevel: config.LOG_INFO, + autoWatch: true, + browsers: ['PhantomJS'], + singleRun: true + }); +}; diff --git a/src/ui_ng/lib/package.json b/src/ui_ng/lib/package.json index 3c3d45c38..9ef32002a 100644 --- a/src/ui_ng/lib/package.json +++ b/src/ui_ng/lib/package.json @@ -6,6 +6,7 @@ "start": "ng serve --host 0.0.0.0 --port 4500 --proxy-config proxy.config.json", "lint": "tslint \"src/**/*.ts\"", "test": "ng test --single-run", + "test:once": "karma start karma.conf.js --single-run", "pree2e": "webdriver-manager update", "e2e": "protractor", "cleanup": "rimraf dist/bundles dist/src dist/index.d.ts dist/index.metadata.json dist/index.js dist/index.js.map dist/LICENSE dist/AUTHORS", @@ -17,21 +18,28 @@ }, "private": true, "dependencies": { - "@angular/common": "^4.0.0", - "@angular/compiler": "^4.0.0", - "@angular/core": "^4.0.0", - "@angular/http": "^4.0.0", - "clarity-angular": "^0.8.14", - "clarity-icons": "^0.8.14", - "clarity-ui": "^0.8.14", + "@angular/animations": "^4.0.1", + "@angular/common": "^4.0.1", + "@angular/compiler": "^4.0.1", + "@angular/core": "^4.0.1", + "@angular/forms": "^4.0.1", + "@angular/http": "^4.0.1", + "@angular/platform-browser": "^4.0.1", + "@angular/platform-browser-dynamic": "^4.0.1", + "@angular/router": "^4.0.1", + "@webcomponents/custom-elements": "1.0.0-alpha.3", + "web-animations-js": "^2.2.1", + "clarity-angular": "^0.9.0", + "clarity-icons": "^0.9.0", + "clarity-ui": "^0.9.0", "core-js": "^2.4.1", "rxjs": "^5.0.1", "ts-helpers": "^1.1.1", - "zone.js": "^0.7.2" + "zone.js": "^0.8.4" }, "devDependencies": { "@angular/cli": "^1.0.0", - "@angular/compiler-cli": "^2.4.1", + "@angular/compiler-cli": "^4.0.1", "@types/core-js": "^0.9.41", "@types/jasmine": "~2.2.30", "@types/node": "^6.0.42", @@ -50,7 +58,7 @@ "rollup": "^0.41.6", "ts-node": "1.2.1", "tslint": "^4.1.1", - "typescript": "~2.0.3", + "typescript": "~2.2.0", "typings": "^1.4.0", "uglify-js": "^2.8.22", "webdriver-manager": "10.2.5", diff --git a/src/ui_ng/lib/pkg/package.json b/src/ui_ng/lib/pkg/package.json index 124f78722..789a90fa0 100644 --- a/src/ui_ng/lib/pkg/package.json +++ b/src/ui_ng/lib/pkg/package.json @@ -19,16 +19,23 @@ }, "homepage": "https://github.com/vmware/harbor#readme", "peerDependencies": { - "@angular/common": "^4.0.0", - "@angular/compiler": "^4.0.0", - "@angular/core": "^4.0.0", - "@angular/http": "^4.0.0", - "clarity-angular": "^0.8.14", - "clarity-icons": "^0.8.14", - "clarity-ui": "^0.8.14", + "@angular/animations": "^4.0.1", + "@angular/common": "^4.0.1", + "@angular/compiler": "^4.0.1", + "@angular/core": "^4.0.1", + "@angular/forms": "^4.0.1", + "@angular/http": "^4.0.1", + "@angular/platform-browser": "^4.0.1", + "@angular/platform-browser-dynamic": "^4.0.1", + "@angular/router": "^4.0.1", + "@webcomponents/custom-elements": "1.0.0-alpha.3", + "web-animations-js": "^2.2.1", + "clarity-angular": "^0.9.0", + "clarity-icons": "^0.9.0", + "clarity-ui": "^0.9.0", "core-js": "^2.4.1", "rxjs": "^5.0.1", "ts-helpers": "^1.1.1", - "zone.js": "^0.7.2" + "zone.js": "^0.8.4" } } \ No newline at end of file diff --git a/src/ui_ng/lib/src/app.module.ts b/src/ui_ng/lib/src/app.module.ts new file mode 100644 index 000000000..f6d9797ba --- /dev/null +++ b/src/ui_ng/lib/src/app.module.ts @@ -0,0 +1,24 @@ +import { BrowserAnimationsModule } from "@angular/platform-browser/animations"; +import { BrowserModule } from '@angular/platform-browser'; +import { NgModule } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { HttpModule } from '@angular/http'; +import { ClarityModule } from 'clarity-angular'; +import { HarborLibraryModule } from './harbor-library.module'; + +@NgModule({ + declarations: [], + imports: [ + BrowserAnimationsModule, + BrowserModule, + FormsModule, + HttpModule, + ClarityModule.forRoot(), + HarborLibraryModule.forRoot() + ], + providers: [], + bootstrap: [] +}) + +export class AppModule { +} diff --git a/src/ui_ng/lib/src/environments/environment.prod.ts b/src/ui_ng/lib/src/environments/environment.prod.ts new file mode 100644 index 000000000..3612073bc --- /dev/null +++ b/src/ui_ng/lib/src/environments/environment.prod.ts @@ -0,0 +1,3 @@ +export const environment = { + production: true +}; diff --git a/src/ui_ng/lib/src/environments/environment.ts b/src/ui_ng/lib/src/environments/environment.ts new file mode 100644 index 000000000..00313f166 --- /dev/null +++ b/src/ui_ng/lib/src/environments/environment.ts @@ -0,0 +1,8 @@ +// The file contents for the current environment will overwrite these during build. +// The build system defaults to the dev environment which uses `environment.ts`, but if you do +// `ng build --env=prod` then `environment.prod.ts` will be used instead. +// The list of which env maps to which file can be found in `angular-cli.json`. + +export const environment = { + production: false +}; diff --git a/src/ui_ng/lib/src/main.ts b/src/ui_ng/lib/src/main.ts new file mode 100644 index 000000000..821632b09 --- /dev/null +++ b/src/ui_ng/lib/src/main.ts @@ -0,0 +1,12 @@ +import './polyfills.ts'; + +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; +import { enableProdMode } from '@angular/core'; +import { environment } from './environments/environment'; +import { AppModule } from './app.module'; + +if (environment.production) { + enableProdMode(); +} + +platformBrowserDynamic().bootstrapModule(AppModule); diff --git a/src/ui_ng/lib/src/polyfills.ts b/src/ui_ng/lib/src/polyfills.ts new file mode 100644 index 000000000..f26b6d8b6 --- /dev/null +++ b/src/ui_ng/lib/src/polyfills.ts @@ -0,0 +1,22 @@ +// This file includes polyfills needed by Angular 2 and is loaded before +// the app. You can add your own extra polyfills to this file. +import 'core-js/es6/symbol'; +import 'core-js/es6/object'; +import 'core-js/es6/function'; +import 'core-js/es6/parse-int'; +import 'core-js/es6/parse-float'; +import 'core-js/es6/number'; +import 'core-js/es6/math'; +import 'core-js/es6/string'; +import 'core-js/es6/date'; +import 'core-js/es6/array'; +import 'core-js/es6/regexp'; +import 'core-js/es6/map'; +import 'core-js/es6/set'; +import 'core-js/es6/reflect'; + +import 'core-js/es7/reflect'; + + +import 'zone.js/dist/zone'; + diff --git a/src/ui_ng/lib/src/service/access-log.service.spec.ts b/src/ui_ng/lib/src/service/access-log.service.spec.ts index fa874492d..6ace03477 100644 --- a/src/ui_ng/lib/src/service/access-log.service.spec.ts +++ b/src/ui_ng/lib/src/service/access-log.service.spec.ts @@ -5,14 +5,16 @@ import { AccessLogService, AccessLogDefaultService } from './access-log.service' describe('AccessLogService', () => { beforeEach(() => { TestBed.configureTestingModule({ - providers: [{ - provide: AccessLogService, - useClass: AccessLogDefaultService - }] + providers: [ + AccessLogDefaultService, + { + provide: AccessLogService, + useClass: AccessLogDefaultService + }] }); }); - it('should ...', inject([AccessLogDefaultService], (service: AccessLogService) => { + it('should be initialized', inject([AccessLogDefaultService], (service: AccessLogService) => { expect(service).toBeTruthy(); })); }); diff --git a/src/ui_ng/lib/src/service/endpoint.service.spec.ts b/src/ui_ng/lib/src/service/endpoint.service.spec.ts index 304ad55cb..37890bb26 100644 --- a/src/ui_ng/lib/src/service/endpoint.service.spec.ts +++ b/src/ui_ng/lib/src/service/endpoint.service.spec.ts @@ -5,14 +5,16 @@ import { EndpointService, EndpointDefaultService } from './endpoint.service'; describe('EndpointService', () => { beforeEach(() => { TestBed.configureTestingModule({ - providers: [{ - provide: EndpointService, - useClass: EndpointDefaultService - }] + providers: [ + EndpointDefaultService, + { + provide: EndpointService, + useClass: EndpointDefaultService + }] }); }); - it('should ...', inject([EndpointDefaultService], (service: EndpointService) => { + it('should be initialized', inject([EndpointDefaultService], (service: EndpointService) => { expect(service).toBeTruthy(); })); }); diff --git a/src/ui_ng/lib/src/service/replication.service.spec.ts b/src/ui_ng/lib/src/service/replication.service.spec.ts index 3c6786fb1..aa8285319 100644 --- a/src/ui_ng/lib/src/service/replication.service.spec.ts +++ b/src/ui_ng/lib/src/service/replication.service.spec.ts @@ -5,14 +5,16 @@ import { ReplicationService, ReplicationDefaultService } from './replication.ser describe('ReplicationService', () => { beforeEach(() => { TestBed.configureTestingModule({ - providers: [{ - provide: ReplicationService, - useClass: ReplicationDefaultService - }] + providers: [ + ReplicationDefaultService, + { + provide: ReplicationService, + useClass: ReplicationDefaultService + }] }); }); - it('should ...', inject([ReplicationDefaultService], (service: ReplicationService) => { + it('should be initialized', inject([ReplicationDefaultService], (service: ReplicationService) => { expect(service).toBeTruthy(); })); }); diff --git a/src/ui_ng/lib/src/service/repository.service.spec.ts b/src/ui_ng/lib/src/service/repository.service.spec.ts index 3c6786fb1..aa8285319 100644 --- a/src/ui_ng/lib/src/service/repository.service.spec.ts +++ b/src/ui_ng/lib/src/service/repository.service.spec.ts @@ -5,14 +5,16 @@ import { ReplicationService, ReplicationDefaultService } from './replication.ser describe('ReplicationService', () => { beforeEach(() => { TestBed.configureTestingModule({ - providers: [{ - provide: ReplicationService, - useClass: ReplicationDefaultService - }] + providers: [ + ReplicationDefaultService, + { + provide: ReplicationService, + useClass: ReplicationDefaultService + }] }); }); - it('should ...', inject([ReplicationDefaultService], (service: ReplicationService) => { + it('should be initialized', inject([ReplicationDefaultService], (service: ReplicationService) => { expect(service).toBeTruthy(); })); }); diff --git a/src/ui_ng/lib/src/service/tag.service.spec.ts b/src/ui_ng/lib/src/service/tag.service.spec.ts index cd375a8eb..aa0a15a1c 100644 --- a/src/ui_ng/lib/src/service/tag.service.spec.ts +++ b/src/ui_ng/lib/src/service/tag.service.spec.ts @@ -5,14 +5,16 @@ import { TagService, TagDefaultService } from './tag.service'; describe('TagService', () => { beforeEach(() => { TestBed.configureTestingModule({ - providers: [{ - provide: TagService, - useClass: TagDefaultService - }] + providers: [ + TagDefaultService, + { + provide: TagService, + useClass: TagDefaultService + }] }); }); - it('should ...', inject([TagDefaultService], (service: TagService) => { + it('should be initialized', inject([TagDefaultService], (service: TagService) => { expect(service).toBeTruthy(); })); }); diff --git a/src/ui_ng/lib/src/system/providers/system-info.service.spec.ts b/src/ui_ng/lib/src/system/providers/system-info.service.spec.ts index cd1f7000d..6b7ad9980 100644 --- a/src/ui_ng/lib/src/system/providers/system-info.service.spec.ts +++ b/src/ui_ng/lib/src/system/providers/system-info.service.spec.ts @@ -1,15 +1,29 @@ import { TestBed, inject } from '@angular/core/testing'; import { SystemInfoService } from './system-info.service'; +import { HttpModule } from '@angular/http'; +import { SERVICE_CONFIG, IServiceConfig } from '../../service.config'; + +export const testConfig: IServiceConfig = { + systemInfoEndpoint: "/api/systeminfo", + repositoryBaseEndpoint: "", + logBaseEndpoint: "", + targetBaseEndpoint: "", + replicationRuleEndpoint: "", + replicationJobEndpoint: "" +}; describe('SysteninfoService', () => { beforeEach(() => { TestBed.configureTestingModule({ - providers: [SystemInfoService] + imports: [HttpModule], + providers: [ + { provide: SERVICE_CONFIG, useValue: testConfig }, + SystemInfoService] }); }); - it('should ...', inject([SystemInfoService], (service: SystemInfoService) => { + it('should be initialized', inject([SystemInfoService], (service: SystemInfoService) => { expect(service).toBeTruthy(); })); }); diff --git a/src/ui_ng/lib/src/system/system.component.spec.ts b/src/ui_ng/lib/src/system/system.component.spec.ts index 05d48af03..cc37c84ee 100644 --- a/src/ui_ng/lib/src/system/system.component.spec.ts +++ b/src/ui_ng/lib/src/system/system.component.spec.ts @@ -1,6 +1,18 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { HttpModule } from '@angular/http'; import { SystemComponent } from './system.component'; +import { SystemInfoService } from './providers/system-info.service'; +import { SERVICE_CONFIG, IServiceConfig } from '../service.config'; + +export const testConfig: IServiceConfig = { + systemInfoEndpoint: "/api/systeminfo", + repositoryBaseEndpoint: "", + logBaseEndpoint: "", + targetBaseEndpoint: "", + replicationRuleEndpoint: "", + replicationJobEndpoint: "" +}; describe('SystemComponent', () => { let component: SystemComponent; @@ -8,7 +20,12 @@ describe('SystemComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ - declarations: [SystemComponent] + imports: [HttpModule], + declarations: [SystemComponent], + providers: [ + { provide: SERVICE_CONFIG, useValue: testConfig }, + SystemInfoService + ] }) .compileComponents(); })); @@ -19,7 +36,7 @@ describe('SystemComponent', () => { fixture.detectChanges(); }); - it('should create', () => { + it('should be created', () => { expect(component).toBeTruthy(); }); }); diff --git a/src/ui_ng/lib/src/test.ts b/src/ui_ng/lib/src/test.ts new file mode 100644 index 000000000..81af89096 --- /dev/null +++ b/src/ui_ng/lib/src/test.ts @@ -0,0 +1,32 @@ +import './polyfills.ts'; + +import 'zone.js/dist/long-stack-trace-zone'; +import 'zone.js/dist/proxy.js'; +import 'zone.js/dist/sync-test'; +import 'zone.js/dist/jasmine-patch'; +import 'zone.js/dist/async-test'; +import 'zone.js/dist/fake-async-test'; +import { getTestBed } from '@angular/core/testing'; +import { + BrowserDynamicTestingModule, + platformBrowserDynamicTesting +} from '@angular/platform-browser-dynamic/testing'; + +// Unfortunately there's no typing for the `__karma__` variable. Just declare it as any. +declare var __karma__: any; +declare var require: any; + +// Prevent Karma from running prematurely. +__karma__.loaded = function () {}; + +// First, initialize the Angular testing environment. +getTestBed().initTestEnvironment( + BrowserDynamicTestingModule, + platformBrowserDynamicTesting() +); +// Then we find all the tests. +let context = require.context('./', true, /\.spec\.ts/); +// And load the modules. +context.keys().map(context); +// Finally, start Karma to run the tests. +__karma__.start(); diff --git a/src/ui_ng/lib/src/tsconfig.json b/src/ui_ng/lib/src/tsconfig.json new file mode 100644 index 000000000..a0408f846 --- /dev/null +++ b/src/ui_ng/lib/src/tsconfig.json @@ -0,0 +1,33 @@ +{ + "compileOnSave": false, + "compilerOptions": { + "rootDir": "../", + "baseUrl": "", + "declaration": false, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "lib": [ + "es6", + "dom" + ], + "mapRoot": "src", + "module": "commonjs", + "moduleResolution": "node", + "outDir": "dist", + "sourceMap": true, + "target": "es5", + "typeRoots": [ + "node_modules/@types" + ], + "types": [ + "jasmine", + "core-js", + "node" + ] + }, + "exclude": [ + "node_modules", + "dist", + "test.ts" + ] +} \ No newline at end of file diff --git a/src/ui_ng/lib/tsconfig.json b/src/ui_ng/lib/tsconfig.json index 90bd8fce5..e46838e06 100644 --- a/src/ui_ng/lib/tsconfig.json +++ b/src/ui_ng/lib/tsconfig.json @@ -1,6 +1,7 @@ { "compilerOptions": { - "baseUrl": ".", + "baseUrl": "", + "rootDir": ".", "declaration": true, "stripInternal": true, "experimentalDecorators": true, @@ -12,7 +13,6 @@ "@angular/core": ["node_modules/@angular/core"], "rxjs/*": ["node_modules/rxjs/*"] }, - "rootDir": ".", "outDir": "dist", "sourceMap": true, "inlineSources": true, @@ -20,9 +20,23 @@ "skipLibCheck": true, "lib": [ "es2015", + "es6", "dom" + ], + "typeRoots": [ + "node_modules/@types" + ], + "types": [ + "jasmine", + "core-js", + "node" ] }, + "exclude": [ + "node_modules", + "dist", + "test.ts" + ], "files": [ "index.ts" ],