mirror of
https://github.com/Alfresco/alfresco-content-app.git
synced 2025-05-12 17:04:46 +00:00
[ACA-1799] add tests for share file (#727)
* initial work * shared link created through API * add tests for share file on all list views * remove utc for end of day * remove hours and minutes * update unit test * workaround * update docker settings for tomcat * tomcat setup for e2e
This commit is contained in:
parent
9012c0832b
commit
30b445dde9
@ -37,4 +37,4 @@ jobs:
|
||||
script: npm run build && npm run e2e:docker
|
||||
- stage: e2e
|
||||
name: 'Tomcat'
|
||||
script: npm run build.tomcat && npm run docker.tomcat.e2e
|
||||
script: npm run build.tomcat.e2e && npm run docker.tomcat.e2e
|
||||
|
@ -1,11 +1,9 @@
|
||||
FROM nginx:stable-alpine
|
||||
LABEL version="1.3"
|
||||
LABEL version="1.4"
|
||||
LABEL maintainer="Denys Vuika <denys.vuika@alfresco.com>"
|
||||
|
||||
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
||||
|
||||
#COPY --chown=nginx:nginx ./docker-entrypoint.sh /
|
||||
COPY ./docker-entrypoint.sh /
|
||||
RUN chmod +x /docker-entrypoint.sh
|
||||
|
||||
|
13
build-tomcat-e2e.sh
Executable file
13
build-tomcat-e2e.sh
Executable file
@ -0,0 +1,13 @@
|
||||
npm run build -- --base-href ./
|
||||
|
||||
node -e "
|
||||
const fs = require('fs');
|
||||
const config = require('./dist/app/app.config.json');
|
||||
config.baseShareUrl = 'http://localhost:4000/content-app';
|
||||
fs.writeFileSync(
|
||||
'./dist/app/app.config.json',
|
||||
JSON.stringify(config, null, 2)
|
||||
);
|
||||
"
|
||||
|
||||
jar -cvf docker/tomcat/artifacts/content-app.war -C dist/app/ .
|
@ -51,8 +51,14 @@ fi
|
||||
if [[ $ACSURL ]]; then
|
||||
sed -i s%{protocol}//{hostname}{:port}%"$ACSURL"%g /usr/share/nginx/html/app.config.json
|
||||
fi
|
||||
|
||||
if [[ $BASEPATH ]]; then
|
||||
sed -i s%href=\"/\"%href=\""$BASEPATH"\"%g /usr/share/nginx/html/index.html
|
||||
fi
|
||||
|
||||
if [ -n "${APP_BASE_SHARE_URL}" ];then
|
||||
sed -e "s/\"baseShareUrl\": \".*\"/\"baseShareUrl\": \"${APP_BASE_SHARE_URL}\"/g" \
|
||||
-i ./app.config.json
|
||||
fi
|
||||
|
||||
nginx -g "daemon off;"
|
||||
|
@ -2,7 +2,7 @@ version: '3'
|
||||
|
||||
services:
|
||||
alfresco:
|
||||
image: alfresco/alfresco-content-repository-community:6.0.7-ga
|
||||
image: alfresco/alfresco-content-repository-community:6.1.0-ea
|
||||
depends_on:
|
||||
- postgres
|
||||
environment:
|
||||
@ -26,7 +26,7 @@ services:
|
||||
- 8080:8080 #Browser port
|
||||
|
||||
share:
|
||||
image: alfresco/alfresco-share:6.0.b
|
||||
image: alfresco/alfresco-share:6.0.c
|
||||
depends_on:
|
||||
- alfresco
|
||||
environment:
|
||||
@ -50,7 +50,7 @@ services:
|
||||
- 5432:5432
|
||||
|
||||
solr6:
|
||||
image: alfresco/alfresco-search-services:1.1.1
|
||||
image: alfresco/alfresco-search-services:1.2.0
|
||||
depends_on:
|
||||
- alfresco
|
||||
environment:
|
||||
@ -70,6 +70,8 @@ services:
|
||||
content-app:
|
||||
image: alfresco/alfresco-content-app:development-latest-tomcat8
|
||||
build: .
|
||||
environment:
|
||||
- APP_BASE_SHARE_URL={protocol}//{hostname}{:port}/content-app/
|
||||
depends_on:
|
||||
- alfresco
|
||||
networks:
|
||||
|
83
e2e/components/datetime-picker/datetime-picker.ts
Executable file
83
e2e/components/datetime-picker/datetime-picker.ts
Executable file
@ -0,0 +1,83 @@
|
||||
/*!
|
||||
* @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 { ElementFinder, by, browser, ExpectedConditions as EC } from 'protractor';
|
||||
import { BROWSER_WAIT_TIMEOUT } from '../../configs';
|
||||
import { Component } from '../component';
|
||||
|
||||
export class DateTimePicker extends Component {
|
||||
private static selectors = {
|
||||
root: '.mat-datetimepicker-popup',
|
||||
|
||||
header: '.mat-datetimepicker-calendar-header',
|
||||
year: '.mat-datetimepicker-calendar-header-year',
|
||||
date: '.mat-datetimepicker-calendar-header-date',
|
||||
|
||||
content: '.mat-datetimepicker-calendar-content',
|
||||
dayPicker: 'mat-datetimepicker-month-view',
|
||||
|
||||
today: '.mat-datetimepicker-calendar-body-today',
|
||||
firstActiveDay: '.mat-datetimepicker-calendar-body-active .mat-datetimepicker-calendar-body-cell-content',
|
||||
};
|
||||
|
||||
calendar: ElementFinder = browser.element(by.css(DateTimePicker.selectors.root));
|
||||
headerDate: ElementFinder = this.component.element(by.css(DateTimePicker.selectors.date));
|
||||
headerYear: ElementFinder = this.component.element(by.css(DateTimePicker.selectors.year));
|
||||
dayPicker: ElementFinder = this.component.element(by.css(DateTimePicker.selectors.dayPicker));
|
||||
|
||||
constructor(ancestor?: ElementFinder) {
|
||||
super(DateTimePicker.selectors.root, ancestor);
|
||||
}
|
||||
|
||||
async waitForDateTimePickerToOpen() {
|
||||
await browser.wait(EC.presenceOf(this.calendar), BROWSER_WAIT_TIMEOUT);
|
||||
}
|
||||
|
||||
async waitForDateTimePickerToClose() {
|
||||
await browser.wait(EC.stalenessOf(this.calendar), BROWSER_WAIT_TIMEOUT);
|
||||
}
|
||||
|
||||
async isCalendarOpen() {
|
||||
return await browser.isElementPresent(by.css(DateTimePicker.selectors.root));
|
||||
}
|
||||
|
||||
async getDate() {
|
||||
return await this.headerDate.getText();
|
||||
}
|
||||
|
||||
async getYear() {
|
||||
return await this.headerYear.getText();
|
||||
}
|
||||
|
||||
async setDefaultDay() {
|
||||
const today = await this.dayPicker.element(by.css(DateTimePicker.selectors.today)).getText();
|
||||
const tomorrow = (parseInt(today, 10) + 1).toString();
|
||||
const date = await this.getDate();
|
||||
const year = await this.getYear();
|
||||
const elem = this.dayPicker.element(by.cssContainingText(DateTimePicker.selectors.firstActiveDay, tomorrow));
|
||||
await elem.click();
|
||||
return `${date} ${year}`;
|
||||
}
|
||||
}
|
@ -23,23 +23,41 @@
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { ElementFinder, by, browser, ExpectedConditions as EC } from 'protractor';
|
||||
import { ElementFinder, ElementArrayFinder, by, browser, ExpectedConditions as EC } from 'protractor';
|
||||
import { BROWSER_WAIT_TIMEOUT } from '../../configs';
|
||||
import { DateTimePicker } from '../../components/datetime-picker/datetime-picker';
|
||||
import { Component } from '../component';
|
||||
|
||||
export class ShareDialog extends Component {
|
||||
private static selectors = {
|
||||
root: '.adf-share-dialog',
|
||||
|
||||
title: '.mat-dialog-title',
|
||||
content: '.mat-dialog-content',
|
||||
title: `[data-automation-id='adf-share-dialog-title']`,
|
||||
info: '.adf-share-link__info',
|
||||
label: '.adf-share-link__label',
|
||||
shareToggle: `[data-automation-id='adf-share-toggle']`,
|
||||
linkUrl: `[data-automation-id='adf-share-link']`,
|
||||
inputAction: '.input-action',
|
||||
expireToggle: `[data-automation-id='adf-expire-toggle']`,
|
||||
datetimePickerButton: '.mat-datetimepicker-toggle',
|
||||
expirationInput: 'input[formcontrolname="time"]',
|
||||
button: `[data-automation-id='adf-share-dialog-close']`
|
||||
};
|
||||
|
||||
dateTimePicker = new DateTimePicker();
|
||||
|
||||
title: ElementFinder = this.component.element(by.css(ShareDialog.selectors.title));
|
||||
content: ElementFinder = this.component.element(by.css(ShareDialog.selectors.content));
|
||||
infoText: ElementFinder = this.component.element(by.css(ShareDialog.selectors.info));
|
||||
labels: ElementArrayFinder = this.component.all(by.css(ShareDialog.selectors.label));
|
||||
shareToggle: ElementFinder = this.component.element(by.css(ShareDialog.selectors.shareToggle));
|
||||
url: ElementFinder = this.component.element(by.css(ShareDialog.selectors.linkUrl));
|
||||
urlAction: ElementFinder = this.component.element(by.css(ShareDialog.selectors.inputAction));
|
||||
expireToggle: ElementFinder = this.component.element(by.css(ShareDialog.selectors.expireToggle));
|
||||
expireInput: ElementFinder = this.component.element(by.css(ShareDialog.selectors.expirationInput));
|
||||
datetimePickerButton: ElementFinder = this.component.element(by.css(ShareDialog.selectors.datetimePickerButton));
|
||||
closeButton: ElementFinder = this.component.element(by.css(ShareDialog.selectors.button));
|
||||
|
||||
|
||||
constructor(ancestor?: ElementFinder) {
|
||||
super(ShareDialog.selectors.root, ancestor);
|
||||
}
|
||||
@ -48,20 +66,81 @@ export class ShareDialog extends Component {
|
||||
await browser.wait(EC.stalenessOf(this.title), BROWSER_WAIT_TIMEOUT);
|
||||
}
|
||||
|
||||
async waitForDialogToOpen() {
|
||||
await browser.wait(EC.presenceOf(this.title), BROWSER_WAIT_TIMEOUT);
|
||||
}
|
||||
|
||||
async isDialogOpen() {
|
||||
return await browser.$(ShareDialog.selectors.root).isDisplayed();
|
||||
return await browser.isElementPresent(by.css(ShareDialog.selectors.root));
|
||||
}
|
||||
|
||||
async getTitle() {
|
||||
return await this.title.getText();
|
||||
}
|
||||
|
||||
async getText() {
|
||||
return await this.content.getText();
|
||||
async getInfoText() {
|
||||
return await this.infoText.getText();
|
||||
}
|
||||
|
||||
getLabels() {
|
||||
return this.labels;
|
||||
}
|
||||
|
||||
async getLinkUrl() {
|
||||
return await this.url.getAttribute('value');
|
||||
}
|
||||
|
||||
async isUrlReadOnly() {
|
||||
return await this.url.getAttribute('readonly');
|
||||
}
|
||||
|
||||
async clickClose() {
|
||||
await this.closeButton.click();
|
||||
await this.waitForDialogToClose();
|
||||
}
|
||||
|
||||
getShareToggle() {
|
||||
return this.shareToggle;
|
||||
}
|
||||
|
||||
getExpireToggle() {
|
||||
return this.expireToggle;
|
||||
}
|
||||
|
||||
getExpireInput() {
|
||||
return this.expireInput;
|
||||
}
|
||||
|
||||
async isShareToggleEnabled() {
|
||||
const toggleClass = await this.getShareToggle().getAttribute('class');
|
||||
return toggleClass.includes('checked');
|
||||
}
|
||||
|
||||
async isExpireToggleEnabled() {
|
||||
const toggleClass = await this.getExpireToggle().getAttribute('class');
|
||||
return toggleClass.includes('checked');
|
||||
}
|
||||
|
||||
async copyUrl() {
|
||||
return await this.urlAction.click();
|
||||
}
|
||||
|
||||
async openDatetimePicker() {
|
||||
return await this.datetimePickerButton.click();
|
||||
}
|
||||
|
||||
async closeDatetimePicker() {
|
||||
if (await this.dateTimePicker.isCalendarOpen()) {
|
||||
return await this.datetimePickerButton.click();
|
||||
}
|
||||
}
|
||||
|
||||
async getExpireDate() {
|
||||
return await this.getExpireInput().getAttribute('value');
|
||||
}
|
||||
|
||||
async clickExpirationToggle() {
|
||||
await this.expireToggle.click();
|
||||
}
|
||||
|
||||
}
|
||||
|
1085
e2e/suites/actions/share-file.test.ts
Executable file
1085
e2e/suites/actions/share-file.test.ts
Executable file
File diff suppressed because it is too large
Load Diff
@ -100,14 +100,14 @@ describe('Extensions - Metadata presets', () => {
|
||||
done();
|
||||
});
|
||||
|
||||
it('Set groups of properties to display - []', async () => {
|
||||
it('Set groups of properties to display - [C286636]', async () => {
|
||||
expect(await metadataCard.isExpansionPanelPresent(0)).toBe(true, `expansion panel is not present`);
|
||||
expect(await metadataCard.getComponentIdOfPanel(0)).toEqual(`adf-metadata-group-${customGroup1.title}`);
|
||||
expect(await metadataCard.isExpansionPanelPresent(1)).toBe(true, `expansion panel is not present`);
|
||||
expect(await metadataCard.getComponentIdOfPanel(1)).toEqual(`adf-metadata-group-${customGroup2.title}`);
|
||||
});
|
||||
|
||||
it('Disabled group is not displayed - []', async () => {
|
||||
it('Disabled group is not displayed - [C286637]', async () => {
|
||||
expect(await metadataCard.isExpansionPanelPresent(2)).toBe(false, `disabled group is displayed`);
|
||||
expect(await metadataCard.getComponentIdOfPanel(1)).not.toEqual(`adf-metadata-group-${disabledGroup.title}`);
|
||||
expect(await metadataCard.getComponentIdOfPanel(0)).not.toEqual(`adf-metadata-group-${disabledGroup.title}`);
|
||||
|
@ -54,6 +54,10 @@ export class NodesApi extends RepoApi {
|
||||
return (await this.getNodeByPath(`${relativePath}`)).entry.properties['cm:description'];
|
||||
}
|
||||
|
||||
async getNodeProperty(nodeId: string, property: string) {
|
||||
return (await this.getNodeById(nodeId)).entry.properties[property];
|
||||
}
|
||||
|
||||
async deleteNodeById(id: string, permanent: boolean = true) {
|
||||
await this.apiAuth();
|
||||
return await this.alfrescoJsApi.core.nodesApi.deleteNode(id, { permanent });
|
||||
|
@ -32,10 +32,17 @@ export class SharedLinksApi extends RepoApi {
|
||||
super(username, password);
|
||||
}
|
||||
|
||||
async shareFileById(id: string) {
|
||||
async shareFileById(id: string, expireDate?: Date) {
|
||||
try {
|
||||
await this.apiAuth();
|
||||
const data = { nodeId: id };
|
||||
return await this.alfrescoJsApi.core.sharedlinksApi.addSharedLink(data);
|
||||
const data = {
|
||||
nodeId: id,
|
||||
expiresAt: expireDate
|
||||
};
|
||||
return await this.alfrescoJsApi.core.sharedlinksApi.addSharedLink(data);
|
||||
} catch (error) {
|
||||
console.log('---- shareFileById error: ', error);
|
||||
}
|
||||
}
|
||||
|
||||
async shareFilesByIds(ids: string[]) {
|
||||
|
@ -115,4 +115,8 @@ export class Utils {
|
||||
static getBrowserLog() {
|
||||
return browser.manage().logs().get('browser');
|
||||
}
|
||||
|
||||
static formatDate(date: string) {
|
||||
return new Date(date).toLocaleDateString('en-US');
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
"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 ./ && jar -cvf docker/tomcat/artifacts/content-app.war -C dist/app/ .",
|
||||
"build.tomcat.e2e": "./build-tomcat-e2e.sh",
|
||||
"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",
|
||||
|
@ -317,7 +317,7 @@ describe('ShareDialogComponent', () => {
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(nodesApiService.updateNode).toHaveBeenCalledWith('nodeId', {
|
||||
properties: { 'qshare:expiryDate': date.utc().format() }
|
||||
properties: { 'qshare:expiryDate': date }
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -103,7 +103,7 @@ export class ShareDialogComponent implements OnInit, OnDestroy {
|
||||
this.baseShareUrl = this.data.baseShareUrl;
|
||||
const properties = this.data.node.entry.properties;
|
||||
|
||||
if (properties && !properties['qshare:sharedId']) {
|
||||
if (!properties || !properties['qshare:sharedId']) {
|
||||
this.createSharedLinks(this.data.node.entry.id);
|
||||
} else {
|
||||
this.sharedId = properties['qshare:sharedId'];
|
||||
@ -174,7 +174,13 @@ export class ShareDialogComponent implements OnInit, OnDestroy {
|
||||
(sharedLink: SharedLinkEntry) => {
|
||||
if (sharedLink.entry) {
|
||||
this.sharedId = sharedLink.entry.id;
|
||||
this.data.node.entry.properties['qshare:sharedId'] = this.sharedId;
|
||||
if (this.data.node.entry.properties) {
|
||||
this.data.node.entry.properties['qshare:sharedId'] = this.sharedId;
|
||||
} else {
|
||||
this.data.node.entry.properties = {
|
||||
'qshare:sharedId': this.sharedId
|
||||
};
|
||||
}
|
||||
this.isDisabled = false;
|
||||
this.isFileShared = true;
|
||||
|
||||
@ -217,12 +223,7 @@ export class ShareDialogComponent implements OnInit, OnDestroy {
|
||||
private updateNode(date: moment.Moment): Observable<MinimalNodeEntryEntity> {
|
||||
return this.nodesApiService.updateNode(this.data.node.entry.id, {
|
||||
properties: {
|
||||
'qshare:expiryDate': date
|
||||
? date
|
||||
.utc()
|
||||
.endOf('day')
|
||||
.format()
|
||||
: null
|
||||
'qshare:expiryDate': date ? date.endOf('day') : null
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -230,6 +231,6 @@ export class ShareDialogComponent implements OnInit, OnDestroy {
|
||||
private updateEntryExpiryDate(date: moment.Moment) {
|
||||
const { properties } = this.data.node.entry;
|
||||
|
||||
properties['qshare:expiryDate'] = date ? date.local() : null;
|
||||
properties['qshare:expiryDate'] = date ? date.toDate() : null;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user