[ACA-1843] tomcat e2e runs (#674)

* tomcat environment

* disable artifact deployment for now

* travis settings update

* protractor settings

* protractor settings

* e2e fixes

* e2e fixes

* [ACA-1842] fix library dialog

* cleanup travis settings

* disable test (bug raised)

* fix after rebase

* fix after rebase
This commit is contained in:
Denys Vuika 2018-09-29 11:21:38 +01:00 committed by GitHub
parent 25e6f15ffc
commit 93e6489881
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 267 additions and 72 deletions

View File

@ -30,18 +30,9 @@ jobs:
script:
- npm run test:ci
- bash <(curl -s https://codecov.io/bash) -X gcov
before_deploy: 'npm run build.tomcat'
deploy:
provider: s3
region: $ARTIFACTS_REGION
access_key_id: $ARTIFACTS_KEY
secret_access_key: $ARTIFACTS_SECRET
bucket: $ARTIFACTS_BUCKET
skip_cleanup: true
local-dir: dist/tomcat
upload-dir: ${TRAVIS_BUILD_NUMBER}/tomcat
on:
repo: Alfresco/alfresco-content-app
branch: development
- stage: e2e
name: 'Nginx'
script: npm run build && npm run e2e:docker
- stage: e2e
name: 'Tomcat'
script: npm run build.tomcat && npm run docker.tomcat.e2e

View File

@ -1,6 +1,8 @@
{
"javascript.preferences.quoteStyle": "single",
"javascript.preferences.importModuleSpecifier": "relative",
"typescript.preferences.quoteStyle": "single",
"typescript.preferences.importModuleSpecifier": "relative",
"editor.formatOnSave": true,
"[html]": {
"editor.formatOnSave": false

5
docker/tomcat/Dockerfile Normal file
View File

@ -0,0 +1,5 @@
FROM tomcat
LABEL version="1.3"
LABEL maintainer="Denys Vuika <denys.vuika@alfresco.com>"
COPY ./artifacts/content-app.war /usr/local/tomcat/webapps/content-app.war

1
docker/tomcat/artifacts/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*.war

View File

View File

@ -0,0 +1,95 @@
version: '3'
services:
alfresco:
image: alfresco/alfresco-content-repository-community:6.0.7-ga
depends_on:
- postgres
environment:
JAVA_OPTS: '
-Ddb.driver=org.postgresql.Driver
-Ddb.username=alfresco
-Ddb.password=alfresco
-Ddb.url=jdbc:postgresql://postgres:5432/alfresco
-Dsolr.host=solr6
-Dsolr.port=8983
-Dsolr.secureComms=none
-Dsolr.base.url=/solr
-Dindex.subsystem.name=solr6
-Dshare.host=localhost
-Ddeployment.method=DOCKER_COMPOSE
-Dcsrf.filter.enabled=false
'
networks:
- internal
ports:
- 8080:8080 #Browser port
share:
image: alfresco/alfresco-share:6.0.b
depends_on:
- alfresco
environment:
- REPO_HOST=alfresco
- REPO_PORT=8080
networks:
- internal
ports:
- 8083:8080
postgres:
image: postgres:10.1
environment:
- POSTGRES_PASSWORD=alfresco
- POSTGRES_USER=alfresco
- POSTGRES_DB=alfresco
command: postgres -c max_connections=300 -c log_min_messages=LOG
networks:
- internal
ports:
- 5432:5432
solr6:
image: alfresco/alfresco-search-services:1.1.1
depends_on:
- alfresco
environment:
#Solr needs to know how to register itself with Alfresco
- SOLR_ALFRESCO_HOST=alfresco
- SOLR_ALFRESCO_PORT=8080
#Alfresco needs to know how to call solr
- SOLR_SOLR_HOST=solr6
- SOLR_SOLR_PORT=8983
#Create the default alfresco and archive cores
- SOLR_CREATE_ALFRESCO_DEFAULTS=alfresco,archive
networks:
- internal
ports:
- 8983:8983 #Browser port
content-app:
image: alfresco/alfresco-content-app:development-latest-tomcat8
build: .
depends_on:
- alfresco
networks:
- internal
ports:
- 4001:8080
# volumes:
# - ./app.config.json:/usr/share/nginx/html/app.config.json
# - ./nginx.conf:/etc/nginx/conf.d/default.conf
proxy:
image: nginx
depends_on:
- content-app
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf
networks:
- internal
ports:
- 4000:80
networks:
? internal

43
docker/tomcat/nginx.conf Normal file
View File

@ -0,0 +1,43 @@
server {
listen *:80;
set $allowOriginSite *;
proxy_pass_request_headers on;
proxy_pass_header Set-Cookie;
location / {
proxy_pass http://content-app:8080;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_redirect off;
proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass_header Set-Cookie;
}
location /alfresco/ {
proxy_pass http://alfresco:8080;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_redirect off;
proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass_header Set-Cookie;
}
location /share/ {
proxy_pass http://share:8080;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_redirect off;
proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass_header Set-Cookie;
}
}

View File

@ -29,7 +29,7 @@ export const BROWSER_RESOLUTION_HEIGHT = 800;
export const BROWSER_WAIT_TIMEOUT = 10000;
// Application configs
export const APP_HOST = 'http://localhost:4000';
export const USE_HASH_STRATEGY = true;
// Repository configs
export const REPO_API_HOST = 'http://localhost:8080';

View File

@ -31,11 +31,9 @@ import {
promise,
ExpectedConditions as EC
} from 'protractor';
import { BROWSER_WAIT_TIMEOUT } from './../configs';
import { BROWSER_WAIT_TIMEOUT, USE_HASH_STRATEGY } from './../configs';
export abstract class Page {
private static USE_HASH_STRATEGY = true;
private locators = {
app: by.css('app-root'),
layout: by.css('app-layout'),
@ -69,8 +67,8 @@ export abstract class Page {
}
load(relativeUrl: string = ''): promise.Promise<void> {
const hash = Page.USE_HASH_STRATEGY ? '/#' : '';
const path = `${hash}${this.url}${relativeUrl}`;
const hash = USE_HASH_STRATEGY ? '/#' : '';
const path = `${browser.baseUrl}${hash}${this.url}${relativeUrl}`;
return browser.get(path);
}

View File

@ -29,6 +29,7 @@ import { APP_ROUTES } from '../../configs';
import { LoginPage, LogoutPage, BrowsingPage } from '../../pages/pages';
import { Utils } from '../../utilities/utils';
import { RepoClient } from '../../utilities/repo-client/repo-client';
import { navigate } from '../../utilities/browser-utils';
describe('Login', () => {
const peopleApi = new RepoClient().people;
@ -128,11 +129,12 @@ describe('Login', () => {
expect(browser.getCurrentUrl()).toContain(APP_ROUTES.PERSONAL_FILES);
});
it('redirects to Home Page when navigating to the Login page while already logged in - [C213107]', async () => {
xit('redirects to Home Page when navigating to the Login page while already logged in - [C213107]', async () => {
const { username } = johnDoe;
await loginPage.loginWith(username);
await browser.get(APP_ROUTES.LOGIN);
await navigate(APP_ROUTES.LOGIN);
expect(await browser.getCurrentUrl()).toContain(APP_ROUTES.PERSONAL_FILES);
});
@ -189,7 +191,7 @@ describe('Login', () => {
});
it('unauthenticated user is redirected to Login page - [C213106]', async () => {
await browser.get(APP_ROUTES.PERSONAL_FILES);
await navigate(APP_ROUTES.PERSONAL_FILES);
expect(await browser.getCurrentUrl()).toContain(APP_ROUTES.LOGIN);
});

View File

@ -0,0 +1,39 @@
/*!
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2018 Alfresco Software Limited
*
* This file is part of the Alfresco Example Content Application.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* The Alfresco Example Content Application is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The Alfresco Example Content Application is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
import { browser } from 'protractor';
import { USE_HASH_STRATEGY } from '../configs';
export async function navigate(relativePath: string) {
const path = [
browser.baseUrl,
browser.baseUrl.endsWith('/') ? '' : '/',
USE_HASH_STRATEGY ? '#' : '',
relativePath.startsWith('/') ? '' : '/',
relativePath
].join('');
return browser.get(path);
}

View File

@ -15,15 +15,18 @@
"__e2e": "ng e2e",
"__wd:update": "webdriver-manager update --gecko=false --versions.chrome=2.38",
"wd:update": "webdriver-manager update --gecko=false",
"e2e": "npm run wd:update && protractor protractor.conf.js",
"e2e": "npm run wd:update && protractor --baseUrl=http://localhost:4000",
"start:docker": "docker-compose up -d --build && wait-on http://localhost:8080 && wait-on http://localhost:4000",
"stop:docker": "docker-compose stop",
"e2e:docker": "npm run start:docker && npm run e2e && npm run stop:docker",
"spellcheck": "cspell 'src/**/*.ts' 'e2e/**/*.ts' 'projects/**/*.ts'",
"inspect.bundle": "ng build app --prod --stats-json && npx webpack-bundle-analyzer dist/app/stats.json",
"format:check": "prettier --list-different \"src/{app,environments}/**/*{.ts,.js,.css,.scss}\"",
"build.tomcat": "npm run build -- --base-href ./ && mkdir -p dist/tomcat && jar -cvf dist/tomcat/content-app.war -C dist/app/ .",
"start.tomcat": "docker run -v `pwd`/dist/tomcat/content-app.war:/usr/local/tomcat/webapps/content-app.war -it -p 4080:8080 tomcat || exit 0"
"build.tomcat": "npm run build -- --base-href ./ && jar -cvf docker/tomcat/artifacts/content-app.war -C dist/app/ .",
"e2e.tomcat": "npm run wd:update && protractor --baseUrl=http://localhost:4000/content-app/",
"docker.tomcat.start": "cd docker/tomcat && docker-compose up -d --build && wait-on http://localhost:8080 && wait-on http://localhost:4000",
"docker.tomcat.stop": "cd docker/tomcat && docker-compose stop",
"docker.tomcat.e2e": "npm run docker.tomcat.start && npm run e2e.tomcat"
},
"private": true,
"dependencies": {

View File

@ -2,9 +2,7 @@
// https://github.com/angular/protractor/blob/master/lib/config.ts
const path = require('path');
const {
SpecReporter
} = require('jasmine-spec-reporter');
const { SpecReporter } = require('jasmine-spec-reporter');
const jasmineReporters = require('jasmine-reporters');
const CDP = require('chrome-remote-interface');
@ -25,13 +23,11 @@ function rmDir(dirPath) {
if (files.length > 0)
for (var i = 0; i < files.length; i++) {
var filePath = dirPath + '/' + files[i];
if (fs.statSync(filePath).isFile())
fs.unlinkSync(filePath);
else
rmDir(filePath);
if (fs.statSync(filePath).isFile()) fs.unlinkSync(filePath);
else rmDir(filePath);
}
fs.rmdirSync(dirPath);
};
}
exports.config = {
allScriptsTimeout: 40000,
@ -56,10 +52,10 @@ exports.config = {
browserName: 'chrome',
chromeOptions: {
prefs: {
'credentials_enable_service': false,
'download': {
'prompt_for_download': false,
'default_directory': downloadFolder
credentials_enable_service: false,
download: {
prompt_for_download: false,
default_directory: downloadFolder
}
},
args: ['--incognito', '--headless', '--remote-debugging-port=9222']
@ -68,7 +64,7 @@ exports.config = {
directConnect: true,
baseUrl: 'http://localhost:4000',
// baseUrl: 'http://localhost:4000',
framework: 'jasmine2',
jasmineNodeOpts: {
@ -77,7 +73,8 @@ exports.config = {
print: function() {}
},
plugins: [{
plugins: [
{
package: 'jasmine2-protractor-utils',
disableHTMLReport: false,
disableScreenshot: false,
@ -86,40 +83,49 @@ exports.config = {
clearFoldersBeforeTest: true,
htmlReportDir: `${projectRoot}/e2e-output/html-report/`,
screenshotPath: `${projectRoot}/e2e-output/screenshots/`
}],
}
],
onPrepare() {
require('ts-node').register({
project: 'e2e/tsconfig.e2e.json'
});
browser.manage().window().setSize(width, height);
browser
.manage()
.window()
.setSize(width, height);
jasmine.getEnv().addReporter(new SpecReporter({
jasmine.getEnv().addReporter(
new SpecReporter({
spec: {
displayStacktrace: true
}
}));
})
);
jasmine.getEnv().addReporter(new jasmineReporters.JUnitXmlReporter({
jasmine.getEnv().addReporter(
new jasmineReporters.JUnitXmlReporter({
consolidateAll: true,
savePath: `${projectRoot}/e2e-output/junit-report`,
filePrefix: 'results.xml',
useDotNotation: false,
useFullTestName: false,
reportFailedUrl: true
}));
})
);
rmDir(downloadFolder);
CDP().then(client => {
CDP()
.then(client => {
client.send('Page.setDownloadBehavior', {
behavior: 'allow',
downloadPath: downloadFolder
})
});
})
.catch(err => {
console.log(err)
console.log(err);
});
}
}
};

View File

@ -234,7 +234,7 @@ export class ContentManagementService {
});
}
createLibrary(): Observable<SiteEntry> {
createLibrary(): Observable<string> {
const dialogInstance = this.dialogRef.open(LibraryDialogComponent, {
width: '400px'
});
@ -243,9 +243,19 @@ export class ContentManagementService {
this.store.dispatch(new SnackbarErrorAction(message));
});
return dialogInstance
.afterClosed()
.pipe(tap(node => this.libraryCreated.next(node)));
return dialogInstance.afterClosed().pipe(
tap(node => {
if (node) {
this.libraryCreated.next(node);
}
}),
map((node: SiteEntry) => {
if (node && node.entry && node.entry.guid) {
return node.entry.guid;
}
return null;
})
);
}
deleteLibrary(id: string): void {

View File

@ -74,7 +74,7 @@ export class LibraryEffects {
createLibrary$ = this.actions$.pipe(
ofType<CreateLibraryAction>(CREATE_LIBRARY),
mergeMap(() => this.content.createLibrary()),
map(node => new NavigateLibraryAction(node.entry.guid))
map(libraryId => new NavigateLibraryAction(libraryId))
);
@Effect({ dispatch: false })