diff --git a/.gitignore b/.gitignore index 1ded9574f..124479e55 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,8 @@ node_modules .DS_Store .idea +# Ignore all e2e related build files +test/e2e/with-router/build *.e2e-bundle.* *-e2e.html diff --git a/dev-utils/run-script.js b/dev-utils/run-script.js index db6570424..20bde516c 100644 --- a/dev-utils/run-script.js +++ b/dev-utils/run-script.js @@ -123,16 +123,35 @@ function runSauceTests(packagePath, serve = 'true', ...scripts) { * Since there is no easy way to reuse the sauce connect tunnel even using same tunnel identifier, * we launch the sauce connect tunnel before starting all the saucelab tests */ - if (serve === 'true') { startServersWithCleanups(join(PROJECT_DIR, packagePath)) } launchSauceConnect(async sauceConnectProcess => { - if (!sauceLabs) { - return runUnitTests(packagePath) + /** + * Decides the saucelabs test status + */ + let exitCode = 0 + const loggerOpts = { + stdout: process.stdout, + stderr: process.stderr } + const exitProcess = () => process.exit(exitCode) + const runAllAndExit = async commands => { + try { + await runAll(commands, loggerOpts) + } catch (err) { + console.log('runSauceTests failed', err) + exitCode = 1 + } finally { + if (sauceConnectProcess) { + sauceConnectProcess.close(exitProcess) + } else { + exitProcess() + } + } + } /** * `console.logs` from the tests will be truncated when the process exits * To avoid truncation, we flush the data from stdout before exiting the process @@ -141,26 +160,18 @@ function runSauceTests(packagePath, serve = 'true', ...scripts) { process.stdout._handle.setBlocking(true) } - /** - * Decides the saucelabs test status - */ - let exitCode = 0 - const loggerOpts = { - stdout: process.stdout, - stderr: process.stderr - } - - try { - await runAll(scripts, loggerOpts) - console.log(`Ran all [${scripts.join(', ')}] scripts successfully!`) - } catch (err) { - console.log('Sauce Tests Failed', err) - exitCode = 1 - } finally { - sauceConnectProcess.close(() => { - process.exit(exitCode) - }) + if (!sauceLabs) { + /** + * For Angular package we use `ng` commands for running the test instead of + * using our custom karma runner + */ + if (packagePath === 'packages/rum-angular') { + return await runAllAndExit(['test:unit']) + } else { + return runUnitTests(packagePath) + } } + await runAllAndExit(scripts) }) } diff --git a/package.json b/package.json index a7eb11810..bdabe22bc 100644 --- a/package.json +++ b/package.json @@ -169,7 +169,6 @@ "stats-lite": "^2.2.0", "terser-webpack-plugin": "^3.1.0", "ts-node": "^8.3.0", - "tslib": "^1.10.0", "typescript": "^3.7.3", "vue": "^2.6.10", "vue-loader": "^15.7.2", diff --git a/packages/rum-angular/angular.json b/packages/rum-angular/angular.json index 6e6960df8..70b308924 100644 --- a/packages/rum-angular/angular.json +++ b/packages/rum-angular/angular.json @@ -26,8 +26,60 @@ "options": { "main": "test/specs/index.ts", "tsConfig": "tsconfig.spec.json", - "karmaConfig": "karma.conf.js", - "polyfills": "test/polyfills.ts" + "karmaConfig": "karma.conf.js" + } + } + } + }, + "app": { + "projectType": "application", + "schematics": {}, + "root": "test/e2e/with-router", + "sourceRoot": "test/e2e/with-router", + "prefix": "", + "architect": { + "build": { + "builder": "@angular-devkit/build-angular:browser", + "options": { + "outputPath": "test/e2e/with-router/build", + "index": "test/e2e/with-router/index.html", + "main": "test/e2e/with-router/main.ts", + "polyfills": "test/e2e/with-router/polyfills.ts", + "tsConfig": "test/e2e/with-router/tsconfig.app.json", + "aot": true, + "assets": [ + "test/e2e/with-router/assets" + ] + }, + "configurations": { + "production": { + "fileReplacements": [ + { + "replace": "test/e2e/with-router/environments/environment.ts", + "with": "test/e2e/with-router/environments/environment.prod.ts" + } + ], + "optimization": true, + "outputHashing": "all", + "sourceMap": false, + "extractCss": true, + "namedChunks": false, + "vendorChunk": false, + "buildOptimizer": true + } + } + }, + "serve": { + "builder": "@angular-devkit/build-angular:dev-server", + "options": { + "port": 8000, + "browserTarget": "app:build", + "baseHref": "/test/e2e/with-router/build/" + }, + "configurations": { + "production": { + "browserTarget": "app:build:production" + } } } } diff --git a/packages/rum-angular/ng-package.json b/packages/rum-angular/ng-package.json index a0a7872fc..24310e147 100644 --- a/packages/rum-angular/ng-package.json +++ b/packages/rum-angular/ng-package.json @@ -1,8 +1,13 @@ { - "$schema": "./node_modules/ng-packagr/ng-package.schema.json", + "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", "dest": "dist", "lib": { - "entryFile": "src/index.ts" + "entryFile": "src/index.ts", + "umdModuleIds": { + "@elastic/apm-rum": "elastic.apmRum", + "@elastic/apm-rum-core": "elastic.apmRumCore" + }, + "umdId": "elastic.apmRumAngular" }, "whitelistedNonPeerDependencies": [ "@elastic/*" diff --git a/packages/rum-angular/package.json b/packages/rum-angular/package.json index 186b95dd7..72711f47e 100644 --- a/packages/rum-angular/package.json +++ b/packages/rum-angular/package.json @@ -18,8 +18,12 @@ }, "scripts": { "build": "ng build --prod", + "build:e2e": "ng build app --prod", "test:unit": "ng test", - "test": "MODE=none npm run test:unit", + "test:e2e": "npm run script runE2eTests packages/rum-angular/wdio.conf.js", + "test:sauce": "npm run script runSauceTests packages/rum-angular true test:unit build:e2e test:e2e", + "test": "npm run test:sauce", + "script": "node ../../dev-utils/run-script.js", "karma:dev": "ng test --watch", "karma:coverage": "ng test --code-coverage" }, diff --git a/packages/rum-angular/test/e2e/with-router/app.e2e-spec.js b/packages/rum-angular/test/e2e/with-router/app.e2e-spec.js index b2d89a479..dbf472f39 100644 --- a/packages/rum-angular/test/e2e/with-router/app.e2e-spec.js +++ b/packages/rum-angular/test/e2e/with-router/app.e2e-spec.js @@ -26,29 +26,50 @@ const { waitForApmServerCalls } = require('../../../../../dev-utils/webdriver') describe('Angular router integration', function () { - beforeAll(() => browser.url('/test/e2e/with-router/')) + /** + * Change ELEMENT_KEY to approprioate value when using `devtools` + * automation protocol + * https://github.com/webdriverio/webdriverio/blob/e942ce4d802161ac12579553889d9068dccf317c/packages/devtools/src/constants.ts#L8 + */ + const ELEMENT_KEY = 'ELEMENT' + beforeAll(async () => { + await browser.url('test/e2e/with-router/build/') + }) - it('should run angular app and capture route-change', function () { + it('should run angular app and capture route-change', async () => { /** * Should render home page on load */ - const notFoundElement = $('app-root app-home h2') - expect(notFoundElement.getText()).toEqual('Home page') + const result = await browser.findElement( + 'css selector', + 'app-root app-home h2' + ) + expect(await browser.getElementText(result[ELEMENT_KEY])).toEqual( + 'Home page' + ) - browser.waitUntil( - () => { + await browser.waitUntil( + async () => { /** * route to /contacts */ - $('#contacts').click() - const contactListElement = $('app-root app-contact-list') - return contactListElement.getText().indexOf('Name') !== -1 + const result = await browser.findElement('css selector', '#contacts') + await browser.elementClick(result[ELEMENT_KEY]) + const listResult = await browser.findElement( + 'css selector', + 'app-root app-contact-list' + ) + const isDisplayed = await browser.isElementDisplayed( + listResult[ELEMENT_KEY] + ) + return isDisplayed }, - 5000, - 'expected contact list to be rendered' + 10000, + 'expected contact list to be rendered', + 5000 ) - const { sendEvents } = waitForApmServerCalls(0, 2) + const { sendEvents } = await waitForApmServerCalls(0, 2) const { transactions } = sendEvents expect(transactions.length).toBe(2) @@ -64,6 +85,8 @@ describe('Angular router integration', function () { const extSpans = routeTransaction.spans.filter( span => span.type === 'external' ) - expect(extSpans[0].name).toBe('GET /test/e2e/with-router/data.json') + expect(extSpans[0].name).toBe( + 'GET /test/e2e/with-router/build/assets/data.json' + ) }) }) diff --git a/packages/rum-angular/test/e2e/with-router/app/app.routing.module.ts b/packages/rum-angular/test/e2e/with-router/app/app-routing.module.ts similarity index 100% rename from packages/rum-angular/test/e2e/with-router/app/app.routing.module.ts rename to packages/rum-angular/test/e2e/with-router/app/app-routing.module.ts diff --git a/packages/rum-angular/test/e2e/with-router/app/app.module.ts b/packages/rum-angular/test/e2e/with-router/app/app.module.ts index 53eb73429..250cf8afd 100644 --- a/packages/rum-angular/test/e2e/with-router/app/app.module.ts +++ b/packages/rum-angular/test/e2e/with-router/app/app.module.ts @@ -23,22 +23,26 @@ * */ -import { NgModule, Inject, ErrorHandler } from '@angular/core' import { BrowserModule } from '@angular/platform-browser' +import { NgModule, ErrorHandler } from '@angular/core' import { HttpClientModule } from '@angular/common/http' -import { Router } from '@angular/router' +import { + ApmModule, + ApmService, + ApmErrorHandler +} from '@elastic/apm-rum-angular' -import { AppRoutingModule } from './app.routing.module' +import { AppRoutingModule } from './app-routing.module' import { AppComponent } from './app.component' import { HomeComponent } from './home.component' import { ContactListComponent } from './contact-list.component' import { ContactDetailComponent } from './contact-detail.component' import { PageNotFoundComponent } from './not-found.component' -import { ApmService, ApmErrorHandler } from '../../../../src' -import { initializeApmService } from '../../../index' +import { environment } from '../environments/environment' +import { initializeApmService } from '../../../' @NgModule({ - imports: [BrowserModule, AppRoutingModule, HttpClientModule], + imports: [ApmModule, BrowserModule, AppRoutingModule, HttpClientModule], declarations: [ AppComponent, HomeComponent, @@ -47,11 +51,7 @@ import { initializeApmService } from '../../../index' ContactDetailComponent ], providers: [ - { - provide: ApmService, - useClass: ApmService, - deps: [Router] - }, + ApmService, { provide: ErrorHandler, useClass: ApmErrorHandler @@ -60,8 +60,9 @@ import { initializeApmService } from '../../../index' bootstrap: [AppComponent] }) export class AppModule { - constructor(@Inject(ApmService) service: ApmService) { + constructor(service: ApmService) { initializeApmService(service, { + serverUrl: environment.serverUrl, serviceName: 'e2e-angular-integration', logLevel: 'debug' }) diff --git a/packages/rum-angular/test/e2e/with-router/app/contact.service.ts b/packages/rum-angular/test/e2e/with-router/app/contact.service.ts index 8e3522941..7f339a43e 100644 --- a/packages/rum-angular/test/e2e/with-router/app/contact.service.ts +++ b/packages/rum-angular/test/e2e/with-router/app/contact.service.ts @@ -30,7 +30,7 @@ import { HttpClient } from '@angular/common/http' providedIn: 'root' }) export class ContactService { - CONTACT_URL = '/test/e2e/with-router/data.json' + CONTACT_URL = '/test/e2e/with-router/build/assets/data.json' constructor(private http: HttpClient) {} getContacts() { diff --git a/packages/rum-angular/test/e2e/with-router/data.json b/packages/rum-angular/test/e2e/with-router/assets/data.json similarity index 100% rename from packages/rum-angular/test/e2e/with-router/data.json rename to packages/rum-angular/test/e2e/with-router/assets/data.json diff --git a/packages/rum-angular/test/e2e/with-router/environments/environment.prod.ts b/packages/rum-angular/test/e2e/with-router/environments/environment.prod.ts new file mode 100644 index 000000000..e35fd791d --- /dev/null +++ b/packages/rum-angular/test/e2e/with-router/environments/environment.prod.ts @@ -0,0 +1,29 @@ +/** + * MIT License + * + * Copyright (c) 2017-present, Elasticsearch BV + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +export const environment = { + production: true, + serverUrl: 'http://apm-server:8200' +} diff --git a/packages/rum-angular/test/e2e/with-router/webpack.config.js b/packages/rum-angular/test/e2e/with-router/environments/environment.ts similarity index 75% rename from packages/rum-angular/test/e2e/with-router/webpack.config.js rename to packages/rum-angular/test/e2e/with-router/environments/environment.ts index 025da7535..a1ebd6abe 100644 --- a/packages/rum-angular/test/e2e/with-router/webpack.config.js +++ b/packages/rum-angular/test/e2e/with-router/environments/environment.ts @@ -23,20 +23,11 @@ * */ -const path = require('path') -const { - getWebpackConfig, - PACKAGE_TYPES, - BUNDLE_TYPES -} = require('../../../../../dev-utils/build') +// This file can be replaced during build by using the `fileReplacements` array. +// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`. +// The list of file replacements can be found in `angular.json`. -module.exports = { - entry: { - app: path.join(__dirname, 'main.ts') - }, - output: { - path: path.resolve(__dirname), - filename: '[name].e2e-bundle.js' - }, - ...getWebpackConfig(BUNDLE_TYPES.BROWSER_PROD, PACKAGE_TYPES.ANGULAR) +export const environment = { + production: false, + serverUrl: 'http://localhost:8001' } diff --git a/packages/rum-angular/test/e2e/with-router/index.html b/packages/rum-angular/test/e2e/with-router/index.html index fcea45da6..48aab08d5 100644 --- a/packages/rum-angular/test/e2e/with-router/index.html +++ b/packages/rum-angular/test/e2e/with-router/index.html @@ -1,7 +1,7 @@
-